clrghouz/app/Jobs/PacketProcess.php

213 lines
7.4 KiB
PHP
Raw Permalink Normal View History

2023-09-13 10:58:22 +00:00
<?php
namespace App\Jobs;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\UnableToMoveFile;
2023-09-13 10:58:22 +00:00
use App\Classes\File;
use App\Classes\FTN\Packet;
use App\Exceptions\InvalidPacketException;
use App\Models\{Echomail,Netmail,System};
2024-11-20 06:31:11 +00:00
use App\Notifications\Netmails\{PacketPasswordInvalid,UnexpectedPacketFromYou};
2023-09-13 10:58:22 +00:00
class PacketProcess implements ShouldQueue
{
private const LOGKEY = 'JPP';
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private string $filename;
private System $so;
2023-09-13 10:58:22 +00:00
private Carbon $rcvd_time;
private bool $interactive;
private bool $nobot;
2023-09-13 10:58:22 +00:00
public function __construct(string $filename,System $so,bool $interactive=TRUE,Carbon $rcvd_time=NULL,bool $nobot=FALSE)
2023-09-13 10:58:22 +00:00
{
$this->filename = $filename;
$this->so = $so->withoutRelations();
$this->interactive = $interactive;
$this->rcvd_time = $rcvd_time ?: Carbon::now();
$this->nobot = $nobot;
2023-09-13 10:58:22 +00:00
}
public function __get($key): mixed
{
switch ($key) {
case 'jobname':
return $this->filename;
2023-09-13 10:58:22 +00:00
default:
return NULL;
}
}
/**
* When calling MessageProcess - we assume that the packet is from a valid source, and
* the destination (netmail/echomail) is also valid
*/
public function handle()
{
Log::info(sprintf('%s:- Processing mail [%s]',self::LOGKEY,$this->filename));
2023-09-13 10:58:22 +00:00
$fs = Storage::disk(config('fido.local_disk'));
// @todo Catch files that we cannot process, eg: ARJ bundles.
2023-09-13 10:58:22 +00:00
try {
$f = new File($fs->path($this->filename));
2023-09-13 10:58:22 +00:00
$processed = FALSE;
$bad_archive = FALSE;
2023-09-13 10:58:22 +00:00
foreach ($f as $packet) {
try {
$pkt = Packet::process($packet,Arr::get(stream_get_meta_data($packet),'uri'),$f->itemSize(),$this->so);
// Check that the packet is from a system that is defined in the DB
if (! $pkt->fftn) {
Log::error(sprintf('%s:! Packet [%s] is not from a system we know about? [%s]',self::LOGKEY,$this->filename,$pkt->fftn_t));
break;
}
2023-09-13 10:58:22 +00:00
// If we dont have the tftn in the DB, then packet cannot be to us
if (! $pkt->tftn) {
2024-11-20 06:31:11 +00:00
Log::error(sprintf('%s:! Packet [%s] is for a system [%s] we dont know about?',self::LOGKEY,$this->filename,$pkt->tftn_t));
// @todo Notification::route('netmail',$pkt->fftn)->notify(new UnexpectedPacketToUs($this->filename));
break;
}
// Check the packet is to our address, if not we'll reject it.
if (! our_address($pkt->tftn->zone->domain)->contains($pkt->tftn)) {
Log::error(sprintf('%s:! Packet [%s] is not to our address? [%s]',self::LOGKEY,$this->filename,$pkt->tftn->ftn));
2023-09-13 10:58:22 +00:00
// @todo Notification::route('netmail',$pkt->fftn)->notify(new UnexpectedPacketToUs($this->filename));
break;
}
2023-09-13 10:58:22 +00:00
2024-11-20 06:31:11 +00:00
$netmail_only = FALSE;
if (! our_nodes($pkt->fftn->zone->domain)->contains($pkt->fftn)) {
Log::alert(sprintf('%s:! Packet [%s] is from a system that is not configured with us, only NETMAIL processed [%s]',self::LOGKEY,$this->filename,$pkt->fftn_t));
$netmail_only = TRUE;
// Check the packet password
2024-11-20 06:31:11 +00:00
} elseif ($pkt->fftn->pass_packet !== strtoupper($pkt->password)) {
Log::error(sprintf('%s:! Packet from [%s] with password [%s] is invalid.',self::LOGKEY,$pkt->fftn->ftn,$pkt->password));
2023-09-13 10:58:22 +00:00
Notification::route('netmail',$pkt->fftn)->notify(new PacketPasswordInvalid($pkt->password,$f->pktName()));
break;
}
2023-09-13 10:58:22 +00:00
Log::info(sprintf('%s:- Packet has [%d] messages',self::LOGKEY,$pkt->count()));
2023-09-13 10:58:22 +00:00
// Queue messages if there are too many in the packet.
if ($queue = ($pkt->count() > config('fido.queue_msgs')))
Log::info(sprintf('%s:- Messages will be sent to the queue for processing',self::LOGKEY));
$count = 0;
foreach ($pkt as $msg) {
if ($msg instanceof Netmail)
Log::info(sprintf('%s:- Netmail from [%s] to [%s]',self::LOGKEY,$msg->fftn->ftn,$msg->tftn->ftn));
2024-11-20 06:31:11 +00:00
elseif ($msg instanceof Echomail) {
Log::info(sprintf('%s:- Echomail from [%s]',self::LOGKEY,$msg->fftn->ftn));
2024-11-20 06:31:11 +00:00
if ($netmail_only) {
Log::alert(sprintf('%s:! Echomail IGNORED as packet is from an unknown system [%s]',self::LOGKEY,$pkt->fftn->ftn));
continue;
}
}
if ($msg->errors->count()) {
Log::error(sprintf('%s:! Message [%s] has [%d] errors, unable to process',self::LOGKEY,$msg->msgid,$msg->errors->count()));
continue;
}
2023-09-13 10:58:22 +00:00
$msg->set_sender = $pkt->fftn->withoutRelations();
// Record receiving packet and sender
$msg->set_pkt = $f->pktName();
$msg->set_recvtime = $this->rcvd_time;
if ($queue || (! $this->interactive))
Log::info(sprintf('%s:! Message [%s] will be sent to the queue to process',self::LOGKEY,$msg->msgid));
try {
// Dispatch job.
if ($queue || (! $this->interactive))
MessageProcess::dispatch($msg->withoutRelations(),$this->nobot);
else
MessageProcess::dispatchSync($msg->withoutRelations(),$this->nobot);
$count++;
2023-09-13 10:58:22 +00:00
} catch (\Exception $e) {
Log::error(sprintf('%s:! Got error [%s] dispatching message [%s] (%d:%s-%s).',self::LOGKEY,get_class($e),$msg->msgid,$e->getLine(),$e->getFile(),$e->getMessage()));
}
2023-09-13 10:58:22 +00:00
}
if ($count === $pkt->count())
$processed = TRUE;
2024-11-20 06:31:11 +00:00
elseif ($netmail_only)
Notification::route('netmail',$pkt->fftn)->notify(new UnexpectedPacketFromYou($f->pktName()));
} catch (\Exception $e) {
Log::error(sprintf('%s:! Got an exception [%s] processing packet',self::LOGKEY,$e->getMessage()));
$bad_archive = TRUE;
}
2023-09-13 10:58:22 +00:00
}
if ((! $processed) || $bad_archive) {
Log::alert(sprintf('%s:- Not deleting packet [%s], it doesnt seem to be processed?',self::LOGKEY,$this->filename));
2023-09-13 10:58:22 +00:00
} else {
2023-09-13 10:58:22 +00:00
// If we want to keep the packet, we could do that logic here
if (config('fido.packet_keep')) {
$dir = sprintf('%s/%s/%s/%s',config('fido.dir'),($x=Carbon::now())->format('Y'),$x->format('m'),$x->format('d'));
Log::debug(sprintf('%s:- Moving processed packet [%s] to [%s]',self::LOGKEY,$this->filename,$dir));
try {
if ($fs->makeDirectory($dir)) {
$fs->move($this->filename,$x=sprintf('%s/%s',$dir,$f->itemName()));
Log::info(sprintf('%s:- Moved processed packet [%s] to [%s]',self::LOGKEY,$this->filename,$x));
} else
Log::error(sprintf('%s:! Unable to create dir [%s]',self::LOGKEY,$dir));
} catch (UnableToMoveFile $e) {
Log::error(sprintf('%s:! Unable to move packet [%s] to [%s] (%s)',self::LOGKEY,$this->filename,$dir,$e->getMessage()));
} catch (\Exception $e) {
Log::error(sprintf('%s:! Failed moving packet [%s] to [%s] (%s)',self::LOGKEY,$this->filename,$dir,$e->getMessage()));
}
} else {
Log::debug(sprintf('%s:- Deleting processed packet [%s]',self::LOGKEY,$this->filename));
$fs->delete($this->filename);
}
2023-09-13 10:58:22 +00:00
}
} catch (InvalidPacketException $e) {
Log::error(sprintf('%s:- Not deleting packet [%s], as it generated an InvalidPacketException',self::LOGKEY,$this->filename),['e'=>$e->getMessage()]);
2023-09-13 10:58:22 +00:00
} catch (\Exception $e) {
Log::error(sprintf('%s:- Not deleting packet [%s], as it generated an uncaught exception',self::LOGKEY,$this->filename),['e'=>$e->getMessage(),'l'=>$e->getLine(),'f'=>$e->getFile()]);
2023-09-13 10:58:22 +00:00
}
}
}