diff --git a/app/Classes/FTN/Message.php b/app/Classes/FTN/Message.php index a58e44b..a34cc61 100644 --- a/app/Classes/FTN/Message.php +++ b/app/Classes/FTN/Message.php @@ -84,8 +84,10 @@ class Message extends FTNBase public const FLAG_AUDITREQ = 1<<14; // (ARQ) /** @var int Requesting a file update (filename in subject) */ public const FLAG_FILEUPDATEREQ = 1<<15; // (URQ) - /** Echomail has been scanned out */ + /** @var int Echomail has been scanned out */ public const FLAG_ECHOMAIL = 1<<16; + /** @var int Use packet password on the subject line for this message */ + public const FLAG_PKTPASSWD = 1<<17; // FTS-0001.016 Message header 32 bytes node, net, flags, cost, date public const HEADER_LEN = 0x20; // Length of message header diff --git a/app/Classes/FTN/Packet.php b/app/Classes/FTN/Packet.php index a0b40a7..3387edb 100644 --- a/app/Classes/FTN/Packet.php +++ b/app/Classes/FTN/Packet.php @@ -368,8 +368,9 @@ class Packet extends FTNBase implements \Iterator, \Countable * * @param Address $oo * @param Address $o + * @param string|null $passwd Override the password used in the packet */ - public function addressHeader(Address $oo,Address $o): void + public function addressHeader(Address $oo,Address $o,string $passwd=NULL): void { Log::debug(sprintf('%s:+ Creating packet for [%s]',self::LOGKEY,$o->ftn)); @@ -393,7 +394,7 @@ class Packet extends FTNBase implements \Iterator, \Countable 'H' => $date->format('H'), // Hour 'M' => $date->format('i'), // Minute 'S' => $date->format('s'), // Second - 'password' => $o->session('pktpass'), // Packet Password + 'password' => (! is_null($passwd)) ? $passwd : $o->session('pktpass'), // Packet Password ]; } diff --git a/app/Classes/FTN/Process.php b/app/Classes/FTN/Process.php index fb2b209..d4a2cc7 100644 --- a/app/Classes/FTN/Process.php +++ b/app/Classes/FTN/Process.php @@ -2,17 +2,11 @@ namespace App\Classes\FTN; -use Illuminate\Support\Arr; - /** * Abstract class to hold the common functions for automatic responding to echomail/netmail messages */ abstract class Process { - private const LOGKEY = 'R--'; - - protected const MSG_WIDTH = 79; - /** * Return TRUE if the process class handled the message. * @@ -20,79 +14,4 @@ abstract class Process * @return bool */ abstract public static function handle(Message $msg): bool; - - /** - * This function will format text to static::MSG_WIDTH, as well as adding the logo. - */ - public static function format_msg(string $text,array $logo = []): string - { - $msg = utf8_decode(join("\r",static::msg_header()))."\r"; - $c = 0; - $offset = 0; - - while ($offset < strlen($text)) { - $ll = ''; - - // Add our logo - if ($cuser_from,$msg->fftn)); - $ftns = Setup::findOrFail(config('app.id'))->system->match($msg->fboss_o->zone)->first(); - $reply = sprintf("Your test was received here on %s and it looks like you sent it on %s. If that is correct, then it took %s to get here.\r", - Carbon::now()->utc()->toDateTimeString(), - $msg->date->utc()->toDateTimeString(), - $msg->date->diffForHumans(['parts'=>3,'syntax'=>CarbonInterface::DIFF_ABSOLUTE]) - ); - - $reply .= "\r"; - $reply .= "\r"; - $reply .= "------------------------------ BEGIN MESSAGE ------------------------------\r"; - $reply .= sprintf("TO: %s\r",$msg->user_to); - $reply .= sprintf("SUBJECT: %s\r",$msg->subject); - $reply .= str_replace("\r---","\r#--",$msg->message)."\r"; - $reply .= "------------------------------ CONTROL LINES ------------------------------\r"; - $reply .= sprintf("DATE: %s\r",$msg->date->utc()->format('Y-m-d H:i:s')); - $reply .= sprintf("MSGID: %s\r",$msg->msgid); - - foreach ($msg->kludge as $k=>$v) - $reply .= sprintf("@%s: %s\r",strtoupper($k),$v); - foreach ($msg->via as $via) - $reply .= sprintf("VIA: %s\r",$via); - - $reply .= "------------------------------ END MESSAGE ------------------------------\r"; - - $eo = Echoarea::where('name',$msg->echoarea)->single(); - - $o = new Echomail; - $o->init(); - $o->to = $msg->user_from; - $o->from = Setup::PRODUCT_NAME; - $o->subject = 'Test Reply'; - $o->datetime = Carbon::now(); - $o->tzoffset = $o->datetime->utcOffset(); - $o->echoarea_id = $eo?->id; - $o->replyid = $msg->msgid; - $o->fftn_id = $ftns->id; - - $o->flags = Message::FLAG_LOCAL; - $o->msg = static::format_msg($reply,self::$logo); - $o->tagline = 'I ate a clock yesterday, it was very time-consuming.'; - $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); - $o->origin = sprintf('%s (%s)',Setup::PRODUCT_NAME,$ftns->ftn4d); - $o->kludges = collect(['chrs'=>$msg->kludge->get('chrs') ?: 'CP437 2']); - $o->save(); + Notification::route('echomail',$msg->echoarea)->notify(new TestNotification($msg)); return TRUE; } diff --git a/app/Classes/FTN/Process/Netmail/Ping.php b/app/Classes/FTN/Process/Netmail/Ping.php index d128c69..04cb449 100644 --- a/app/Classes/FTN/Process/Netmail/Ping.php +++ b/app/Classes/FTN/Process/Netmail/Ping.php @@ -2,12 +2,11 @@ namespace App\Classes\FTN\Process\Netmail; -use Carbon\Carbon; -use Carbon\CarbonInterface; +use Illuminate\Support\Facades\Notification; use Illuminate\Support\Facades\Log; use App\Classes\FTN\{Message,Process}; -use App\Models\{Netmail,Setup}; +use App\Notifications\Netmails\Ping as PingNotification; /** * Process messages to Ping @@ -18,48 +17,14 @@ final class Ping extends Process { private const LOGKEY = 'RP-'; - private static array $logo = [ - 'ÚÄ¿þÚÄ¿ÚÄ¿', - '³ ³Â³ ³Àij', - 'ÃÄÙÁÁ ÁÄÄÙ' - ]; - public static function handle(Message $msg): bool { if (strtolower($msg->user_to) !== 'ping') return FALSE; Log::info(sprintf('%s:- Processing PING message from (%s) [%s]',self::LOGKEY,$msg->user_from,$msg->fftn)); - $ftns = Setup::findOrFail(config('app.id'))->system->match($msg->fftn_o->zone)->first(); - $reply = sprintf("Your ping was received here on %s and it looks like you sent it on %s. If that is correct, then it took %s to get here.\r", - Carbon::now()->utc()->toDateTimeString(), - $msg->date->utc()->toDateTimeString(), - $msg->date->diffForHumans(['parts'=>3,'syntax'=>CarbonInterface::DIFF_ABSOLUTE]) - ); - - $reply .= "\r"; - $reply .= "Your message travelled along this path on the way here:\r"; - foreach ($msg->via as $path) - $reply .= sprintf(" * %s\r",$path); - - $o = new Netmail; - $o->to = $msg->user_from; - $o->from = Setup::PRODUCT_NAME; - $o->subject = 'Ping Reply'; - $o->datetime = Carbon::now(); - $o->tzoffset = $o->datetime->utcOffset(); - - $o->replyid = $msg->msgid; - $o->fftn_id = $ftns->id; - $o->tftn_id = ($x=$msg->fftn_o) ? $x->id : NULL; - $o->flags = Message::FLAG_LOCAL|Message::FLAG_PRIVATE; - $o->cost = 0; - - $o->msg = static::format_msg($reply,self::$logo); - $o->tagline = 'My ping pong opponent was not happy with my serve. He kept returning it.'; - $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); - $o->save(); + Notification::route('netmail',$msg->fftn_o)->notify(new PingNotification($msg)); return TRUE; } diff --git a/app/Classes/File/Receive.php b/app/Classes/File/Receive.php index 1f1d16e..b1c1d47 100644 --- a/app/Classes/File/Receive.php +++ b/app/Classes/File/Receive.php @@ -3,9 +3,8 @@ namespace App\Classes\File; use Illuminate\Support\Arr; -use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; -use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\Notification; use Symfony\Component\HttpFoundation\File\Exception\FileException; use App\Classes\{File,Protocol}; @@ -13,6 +12,7 @@ use App\Classes\FTN\{InvalidPacketException,Packet}; use App\Exceptions\FileGrewException; use App\Jobs\{MessageProcess,TicProcess}; use App\Models\Address; +use App\Notifications\Netmails\PacketPasswordInvalid; /** * Object representing the files we are receiving @@ -138,10 +138,10 @@ class Receive extends Base } // Check the packet password - if ($this->ao->session('pktpass') != $po->password) { + if ($this->ao->session('pktpass') !== $po->password) { Log::error(sprintf('%s:! Packet from [%s] with password [%s] is invalid.',self::LOGKEY,$this->ao->ftn,$po->password)); - // @todo Generate message to system advising invalid password - that message should be sent without a packet password! + Notification::route('netmail',$this->ao)->notify(new PacketPasswordInvalid($po->password,$this->receiving->nameas)); break; } @@ -158,6 +158,20 @@ class Receive extends Base // @todo Quick check that the packet should be processed by us. // @todo validate that the packet's zone is in the domain. + /* + * // @todo generate exception when echomail for an area that doesnt exist + * // @todo generate exception when echomail for an area sender cannot post to + * // @todo generate exception when echomail for an area sender not subscribed to + * // @todo generate exception when echomail comes from a system not defined here + * // @todo generate exception when echomail comes from a system doesnt exist + * + * // @todo generate exception when netmail to system that doesnt exist (node/point) + * // @todo generate exception when netmail from system that doesnt exist (node/point) + * // @todo generate warning when netmail comes from a system not defined here + * + * // @todo generate exception when packet has wrong password + */ + try { // Dispatch job. if ($queue) diff --git a/app/Console/Commands/NetmailTest.php b/app/Console/Commands/NetmailTest.php index 10cd260..63e249e 100644 --- a/app/Console/Commands/NetmailTest.php +++ b/app/Console/Commands/NetmailTest.php @@ -6,7 +6,7 @@ use Illuminate\Console\Command; use Illuminate\Support\Facades\Notification; use App\Models\Address; -use App\Notifications\NetmailTest as NetmailTestNotification; +use App\Notifications\Netmails\Test as NetmailTestNotification; class NetmailTest extends Command { @@ -35,6 +35,6 @@ class NetmailTest extends Command { $ao = Address::findFTN($this->argument('ftn')); - Notification::route('netmail',$ao)->notify(new NetmailTestNotification($ao)); + Notification::route('netmail',$ao)->notify(new NetmailTestNotification()); } } \ No newline at end of file diff --git a/app/Console/Commands/UserCodeSend.php b/app/Console/Commands/UserCodeSend.php index 0d65b3f..5988e76 100644 --- a/app/Console/Commands/UserCodeSend.php +++ b/app/Console/Commands/UserCodeSend.php @@ -6,7 +6,7 @@ use Illuminate\Console\Command; use Illuminate\Support\Facades\Notification; use App\Models\{Address,User}; -use App\Notifications\AddressLink; +use App\Notifications\Netmails\AddressLink; class UserCodeSend extends Command { @@ -27,6 +27,6 @@ class UserCodeSend extends Command $ao = Address::findFTN($this->argument('ftn')); $uo = User::where('email',$this->argument('email'))->singleOrFail(); - Notification::route('netmail',$ao->parent())->notify(new AddressLink($ao,$uo)); + Notification::route('netmail',$ao->parent())->notify(new AddressLink($uo)); } } \ No newline at end of file diff --git a/app/Http/Controllers/SystemController.php b/app/Http/Controllers/SystemController.php index 98a9238..efc4ee9 100644 --- a/app/Http/Controllers/SystemController.php +++ b/app/Http/Controllers/SystemController.php @@ -3,9 +3,9 @@ namespace App\Http\Controllers; use Carbon\Carbon; -use Illuminate\Support\Collection; use Illuminate\Http\Request; use Illuminate\Support\Arr; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Notification; @@ -13,7 +13,7 @@ use Illuminate\Support\ViewErrorBag; use App\Http\Requests\SystemRegister; use App\Models\{Address,Echoarea,Filearea,Setup,System,SystemZone,Zone}; -use App\Notifications\AddressLink; +use App\Notifications\Netmails\AddressLink; use App\Rules\{FidoInteger,TwoByteInteger}; class SystemController extends Controller @@ -654,7 +654,7 @@ class SystemController extends Controller } if ($ca->count() && $la=$ca->pop()) - Notification::route('netmail',$la)->notify(new AddressLink($la,Auth::user())); + Notification::route('netmail',$la)->notify(new AddressLink(Auth::user())); return view('user.system.register_send') ->with('la',$la) @@ -682,7 +682,7 @@ class SystemController extends Controller // If we have addresses, we'll trigger the routed netmail if ($validate->count()) - Notification::route('netmail',$x=$validate->first())->notify(new AddressLink($x,Auth::user())); + Notification::route('netmail',$validate->first())->notify(new AddressLink(Auth::user())); return view('user.system.widget.register_send') ->with('validate',$validate) diff --git a/app/Jobs/MessageProcess.php b/app/Jobs/MessageProcess.php index f25b7c9..958d89b 100644 --- a/app/Jobs/MessageProcess.php +++ b/app/Jobs/MessageProcess.php @@ -9,9 +9,11 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Notification; -use App\Classes\FTN\{Message,Process}; +use App\Classes\FTN\Message; use App\Models\{Address,Echoarea,Echomail,Netmail,Setup}; +use App\Notifications\Netmails\Reject; class MessageProcess implements ShouldQueue { @@ -83,7 +85,29 @@ class MessageProcess implements ShouldQueue // @todo Enable checks to see if this is a file request or file send - $o = $this->create_netmail($this->msg); + $o = new Netmail; + $o->to = $this->msg->user_to; + $o->from = $this->msg->user_from; + + $o->fftn_id = ($x=$this->msg->fftn_o) ? $x->id : NULL; + $o->tftn_id = ($x=$this->msg->tftn_o) ? $x->id : NULL; + + $o->datetime = $this->msg->date; + $o->tzoffset = $this->msg->date->utcOffset(); + + $o->flags = $this->msg->flags; + $o->cost = $this->msg->cost; + $o->msgid = $this->msg->msgid; + + $o->subject = $this->msg->subject; + $o->msg = $this->msg->message; + + foreach ($this->msg->via as $v) + $o->msg .= sprintf("\01Via %s\r",$v); + + $o->msg_src = $this->msg->message_src; + $o->msg_crc = md5($this->msg->message); + $o->set_pkt = $this->packet; $o->set_sender = $this->sender; $o->set_path = $this->msg->pathaddress; @@ -133,52 +157,9 @@ class MessageProcess implements ShouldQueue // If not processed, no users here! if (! $processed) { - $reject = [ - 'ÚÄ¿ÚÄ¿ ÂÚÄ¿ÚÄ¿Ú¿', - '³ ³ÄÙ ³³ÄÙ³ ³ ', - 'Á ÀÄÙÀÄÙÀÄÙÀÄÙ Á ' - ]; - Log::alert(sprintf('%s:! Netmail to the Hub from (%s) [%s] but no users here.',self::LOGKEY,$this->msg->user_from,$this->msg->fftn)); - $reply = "Your Netmail was not processed by the hub and cannot be delivered to anybody (as there are no users here).\r"; - - $reply .= "\r"; - $reply .= "\r"; - $reply .= "This is your original message:\r"; - $reply .= "------------------------------ BEGIN MESSAGE ------------------------------\r"; - $reply .= sprintf("TO: %s\r",$this->msg->user_to); - $reply .= sprintf("SUBJECT: %s\r",$this->msg->subject); - $reply .= str_replace("\r---","\r#--",$this->msg->message)."\r"; - $reply .= "------------------------------ CONTROL LINES ------------------------------\r"; - $reply .= sprintf("DATE: %s\r",$this->msg->date->format('Y-m-d H:i:s')); - $reply .= sprintf("MSGID: %s\r",$this->msg->msgid); - - foreach ($this->msg->kludge as $k=>$v) - $reply .= sprintf("@%s: %s\r",strtoupper($k),$v); - foreach ($this->msg->via as $via) - $reply .= sprintf("VIA: %s\r",$via); - - $reply .= "------------------------------ END MESSAGE ------------------------------\r"; - - $o = new Netmail; - $o->to = $this->msg->user_from; - $o->from = Setup::PRODUCT_NAME; - $o->subject = 'Message Undeliverable - '.$this->msg->msgid; - $o->datetime = $this->msg->date; - $o->tzoffset = $this->msg->date->utcOffset(); - - $o->cost = 0; - $o->flags = Message::FLAG_LOCAL|Message::FLAG_PRIVATE; - - $o->fftn_id = ($x=$this->msg->tftn_o) ? $x->id : NULL; - $o->tftn_id = ($x=$this->msg->fftn_o) ? $x->id : NULL; - $o->replyid = $this->msg->msgid; - $o->msg = Process::format_msg($reply,$reject); - - $o->tagline = 'Do you think it was fate which brought us together? Nah, bad luck :('; - $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); - $o->save(); + Notification::route('netmail',$this->msg->fftn_o)->notify(new Reject($this->msg)); } // If in transit, store for collection @@ -319,32 +300,4 @@ class MessageProcess implements ShouldQueue } } } - - private function create_netmail(Message $msg): Netmail - { - $o = new Netmail; - $o->to = $msg->user_to; - $o->from = $msg->user_from; - - $o->fftn_id = ($x=$msg->fftn_o) ? $x->id : NULL; - $o->tftn_id = ($x=$msg->tftn_o) ? $x->id : NULL; - - $o->datetime = $msg->date; - $o->tzoffset = $msg->date->utcOffset(); - - $o->flags = $msg->flags; - $o->cost = $msg->cost; - $o->msgid = $msg->msgid; - - $o->subject = $msg->subject; - $o->msg = $msg->message; - - foreach ($msg->via as $v) - $o->msg .= sprintf("\01Via %s\r",$v); - - $o->msg_src = $msg->message_src; - $o->msg_crc = md5($msg->message); // @todo DB schema needs to handle this - - return $o; - } } \ No newline at end of file diff --git a/app/Models/Address.php b/app/Models/Address.php index 6624676..8cc695c 100644 --- a/app/Models/Address.php +++ b/app/Models/Address.php @@ -619,6 +619,23 @@ class Address extends Model $s = Setup::findOrFail(config('app.id')); + if (($x=$this->netmailAlertWaiting())->count()) { + Log::debug(sprintf('%s:= Packaging [%d] netmail alerts to [%s]',self::LOGKEY,$x->count(),$this->ftn)); + $passpos = strpos($x->last()->subject,':'); + + if ($passpos > 8) + Log::alert(sprintf('%s:! Password would be greater than 8 chars? [%d]',self::LOGKEY,$passpos)); + + $pkt = $this->getPacket($x,substr($x->last()->subject,0,$passpos)); + + if ($pkt && $pkt->count() && $update) + DB::table('netmails') + ->whereIn('id',$x->pluck('id')) + ->update(['sent_pkt'=>$pkt->name]); + + return $pkt; + } + if (($x=$this->netmailWaiting()) ->count()) { @@ -644,9 +661,10 @@ class Address extends Model * Return a packet of mail * * @param Collection $msgs of message models (Echomail/Netmail) + * @param string|null $passwd Override password used in packet * @return Packet|null */ - public function getPacket(Collection $msgs): ?Packet + public function getPacket(Collection $msgs,string $passwd=NULL): ?Packet { $s = Setup::findOrFail(config('app.id')); $ao = $s->system->match($this->zone)->first(); @@ -658,7 +676,7 @@ class Address extends Model // Get packet type $type = collect(Packet::PACKET_TYPES)->get($this->system->pkt_type ?: config('app.default_pkt')); $o = new $type; - $o->addressHeader($ao,$this); + $o->addressHeader($ao,$this,$passwd); // $oo = Netmail/Echomail Model $c = 0; @@ -667,7 +685,7 @@ class Address extends Model if (++$c > $s->msgs_pkt) break; - $o->addMail($oo->packet($this)); + $o->addMail($oo->packet($this,$passwd)); } return $o; @@ -690,6 +708,21 @@ class Address extends Model ->get(); } + /** + * Netmail alerts waiting to be sent to this system + * + * @return Collection + */ + public function netmailAlertWaiting(): Collection + { + return Netmail::where('tftn_id',$this->id) + ->whereRaw(sprintf('(flags & %d) > 0',Message::FLAG_LOCAL)) + ->whereRaw(sprintf('(flags & %d) > 0',Message::FLAG_PKTPASSWD)) + ->whereRaw(sprintf('(flags & %d) = 0',Message::FLAG_SENT)) + ->whereNull('sent_at') + ->get(); + } + /** * * Parse a string and split it out as an FTN array diff --git a/app/Models/Netmail.php b/app/Models/Netmail.php index 83da0dd..f3dee4c 100644 --- a/app/Models/Netmail.php +++ b/app/Models/Netmail.php @@ -130,7 +130,7 @@ final class Netmail extends Model implements Packet /** * Return this model as a packet */ - public function packet(Address $ao): Message + public function packet(Address $ao,string $strippass=NULL): Message { Log::debug(sprintf('%s:+ Bundling [%s]',self::LOGKEY,$this->id)); @@ -153,7 +153,7 @@ final class Netmail extends Model implements Packet $o->tzutc = $this->datetime->utcOffset($this->tzoffset)->getOffsetString(''); $o->user_to = $this->to; $o->user_from = $this->from; - $o->subject = $this->subject; + $o->subject = (! is_null($strippass)) ? preg_replace('/^'.$strippass.':/','',$this->subject) : $this->subject; // INTL kludge $o->intl = sprintf('%s %s',$this->tftn->ftn3d,$this->fftn->ftn3d); diff --git a/app/Notifications/AddressLink.php b/app/Notifications/AddressLink.php deleted file mode 100644 index cafbd71..0000000 --- a/app/Notifications/AddressLink.php +++ /dev/null @@ -1,104 +0,0 @@ -queue = 'netmail'; - $this->ao = $ao; - $this->uo = $uo; - } - - /** - * Get the notification's delivery channels. - * - * @param mixed $notifiable - * @return array - */ - public function via($notifiable) - { - return ['netmail']; - } - - /** - * Get the mail representation of the notification. - * - * @param mixed $notifiable - * @return Netmail - * @throws \Exception - */ - public function toNetmail($notifiable): Netmail - { - Log::info(sprintf('%s:Sending a link code for address [%s]',self::LOGKEY,$this->ao->ftn)); - - $so = Setup::findOrFail(config('app.id'))->system; - - $o = new Netmail; - $o->to = $this->ao->system->sysop; - $o->from = Setup::PRODUCT_NAME; - $o->subject = 'Address Link Code'; - $o->datetime = Carbon::now(); - $o->tzoffset = $o->datetime->utcOffset(); - - $o->fftn_id = $so->match($this->ao->zone)->first()->id; - $o->tftn_id = $this->ao->id; - $o->flags = Message::FLAG_LOCAL|Message::FLAG_PRIVATE|Message::FLAG_CRASH; - $o->cost = 0; - - $o->tagline = 'Address Linking...'; - $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); - - // Message - $msg = new Page; - $msg->addLogo(new ANSI(base_path('public/logo/netmail.bin'))); - - $header = new Thick; - $header->addText(ANSI::ansi_code([1,37]).'Clearing Houz'); - $msg->addHeader($header,'FTN Mailer and Tosser',TRUE,0xc4); - - $lbc = new Thin; - $lbc->addText('#link'); - $msg->addLeftBoxContent($lbc); - - $msg->addText(sprintf( - "Hi %s,\r\r". - "This message is to link your address [%s] to your user ID in the Clearing Houz web site.\r\r". - "If you didnt start this process, then you can safely ignore this netmail. But if you wanted to link this address, please head over to [%s] and paste in the following:\r\r%s\r", - $this->ao->system->sysop, - $this->ao->ftn3d, - url('/link'), - $this->ao->set_activation($this->uo) - )); - - $o->msg = $msg->render(); - $o->save(); - - return $o; - } -} \ No newline at end of file diff --git a/app/Notifications/Channels/EchomailChannel.php b/app/Notifications/Channels/EchomailChannel.php new file mode 100644 index 0000000..bbf027c --- /dev/null +++ b/app/Notifications/Channels/EchomailChannel.php @@ -0,0 +1,47 @@ +echomail = $o; + } + + /** + * Send the given notification. + * + * @param mixed $notifiable + * @param \Illuminate\Notifications\Notification $notification + * @return \Psr\Http\Message\ResponseInterface|void + */ + public function send($notifiable,Notification $notification) + { + if (! $echoarea = $notifiable->routeNotificationFor('echomail',$notification)) + return; + + $so = Setup::findOrFail(config('app.id'))->system; + $o = $notification->toEchomail($so,$notifiable); + + Log::info(sprintf('%s:= Posted echomail [%s] to [%s]',self::LOGKEY,$o->msgid,$echoarea)); + } +} \ No newline at end of file diff --git a/app/Notifications/Channels/NetmailChannel.php b/app/Notifications/Channels/NetmailChannel.php index 4b07d39..3294452 100644 --- a/app/Notifications/Channels/NetmailChannel.php +++ b/app/Notifications/Channels/NetmailChannel.php @@ -5,22 +5,21 @@ namespace App\Notifications\Channels; use Illuminate\Notifications\Notification; use Illuminate\Support\Facades\Log; -use App\Models\Netmail; use App\Jobs\AddressPoll as Job; +use App\Models\Netmail; +use App\Models\Setup; class NetmailChannel { private const LOGKEY = 'CN-'; /** - * The HTTP client instance. - * * @var Netmail */ protected Netmail $netmail; /** - * Create a new Slack channel instance. + * Create a new Netmail channel instance. * * @param Netmail $o */ @@ -41,9 +40,10 @@ class NetmailChannel if (! $ao = $notifiable->routeNotificationFor('netmail',$notification)) return; - $o = $notification->toNetmail($notifiable); + $so = Setup::findOrFail(config('app.id'))->system; + $o = $notification->toNetmail($so,$notifiable); Job::dispatch($ao); - Log::info(sprintf('%s:Sent netmail [%s] via [%s]',self::LOGKEY,$o->msgid,$ao->ftn)); + Log::info(sprintf('%s:= Sent netmail [%s] to [%s]',self::LOGKEY,$o->msgid,$ao->ftn)); } } \ No newline at end of file diff --git a/app/Notifications/Echomails.php b/app/Notifications/Echomails.php new file mode 100644 index 0000000..e114418 --- /dev/null +++ b/app/Notifications/Echomails.php @@ -0,0 +1,73 @@ +queue = 'echomail'; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return [ self::via ]; + } + + /** + * Get the mail representation of the notification. + * + * @param System $so + * @param mixed $notifiable + * @return Echomail + * @throws \Exception + */ + abstract public function toEchomail(System $so,object $notifiable): Echomail; + + protected function setupEchomail(Message $mo,System $so,object $notifiable): Echomail + { + $echoarea = $notifiable->routeNotificationFor(static::via); + $eo = Echoarea::where('name',$echoarea)->singleOrFail(); + + $o = new Echomail; + $o->init(); + $o->from = Setup::PRODUCT_NAME; + $o->replyid = $mo->msgid; + $o->echoarea_id = $eo->id; + + $o->datetime = Carbon::now(); + $o->tzoffset = $o->datetime->utcOffset(); + + $o->fftn_id = ($x=$so->match($mo->fftn_o->zone)->first())->id; + $o->flags = (Message::FLAG_LOCAL); + + $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); + $o->origin = sprintf('%s (%s)',Setup::PRODUCT_NAME,$x->ftn4d); + $o->kludges = collect(['chrs'=>$mo->kludge->get('chrs') ?: 'CP437 2']); + + return $o; + } +} \ No newline at end of file diff --git a/app/Notifications/Echomails/Test.php b/app/Notifications/Echomails/Test.php new file mode 100644 index 0000000..19dd38d --- /dev/null +++ b/app/Notifications/Echomails/Test.php @@ -0,0 +1,80 @@ +mo = $mo; + } + + /** + * Get the mail representation of the notification. + * + * @param System $so + * @param mixed $notifiable + * @return Echomail + * @throws \Exception + */ + public function toEchomail(System $so,object $notifiable): Echomail + { + $o = $this->setupEchomail($this->mo,$so,$notifiable); + $echoarea = $notifiable->routeNotificationFor(static::via); + + Log::info(sprintf('%s:+ Creating test echomail to [%s]',self::LOGKEY,$echoarea)); + + $o->to = $this->mo->user_from; + $o->subject = 'Test Reply'; + + // Message + $msg = new Page; + + $header = new Thick; + $header->addText('Clearing Houz'); + $msg->addHeader($header,'FTN Mailer and Tosser',TRUE,0xc4); + + $lbc = new Thin; + $lbc->addText('Test'); + $msg->addLeftBoxContent($lbc,TRUE); + + $msg->addText( + sprintf("Your test was received here on %s and it looks like you sent it on %s. If that is correct, then it took %s to get here.\r\r", + Carbon::now()->utc()->toDateTimeString(), + $this->mo->date->utc()->toDateTimeString(), + $this->mo->date->diffForHumans(['parts'=>3,'syntax'=>CarbonInterface::DIFF_ABSOLUTE]) + ) + ); + + $msg->addText($this->message_path($this->mo)); + + $o->msg = $msg->render(); + $o->tagline = 'I ate a clock yesterday, it was very time-consuming.'; + + $o->save(); + + return $o; + } +} \ No newline at end of file diff --git a/app/Notifications/NetmailTest.php b/app/Notifications/NetmailTest.php deleted file mode 100644 index 63eaac6..0000000 --- a/app/Notifications/NetmailTest.php +++ /dev/null @@ -1,97 +0,0 @@ -queue = 'netmail'; - $this->ao = $ao; - } - - /** - * Get the notification's delivery channels. - * - * @param mixed $notifiable - * @return array - */ - public function via($notifiable) - { - return ['netmail']; - } - - /** - * Get the mail representation of the notification. - * - * @param mixed $notifiable - * @return Netmail - * @throws \Exception - */ - public function toNetmail($notifiable): Netmail - { - Log::info(sprintf('%s:Creating test netmail to [%s]',self::LOGKEY,$this->ao->ftn)); - - $so = Setup::findOrFail(config('app.id'))->system; - - $o = new Netmail; - $o->to = $this->ao->system->sysop; - $o->from = Setup::PRODUCT_NAME; - $o->subject = 'Testing 1, 2, 3...'; - $o->datetime = Carbon::now(); - $o->tzoffset = $o->datetime->utcOffset(); - - $o->fftn_id = $so->match($this->ao->zone)->first()->id; - $o->tftn_id = $this->ao->id; - $o->flags = Message::FLAG_LOCAL|Message::FLAG_PRIVATE; - $o->cost = 0; - - $o->tagline = 'Testing, testing, 1 2 3.'; - $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); - - // Message - $msg = new Page; - $msg->addLogo(new ANSI('public/logo/netmail.bin')); - - $header = new Thick; - $header->addText(ANSI::ansi_code([1,37]).'Clearing Houz'); - $msg->addHeader($header,'FTN Mailer and Tosser',TRUE,0xc4); - - $lbc = new Thin; - $lbc->addText('Test'); - $msg->addLeftBoxContent($lbc); - - $msg->addText( - "Hi there,\r\r". - "This is just a test netmail to make sure we can send a message to your system.\r\r". - "There is no need to reply, but if you do, it'll boost my spirits :)\r" - ); - - $o->msg = $msg->render(); - $o->save(); - - return $o; - } -} \ No newline at end of file diff --git a/app/Notifications/Netmails.php b/app/Notifications/Netmails.php new file mode 100644 index 0000000..a930319 --- /dev/null +++ b/app/Notifications/Netmails.php @@ -0,0 +1,70 @@ +queue = 'netmail'; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return [ self::via ]; + } + + /** + * Get the mail representation of the notification. + * + * @param System $so + * @param mixed $notifiable + * @return Netmail + * @throws \Exception + */ + abstract public function toNetmail(System $so,object $notifiable): Netmail; + + protected function setupNetmail(System $so,object $notifiable): Netmail + { + $ao = $notifiable->routeNotificationFor(static::via); + + $o = new Netmail; + $o->to = $ao->system->sysop; + $o->from = Setup::PRODUCT_NAME; + + $o->datetime = Carbon::now(); + $o->tzoffset = $o->datetime->utcOffset(); + + $o->fftn_id = $so->match($ao->zone)->first()->id; + $o->tftn_id = $ao->id; + $o->flags = (Message::FLAG_LOCAL|Message::FLAG_PRIVATE); + $o->cost = 0; + + $o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID); + + return $o; + } +} \ No newline at end of file diff --git a/app/Notifications/Netmails/AddressLink.php b/app/Notifications/Netmails/AddressLink.php new file mode 100644 index 0000000..d22c277 --- /dev/null +++ b/app/Notifications/Netmails/AddressLink.php @@ -0,0 +1,69 @@ +uo = $uo; + } + + /** + * Get the mail representation of the notification. + * + * @param System $so + * @param mixed $notifiable + * @return Netmail + * @throws \Exception + */ + public function toNetmail(System $so,object $notifiable): Netmail + { + $o = $this->setupNetmail($so,$notifiable); + $ao = $notifiable->routeNotificationFor(static::via); + + Log::info(sprintf('%s:+ Sending a link code for address [%s]',self::LOGKEY,$ao->ftn)); + + $o->subject = 'Address Link Code'; + $o->flags = (Message::FLAG_LOCAL|Message::FLAG_PRIVATE|Message::FLAG_CRASH); + + // Message + $msg = $this->page(TRUE,'#link'); + + $msg->addText(sprintf( + "Hi %s,\r\r". + "This message is to link your address [%s] to your user ID in the Clearing Houz web site.\r\r". + "If you didnt start this process, then you can safely ignore this netmail. But if you wanted to link this address, please head over to [%s] and paste in the following:\r\r%s\r", + $ao->system->sysop, + $ao->ftn3d, + url('/link'), + $ao->set_activation($this->uo) + )); + + $o->msg = $msg->render(); + $o->tagline = 'Address Linking...'; + + $o->save(); + + return $o; + } +} \ No newline at end of file diff --git a/app/Notifications/Netmails/PacketPasswordInvalid.php b/app/Notifications/Netmails/PacketPasswordInvalid.php new file mode 100644 index 0000000..a1dbe27 --- /dev/null +++ b/app/Notifications/Netmails/PacketPasswordInvalid.php @@ -0,0 +1,80 @@ +invalidpass = $invalidpass; + $this->packet = $packet; + } + + /** + * Get the mail representation of the notification. + */ + public function toNetmail(System $so,object $notifiable): Netmail + { + $o = $this->setupNetmail($so,$notifiable); + $ao = $notifiable->routeNotificationFor(static::via); + + Log::info(sprintf('%s:+ Creating netmail to [%s] - system using invalid packet password',self::LOGKEY,$ao->ftn)); + + $o->subject = $this->invalidpass.':Incorrect Packet Password'; + $o->flags = (Message::FLAG_LOCAL|Message::FLAG_PRIVATE|Message::FLAG_PKTPASSWD|Message::FLAG_CRASH); + + // Message + $msg = $this->page(TRUE,'badpass'); + + if ($this->invalidpass) + $msg->addText( + sprintf("Hi there,\r\r". + "You sent me a mail packet (%s) with the incorrect password \"%s\". It wasnt processed.\r\r" + ,$this->packet,$this->invalidpass)); + else + $msg->addText( + sprintf("Hi there,\r\r". + "You sent me a mail packet (%s) with no password? It wasnt processed.\r\r" + ,$this->packet)); + + $msg->addText("Head over to the website if you dont know what your packet password should be :)\r"); + + $o->msg = $msg->render(); + $o->tagline = 'Safety first, password second.'; + + $o->save(); + + return $o; + } + + /** + * Get the array representation of the notification. + * + * @return array + */ + public function toArray(object $notifiable): array + { + return [ + // + ]; + } +} \ No newline at end of file diff --git a/app/Notifications/Netmails/Ping.php b/app/Notifications/Netmails/Ping.php new file mode 100644 index 0000000..4ae18ff --- /dev/null +++ b/app/Notifications/Netmails/Ping.php @@ -0,0 +1,73 @@ +mo = $mo; + } + + /** + * Get the mail representation of the notification. + * + * @param System $so + * @param mixed $notifiable + * @return Netmail + * @throws \Exception + */ + public function toNetmail(System $so,object $notifiable): Netmail + { + $o = $this->setupNetmail($so,$notifiable); + $ao = $notifiable->routeNotificationFor(static::via); + + Log::info(sprintf('%s:+ Creating test netmail to [%s]',self::LOGKEY,$ao->ftn)); + + $o->to = $this->mo->user_from; + $o->replyid = $this->mo->msgid; + $o->subject = 'Ping Reply'; + + // Message + $msg = $this->page(FALSE,'Ping'); + + $msg->addText( + sprintf("Your ping was received here on %s and it looks like you sent it on %s. If that is correct, then it took %s to get here.\r\r", + Carbon::now()->utc()->toDateTimeString(), + $this->mo->date->utc()->toDateTimeString(), + $this->mo->date->diffForHumans(['parts'=>3,'syntax'=>CarbonInterface::DIFF_ABSOLUTE]) + ) + ); + + $msg->addText($this->message_path($this->mo)); + + $o->msg = $msg->render(); + $o->tagline = 'My ping pong opponent was not happy with my serve. He kept returning it.'; + + $o->save(); + + return $o; + } +} \ No newline at end of file diff --git a/app/Notifications/Netmails/Reject.php b/app/Notifications/Netmails/Reject.php new file mode 100644 index 0000000..eb3cd7e --- /dev/null +++ b/app/Notifications/Netmails/Reject.php @@ -0,0 +1,75 @@ +mo = $mo; + } + + /** + * Get the mail representation of the notification. + * + * @param System $so + * @param mixed $notifiable + * @return Netmail + * @throws \Exception + */ + public function toNetmail(System $so,object $notifiable): Netmail + { + $o = $this->setupNetmail($so,$notifiable); + $ao = $notifiable->routeNotificationFor(static::via); + + Log::info(sprintf('%s:+ Creating reject netmail to [%s]',self::LOGKEY,$ao->ftn)); + + $o->to = $this->mo->user_from; + $o->replyid = $this->mo->msgid; + $o->subject = 'Message Undeliverable - '.$this->mo->msgid; + + // Message + $msg = $this->page(FALSE,'Reject'); + + $msg->addText( + sprintf("Your netmail with ID [%s] to [%s] here was received here on [%s] and it looks like you sent it on [%s].\r\r", + $this->mo->msgid, + $this->mo->user_to, + Carbon::now()->utc()->toDateTimeString(), + $this->mo->date->utc()->toDateTimeString(), + ) + ); + + $msg->addText("This hub is not attended, so no user will be able to read your message (the hub is unattended). You may like to try and contact them another way.\r\r"); + + $msg->addText($this->message_path($this->mo)); + + $o->msg = $msg->render(); + $o->tagline = 'Do you think it was fate which brought us together? Nah, bad luck :('; + + $o->save(); + + return $o; + } +} \ No newline at end of file diff --git a/app/Notifications/Netmails/Test.php b/app/Notifications/Netmails/Test.php new file mode 100644 index 0000000..23ec3fc --- /dev/null +++ b/app/Notifications/Netmails/Test.php @@ -0,0 +1,50 @@ +setupNetmail($so,$notifiable); + $ao = $notifiable->routeNotificationFor(static::via); + + Log::info(sprintf('%s:+ Creating test netmail to [%s]',self::LOGKEY,$ao->ftn)); + + $o->subject = 'Testing 1, 2, 3...'; + + // Message + $msg = $this->page(TRUE,'Test'); + + $msg->addText( + "Hi there,\r\r". + "This is just a test netmail to make sure we can send a message to your system.\r\r". + "There is no need to reply, but if you do, it'll boost my spirits :)\r" + ); + + $o->msg = $msg->render(); + $o->tagline = 'Testing, testing, 1 2 3.'; + + $o->save(); + + return $o; + } +} \ No newline at end of file diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index fbe3d27..c00eae8 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -6,8 +6,8 @@ use Illuminate\Notifications\ChannelManager; use Illuminate\Support\Facades\Notification; use Illuminate\Support\ServiceProvider; -use App\Notifications\Channels\NetmailChannel; -use App\Models\Netmail; +use App\Notifications\Channels\{EchomailChannel,NetmailChannel}; +use App\Models\{Echomail,Netmail}; use App\Traits\SingleOrFail; class AppServiceProvider extends ServiceProvider @@ -22,6 +22,10 @@ class AppServiceProvider extends ServiceProvider public function register() { Notification::resolved(function (ChannelManager $service) { + $service->extend('echomail', function ($app) { + return new EchomailChannel($app->make(Echomail::class)); + }); + $service->extend('netmail', function ($app) { return new NetmailChannel($app->make(Netmail::class)); }); diff --git a/app/Traits/MessagePath.php b/app/Traits/MessagePath.php new file mode 100644 index 0000000..212d46b --- /dev/null +++ b/app/Traits/MessagePath.php @@ -0,0 +1,49 @@ +user_to); + $reply .= sprintf("SUBJECT: %s\r",$mo->subject); + $reply .= str_replace("\r---","\r#--",$mo->message)."\r"; + + $reply .= "+--[ CONTROL LINES ]----------------------------------+\r"; + $reply .= sprintf("DATE: %s\r",$mo->date->format('Y-m-d H:i:s')); + $reply .= sprintf("MSGID: %s\r",$mo->msgid); + + foreach ($mo->kludge as $k=>$v) + $reply .= sprintf("@%s: %s\r",strtoupper($k),$v); + + $reply .= "+--[ PATH ]-------------------------------------------+\r"; + + if ($mo->isNetmail()) { + if ($mo->via->count()) + foreach ($mo->via as $via) + $reply .= sprintf("VIA: %s\r",$via); + else + $reply .= "No path information? This would be normal if this message came directly to the hub\r"; + + } else { + if ($mo->path->count()) + foreach ($mo->path as $via) + $reply .= sprintf("VIA: %s\r",$via); + else + $reply .= "No path information? This would be normal if this message came directly to the hub\r"; + } + + $reply .= "+--[ END MESSAGE ]------------------------------------+\r"; + + return $reply; + } +} \ No newline at end of file diff --git a/app/Traits/PageTemplate.php b/app/Traits/PageTemplate.php new file mode 100644 index 0000000..4e644c8 --- /dev/null +++ b/app/Traits/PageTemplate.php @@ -0,0 +1,31 @@ +addLogo(new ANSI('public/logo/netmail.bin')); + + $header = new Thick; + $header->addText('Clearing Houz'); + $page->addHeader($header,'FTN Mailer and Tosser',TRUE,0xc4); + + if ($leftbox) { + $lbc = new Thin; + $lbc->addText($leftbox); + $page->addLeftBoxContent($lbc); + } + + return $page; + } +} \ No newline at end of file diff --git a/database/migrations/2023_07_21_162133_flags_increase_int.php b/database/migrations/2023_07_21_162133_flags_increase_int.php new file mode 100644 index 0000000..fa350e7 --- /dev/null +++ b/database/migrations/2023_07_21_162133_flags_increase_int.php @@ -0,0 +1,25 @@ +