Compare commits
3 Commits
28b48e5bef
...
1128bddcee
Author | SHA1 | Date | |
---|---|---|---|
1128bddcee | |||
4796dd9a6e | |||
d792bf8fe3 |
@ -6,9 +6,9 @@ use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\FTN\Process;
|
||||
use App\Classes\FTN\Process\Netmail\Robot\Unknown;
|
||||
use App\Models\{Echomail,Netmail};
|
||||
use App\Notifications\Netmails\Areafix as AreafixNotification;
|
||||
use App\Notifications\Netmails\Areafix\NotConfiguredHere as AreafixNotConfiguredHereNotification;
|
||||
|
||||
/**
|
||||
* Process messages to Ping
|
||||
@ -19,18 +19,75 @@ final class Areafix extends Process
|
||||
{
|
||||
private const LOGKEY = 'RP-';
|
||||
|
||||
public const areafix_commands = 'App\\Classes\\FTN\\Process\\Netmail\\Robot\\Areafix\\';
|
||||
|
||||
public static function handle(Echomail|Netmail $mo): bool
|
||||
{
|
||||
if (strtolower($mo->to) !== 'areafix')
|
||||
if (((strtolower($mo->to) !== 'areafix') || (strtolower($mo->to) !== 'filefix')) && (! ($mo instanceof Netmail)))
|
||||
return FALSE;
|
||||
|
||||
Log::info(sprintf('%s:- Processing AREAFIX message from (%s) [%s]',self::LOGKEY,$mo->from,$mo->fftn));
|
||||
Log::info(sprintf('%s:- Processing AREAFIX message from (%s) [%s]',self::LOGKEY,$mo->from,$mo->fftn->ftn));
|
||||
|
||||
// If this is not a node we manage, then respond with a sorry can help you
|
||||
if ($mo->fftn->system->sessions->count())
|
||||
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotification($mo));
|
||||
else
|
||||
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotConfiguredHereNotification($mo));
|
||||
if (! $mo->fftn->system->sessions->count()) {
|
||||
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotification\NotConfiguredHere($mo));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// If this nodes password is not correct
|
||||
if ($mo->fftn->pass_fix !== strtoupper($mo->subject)) {
|
||||
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotification\InvalidPassword($mo));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
$result = collect();
|
||||
$result->push('--> BEGIN <--');
|
||||
|
||||
foreach ($mo->body_lines as $command) {
|
||||
// Skip empty lines
|
||||
if (! $command)
|
||||
continue;
|
||||
|
||||
$command = explode(' ',strtoupper(trim($command)));
|
||||
|
||||
// If command starts with '...' or '---', its a tear/tag line, and we have reached the end
|
||||
if (str_starts_with($command[0],'...') || str_starts_with($command[0],'---')) {
|
||||
Log::debug(sprintf('%s:= We got a tearline/tagline, end of processing',self::LOGKEY));
|
||||
|
||||
$result->push('--> END OF PROCESSING <--');
|
||||
|
||||
break;
|
||||
|
||||
// If command doesnt start with %, its an area
|
||||
} elseif (! str_starts_with($command[0],'%')) {
|
||||
Log::debug(sprintf('%s:= Assuming command [%s] is an AREA command',self::LOGKEY,$command[0]));
|
||||
|
||||
array_unshift($command,'%AREA');
|
||||
}
|
||||
|
||||
// Parse the message body and pluck out the commands on each line
|
||||
$class = self::areafix_commands.ucfirst(strtolower(substr($command[0],1)));
|
||||
|
||||
if (! class_exists($class)) {
|
||||
$result->push(sprintf('%-25s <-- **COMMAND UNKNOWN**',join(' ',$command)));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Drop the command from the array, the rest are arguments
|
||||
array_shift($command);
|
||||
|
||||
// Refresh our echoareas
|
||||
$mo->fftn->load('echoareas');
|
||||
|
||||
$o = new $class($mo,$command);
|
||||
$result->push($o->process());
|
||||
}
|
||||
|
||||
// Reply with a confirmation of what commands were processed
|
||||
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotification\CommandsProcessed($mo,$result));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
140
app/Classes/FTN/Process/Netmail/Robot/Areafix/Area.php
Normal file
140
app/Classes/FTN/Process/Netmail/Robot/Areafix/Area.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\FTN\Process\Netmail\Robot\Areafix;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Jobs\AreafixRescan;
|
||||
|
||||
// Echoarea Processing Command
|
||||
class Area extends Base
|
||||
{
|
||||
private const LOGKEY = 'AFA';
|
||||
|
||||
private const command = '%AREA';
|
||||
|
||||
public static function help(): array
|
||||
{
|
||||
return [
|
||||
self::command.' [-|+]<ECHOAREA> [R|D=<DAYS>]',
|
||||
' Use the area command to subscribe (+) or unsubscribe (-) to an ECHOAREA',
|
||||
' Arguments:',
|
||||
' - ECHOAREA (required) name of area to subscribe or unsubscribe',
|
||||
' - D=DAYS (optional) number of days to resend mail from this area that you',
|
||||
' havent already received (useful if you are resubscribing to an area and',
|
||||
' have received mail in the past)',
|
||||
' - R=DAYS (optional) number of days to resend mail from this area (even if',
|
||||
' it was sent to you previously)',
|
||||
' Notes:',
|
||||
' * "+" is optional, and is implied if "-" is not used',
|
||||
' * "R" and "D" options only apply to subscribing',
|
||||
];
|
||||
}
|
||||
|
||||
public function process(): string
|
||||
{
|
||||
// If command starts with '-', its to unsubscribe
|
||||
if (str_starts_with($this->arguments[0],'-')) {
|
||||
$sub = FALSE;
|
||||
$area = substr($this->arguments[0],1);
|
||||
|
||||
} elseif (str_starts_with($this->arguments[0],'+')) {
|
||||
$sub = TRUE;
|
||||
$area = substr($this->arguments[0],1);
|
||||
|
||||
} else {
|
||||
$sub = TRUE;
|
||||
$area = $this->arguments[0];
|
||||
}
|
||||
|
||||
Log::debug(sprintf('%s:- Processing [%s] for [%s]',self::LOGKEY,$sub ? 'ADD' : 'REMOVE',$area));
|
||||
|
||||
// Drop the area from the arguments, the rest are options
|
||||
array_shift($this->arguments);
|
||||
|
||||
if ($ea=$this->mo->fftn->domain->echoareas->where('name',$area)->pop()) {
|
||||
// If already subscribed
|
||||
if ($nea=$this->mo->fftn->echoareas->where('name',$area)->pop()) {
|
||||
// requesting to subscribe "You already are since..., arguments ignored
|
||||
if ($sub) {
|
||||
Log::debug(sprintf('%s:- FTN [%s] ALREADY subscribed to [%s] since [%s]',self::LOGKEY,$this->mo->fftn->ftn,$area,$nea->pivot->subscribed->format('Y-m-d H:i')));
|
||||
|
||||
return sprintf('%-25s <-- ALREADY subscribed since %s',$area,$nea->pivot->subscribed->format('Y-m-d H:i'));
|
||||
|
||||
// requesting to unsubscribe
|
||||
} else {
|
||||
$this->mo->fftn->echoareas()->detach($ea->id);
|
||||
|
||||
// Remove sub, clear queue
|
||||
$x = DB::table('echomail_seenby')
|
||||
->where('address_id',$this->mo->fftn->id)
|
||||
->join('echomails',['echomails.id'=>'echomail_seenby.echomail_id'])
|
||||
->where('echoarea_id',$nea->id)
|
||||
->whereNotNull('export_at')
|
||||
->whereNull('sent_at')
|
||||
->orderBy('echomails.datetime')
|
||||
->skip($this->mo->fftn->system->pkt_msgs)
|
||||
->delete();
|
||||
|
||||
Log::debug(sprintf('%s:- FTN [%s] UNSUBSCRIBED from [%s] clearing [%s]',self::LOGKEY,$this->mo->fftn->ftn,$area,$x));
|
||||
|
||||
return sprintf('%-25s <-- UNSUBSCRIBED, CLEARED [%d] MSGS from queue',$area,$x);
|
||||
}
|
||||
|
||||
// If not subscribed
|
||||
} else {
|
||||
// requesting to subscribe, subsubsribe and rescan if arguments
|
||||
if ($sub) {
|
||||
$this->mo->fftn->echoareas()->attach([$ea->id=>['subscribed'=>Carbon::now()]]);
|
||||
|
||||
// If we have arguments, they are to rescan
|
||||
if (count($this->arguments) === 1) {
|
||||
$m = [];
|
||||
if (preg_match('/^([DR])=([0-9]+)$/',$this->arguments[0],$m)) {
|
||||
switch ($m[1]) {
|
||||
// Scan
|
||||
case 'D':
|
||||
AreafixRescan::dispatch($this->mo->fftn,$ea,$m[2])
|
||||
->onQueue('mail');
|
||||
|
||||
return sprintf('%-25s <-- AREA SUBSCRIBED, RESCAN [%d] DAYS queued',$area,$m[2]);
|
||||
|
||||
// Scan
|
||||
case 'R':
|
||||
AreafixRescan::dispatch($this->mo->fftn,$ea,$m[2],TRUE)
|
||||
->onQueue('mail');
|
||||
|
||||
return sprintf('%-25s <-- AREA SUBSCRIBED, FORCE RESCAN [%d] DAYS queued',$area,$m[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return sprintf('%-25s <-- AREA SUBSCRIBED, INVALID OPTIONS',$area);
|
||||
|
||||
} elseif (count($this->arguments) > 1) {
|
||||
Log::debug(sprintf('%s:- FTN [%s] subscribed to [%s], extra commands [%s] ignored',self::LOGKEY,$this->mo->fftn->ftn,$area,implode('|',$this->arguments)));
|
||||
|
||||
return sprintf('%-25s <-- AREA SUBSCRIBED, OPTIONS IGNORED',$area);
|
||||
|
||||
} else {
|
||||
Log::debug(sprintf('%s:- FTN [%s] subscribed to [%s]',self::LOGKEY,$this->mo->fftn->ftn,$area));
|
||||
|
||||
return sprintf('%-25s <-- AREA SUBSCRIBED',$area);
|
||||
}
|
||||
|
||||
// If not subscribed, "you arent subscribed, arguments ignored"
|
||||
} else {
|
||||
Log::debug(sprintf('%s:- FTN [%s] is NOT subscribed to [%s], NO ACTION taken',self::LOGKEY,$this->mo->fftn->ftn,$area));
|
||||
|
||||
return sprintf('%-25s <-- NOT subscribed, NO ACTION taken',$area);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Log::debug(sprintf('%s:- FTN [%s] area UNKNOWN [%s], NO ACTION taken',self::LOGKEY,$this->mo->fftn->ftn,$area));
|
||||
|
||||
return sprintf('%-25s <-- AREA UNKNOWN, NO ACTION TAKEN',$area);
|
||||
}
|
||||
}
|
||||
}
|
26
app/Classes/FTN/Process/Netmail/Robot/Areafix/Base.php
Normal file
26
app/Classes/FTN/Process/Netmail/Robot/Areafix/Base.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\FTN\Process\Netmail\Robot\Areafix;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Models\Netmail;
|
||||
|
||||
// Our base areafix commands class
|
||||
abstract class Base
|
||||
{
|
||||
private const LOGKEY = 'AB-';
|
||||
|
||||
protected Netmail $mo;
|
||||
protected array $arguments;
|
||||
|
||||
public function __construct(Netmail $mo,array $arguments) {
|
||||
Log::debug(sprintf('%s:- Areafix [%s] command with arguments [%s] for [%s]',self::LOGKEY,get_class($this),implode('|',$arguments),$mo->fftn->ftn));
|
||||
|
||||
$this->mo = $mo;
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
|
||||
abstract public static function help(): array;
|
||||
abstract public function process(): string;
|
||||
}
|
44
app/Classes/FTN/Process/Netmail/Robot/Areafix/Help.php
Normal file
44
app/Classes/FTN/Process/Netmail/Robot/Areafix/Help.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\FTN\Process\Netmail\Robot\Areafix;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
use App\Classes\FTN\Process\Netmail\Areafix;
|
||||
use App\Notifications\Netmails\Areafix\Help as HelpNotification;
|
||||
|
||||
// A Help Index Command
|
||||
class Help extends Base
|
||||
{
|
||||
private const LOGKEY = 'AFH';
|
||||
private const areafix_classes = 'app/Classes/FTN/Process/Netmail/Robot/Areafix';
|
||||
private const command = '%HELP';
|
||||
|
||||
public static function help(): array
|
||||
{
|
||||
return [
|
||||
self::command,
|
||||
' This message!',
|
||||
];
|
||||
}
|
||||
|
||||
public function process(): string
|
||||
{
|
||||
Log::debug(sprintf('%s:- Processing [%s] for [%s]',self::LOGKEY,self::command,$this->mo->fftn->ftn));
|
||||
|
||||
$result = collect();
|
||||
|
||||
foreach (preg_grep('/^([^.])/',scandir(self::areafix_classes)) as $file) {
|
||||
if ($file === 'Base.php')
|
||||
continue;
|
||||
|
||||
$class = Areafix::areafix_commands.preg_replace('/\.php$/','',$file);
|
||||
$result = $result->merge($class::help());
|
||||
}
|
||||
|
||||
Notification::route('netmail',$this->mo->fftn)->notify(new HelpNotification($this->mo,$result));
|
||||
|
||||
return sprintf('%-25s <-- COMMAND PROCESSED',self::command);
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ use App\Classes\Protocol as BaseProtocol;
|
||||
use App\Classes\Sock\Exception\SocketException;
|
||||
use App\Classes\Sock\SocketClient;
|
||||
use App\Exceptions\{FileGrewException,InvalidFTNException};
|
||||
use App\Models\{Address,Mailer};
|
||||
use App\Models\{Address,Mailer,Setup};
|
||||
|
||||
final class Binkp extends BaseProtocol
|
||||
{
|
||||
@ -195,7 +195,7 @@ final class Binkp extends BaseProtocol
|
||||
$this->msgs(self::BPM_NUL,sprintf('NDL %d,TCP,BINKP',$this->client->speed));
|
||||
$this->msgs(self::BPM_NUL,sprintf('TIME %s',Carbon::now()->toRfc2822String()));
|
||||
$this->msgs(self::BPM_NUL,
|
||||
sprintf('VER %s-%s %s/%s',config('app.name'),$this->setup->version,self::PROT,self::VERSION));
|
||||
sprintf('VER %s-%s %s/%s',Setup::PRODUCT_NAME_SHORT,$this->setup->version,self::PROT,self::VERSION));
|
||||
|
||||
if ($this->originate) {
|
||||
$opt = $this->capGet(self::F_NOREL,self::O_WANT) ? ' NR' : '';
|
||||
|
@ -207,7 +207,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
||||
// Mailer Details
|
||||
$makedata .= sprintf('{%s}{%s}{%s}{%s}',
|
||||
Setup::product_id(),
|
||||
config('app.name'),
|
||||
Setup::PRODUCT_NAME_SHORT,
|
||||
$this->setup->version,
|
||||
'#000000' // Serial Numbers
|
||||
);
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
namespace App\Console\Commands\Areafix;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use App\Models\{Address,Echoarea,Echomail};
|
||||
use App\Jobs\AreafixRescan;
|
||||
use App\Models\{Address,Echoarea};
|
||||
|
||||
class Rescan extends Command
|
||||
{
|
||||
@ -18,6 +18,8 @@ class Rescan extends Command
|
||||
.' {ftn : FTN Address}'
|
||||
.' {area : Echoarea Tag}'
|
||||
.' {days? : Limit to messages authored days ago}'
|
||||
.' {--j|queue : Queue the Job}'
|
||||
.' {--Q|queuename=default : Queue on queue}'
|
||||
.' {--R|export : Re-export previously sent messages}';
|
||||
|
||||
/**
|
||||
@ -47,67 +49,12 @@ class Rescan extends Command
|
||||
if (! $this->argument('area'))
|
||||
throw new \Exception('Areaname is required');
|
||||
|
||||
$eao = Echoarea::where('name',$this->argument('area'))->singleOrFail();
|
||||
if ($eao->domain_id !== $ao->zone->domain_id)
|
||||
throw new \Exception(sprintf('Echo area [%s] is not in domain [%s] for FTN [%s]',$eao->name,$ao->zone->domain->name,$ao->ftn));
|
||||
$eo = Echoarea::where('name',$this->argument('area'))->sole();
|
||||
|
||||
// Check that the user is subscribed
|
||||
if (! $ao->echoareas->contains($eao->id))
|
||||
throw new \Exception(sprintf('FTN [%s] is not subscribed to [%s]',$ao->ftn,$eao->name));
|
||||
|
||||
// Check that an FTN can read the area
|
||||
if (! $eao->can_read($ao->security))
|
||||
throw new \Exception(sprintf('FTN [%s] doesnt have permission to receive [%s]',$ao->ftn,$eao->name));
|
||||
|
||||
foreach (Echomail::select(['id','datetime'])
|
||||
->where('echoarea_id',$eao->id)
|
||||
->when(
|
||||
$this->argument('days'),
|
||||
fn($query)=>$query->where('datetime','>=',
|
||||
Carbon::now()
|
||||
->subDays($this->argument('days'))
|
||||
->startOfDay())
|
||||
)
|
||||
->orderBy('datetime')
|
||||
->cursor() as $eo) {
|
||||
|
||||
// Echomail hasnt been exported before
|
||||
if (! $eo->seenby->count()) {
|
||||
$eo->seenby()->attach($ao->id,['export_at'=>Carbon::now()]);
|
||||
|
||||
$this->info(sprintf('Exported [%d] MSG (%s) dated (%s) to [%s]',$eo->id,$eo->msgid ?: '*NO MSGID*',$eo->datetime->format('Y-m-d H:i:s'),$ao->ftn3d));
|
||||
|
||||
} else {
|
||||
$export = $eo->seenby->where('id',$ao->id)->pop();
|
||||
|
||||
if ($export) {
|
||||
// Echomail is pending export
|
||||
if ($export->pivot->export_at && is_null($export->pivot->sent_at) && is_null($export->pivot->sent_pkt)) {
|
||||
$this->warn(sprintf('Not exporting [%d] MSG (%s) dated (%s) already queued for [%s]',$eo->id,$eo->msgid ?: '*NO MSGID*',$eo->datetime->format('Y-m-d H:i:s'),$ao->ftn3d));
|
||||
|
||||
// Echomail has been exported
|
||||
} elseif ($this->option('export')) {
|
||||
$eo->seenby()->updateExistingPivot($ao,['export_at'=>Carbon::now(),'sent_at'=>NULL,'sent_pkt'=>NULL]);
|
||||
|
||||
$this->info(sprintf('Re-exported [%d] MSG (%s) dated (%s) to [%s]',$eo->id,$eo->msgid ?: '*NO MSGID*',$eo->datetime,$ao->ftn3d));
|
||||
|
||||
} else {
|
||||
$this->info(sprintf('Not resending previously sent message [%d], MSGID (%s) - sent in Pkt [%s] on [%s]',
|
||||
$eo->id,
|
||||
$eo->msgid ?: '* NO MSGID*',
|
||||
$export->pivot->sent_pkt ?: '-',
|
||||
$export->pivot->sent_at ?: '-',
|
||||
));
|
||||
}
|
||||
|
||||
// Echomail has not been exported
|
||||
} else {
|
||||
$eo->seenby()->attach($ao,['export_at'=>Carbon::now(),'sent_at'=>NULL,'sent_pkt'=>NULL]);
|
||||
|
||||
$this->info(sprintf('Exported [%d] to [%s]',$eo->id,$ao->ftn3d));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->option('queue'))
|
||||
AreafixRescan::dispatch($ao,$eo,$this->argument('days'))->onQueue($this->option('queuename'));
|
||||
else
|
||||
AreafixRescan::dispatchSync($ao,$eo,$this->argument('days'));
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
137
app/Jobs/AreafixRescan.php
Normal file
137
app/Jobs/AreafixRescan.php
Normal file
@ -0,0 +1,137 @@
|
||||
<?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\Middleware\Skip;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Models\{Address,Echoarea,Echomail};
|
||||
|
||||
class AreafixRescan implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
private const LOGKEY = 'JAR';
|
||||
|
||||
private Address $ao; // System address
|
||||
private Echoarea $eao; // Domain we are processing
|
||||
private int $days;
|
||||
private bool $rescan;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(Address $ao,Echoarea $eao,int $days=30,bool $rescan=FALSE)
|
||||
{
|
||||
$this->ao = $ao->withoutRelations();
|
||||
$this->eao = $eao->withoutRelations();
|
||||
$this->days = $days;
|
||||
$this->rescan = $rescan;
|
||||
}
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'jobname':
|
||||
return sprintf('%s %s (%d)',$this->ao->ftn,$this->eao->name,$this->days);
|
||||
|
||||
default:
|
||||
$this->fail('Unkown key:'.$key);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [
|
||||
Skip::when(function(): bool {
|
||||
if ($this->eao->domain_id !== $this->ao->zone->domain_id) {
|
||||
Log::error(sprintf('%s:! Echo area [%s] is not in domain [%s] for FTN [%s]',self::LOGKEY,$this->eao->name,$this->ao->zone->domain->name,$this->ao->ftn));
|
||||
|
||||
return TRUE;
|
||||
|
||||
// Check that the user is subscribed
|
||||
} elseif (! $this->ao->echoareas->contains($this->eao->id)) {
|
||||
Log::error(sprintf('%s:! FTN [%s] is not subscribed to [%s]',self::LOGKEY,$this->ao->ftn,$this->eao->name));
|
||||
|
||||
return TRUE;
|
||||
|
||||
// Check that an FTN can read the area
|
||||
} elseif (! $this->eao->can_read($this->ao->security)) {
|
||||
Log::error(sprintf('%s:! FTN [%s] doesnt have permission to receive [%s]',self::LOGKEY,$this->ao->ftn,$this->eao->name));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
$c = 0;
|
||||
$s = 0;
|
||||
foreach (Echomail::select(['id','datetime'])
|
||||
->where('echoarea_id',$this->eao->id)
|
||||
->where('datetime','>=',
|
||||
Carbon::now()
|
||||
->subDays($this->days)
|
||||
->startOfDay()
|
||||
)
|
||||
->orderBy('datetime')
|
||||
->cursor() as $eo) {
|
||||
|
||||
// Echomail hasnt been exported before
|
||||
if (! $eo->seenby->count()) {
|
||||
$eo->seenby()->attach($this->ao->id,['export_at'=>Carbon::now()]);
|
||||
$c++;
|
||||
|
||||
Log::debug(sprintf('Exported [%d] MSG (%s) dated (%s) to [%s]',$eo->id,$eo->msgid ?: '*NO MSGID*',$eo->datetime->format('Y-m-d H:i:s'),$this->ao->ftn3d));
|
||||
|
||||
} else {
|
||||
$export = $eo->seenby->where('id',$this->ao->id)->pop();
|
||||
|
||||
if ($export) {
|
||||
// Echomail is pending export
|
||||
if ($export->pivot->export_at && is_null($export->pivot->sent_at) && is_null($export->pivot->sent_pkt)) {
|
||||
$s++;
|
||||
Log::debug(sprintf('Not exporting [%d] MSG (%s) dated (%s) already queued for [%s]',$eo->id,$eo->msgid ?: '*NO MSGID*',$eo->datetime->format('Y-m-d H:i:s'),$this->ao->ftn3d));
|
||||
|
||||
// Echomail has been exported
|
||||
} elseif ($this->rescan) {
|
||||
$eo->seenby()->updateExistingPivot($this->ao,['export_at'=>Carbon::now(),'sent_at'=>NULL]);
|
||||
$c++;
|
||||
|
||||
Log::debug(sprintf('Re-exported [%d] MSG (%s) dated (%s) to [%s]',$eo->id,$eo->msgid ?: '*NO MSGID*',$eo->datetime,$this->ao->ftn3d));
|
||||
|
||||
} else {
|
||||
$s++;
|
||||
Log::debug(sprintf('Not resending previously sent message [%d], MSGID (%s) - sent in Pkt [%s] on [%s]',
|
||||
$eo->id,
|
||||
$eo->msgid ?: '* NO MSGID*',
|
||||
$export->pivot->sent_pkt ?: '-',
|
||||
$export->pivot->sent_at ?: '-',
|
||||
));
|
||||
}
|
||||
|
||||
// Echomail has not been exported
|
||||
} else {
|
||||
$eo->seenby()->attach($this->ao,['export_at'=>Carbon::now(),'sent_at'=>NULL,'sent_pkt'=>NULL]);
|
||||
$c++;
|
||||
|
||||
Log::debug(sprintf('Exported [%d] to [%s]',$eo->id,$this->ao->ftn3d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @todo Send a netmail to the node about the rescan
|
||||
Log::info(sprintf('%s:= Queued [%d], Skipped [%d] echomails for [%s] in [%s]',self::LOGKEY,$c,$s,$this->ao->ftn,$this->eao->name));
|
||||
}
|
||||
}
|
@ -569,6 +569,7 @@ class Address extends Model
|
||||
public function echoareas()
|
||||
{
|
||||
return $this->belongsToMany(Echoarea::class)
|
||||
->using(AddressEchoarea::class)
|
||||
->orderBy('name')
|
||||
->withPivot(['subscribed']);
|
||||
}
|
||||
|
12
app/Models/AddressEchoarea.php
Normal file
12
app/Models/AddressEchoarea.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
|
||||
class AddressEchoarea extends Pivot
|
||||
{
|
||||
protected $casts = [
|
||||
'subscribed' => 'datetime:Y-m-d H:i',
|
||||
];
|
||||
}
|
@ -277,6 +277,16 @@ final class Netmail extends Model implements Packet
|
||||
: $this->getRelationValue('path');
|
||||
}
|
||||
|
||||
/**
|
||||
* Split the body of a message into a collection of lines.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBodyLinesAttribute(): array
|
||||
{
|
||||
return explode("\r",$this->msg_src);
|
||||
}
|
||||
|
||||
/* METHODS */
|
||||
|
||||
/**
|
||||
|
67
app/Notifications/Netmails/Areafix/CommandsProcessed.php
Normal file
67
app/Notifications/Netmails/Areafix/CommandsProcessed.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Netmails\Areafix;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Notifications\Netmails;
|
||||
use App\Models\Netmail;
|
||||
use App\Traits\{MessagePath,PageTemplate};
|
||||
|
||||
class CommandsProcessed extends Netmails
|
||||
{
|
||||
use MessagePath,PageTemplate;
|
||||
|
||||
private const LOGKEY = 'ACU';
|
||||
|
||||
/**
|
||||
* Reply to a areafix, commands unknown.
|
||||
*
|
||||
* @param Netmail $mo
|
||||
* @param Collection $commands
|
||||
*/
|
||||
public function __construct(private Netmail $mo,private Collection $commands)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return Netmail
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function toNetmail(object $notifiable): Netmail
|
||||
{
|
||||
$o = $this->setupNetmail($notifiable);
|
||||
$ao = $notifiable->routeNotificationFor(static::via);
|
||||
|
||||
Log::info(sprintf('%s:+ Responding to areafix for a node [%s] commands processed',self::LOGKEY,$ao->ftn));
|
||||
|
||||
$o->to = $this->mo->from;
|
||||
$o->replyid = $this->mo->msgid;
|
||||
$o->subject = 'Areafix - Result';
|
||||
|
||||
// Message
|
||||
$msg = $this->page(FALSE,'Areafix');
|
||||
|
||||
$msg->addText("Your areafix request has been received, here is the result:\r\r");
|
||||
|
||||
foreach ($this->commands as $command) {
|
||||
$msg->addText("$command\r");
|
||||
}
|
||||
|
||||
$msg->addText("\r");
|
||||
|
||||
$msg->addText($this->message_path($this->mo));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->set_tagline = 'Why did the robot cross the road? The chicken programmed it.';
|
||||
|
||||
$o->save();
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
65
app/Notifications/Netmails/Areafix/Help.php
Normal file
65
app/Notifications/Netmails/Areafix/Help.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Netmails\Areafix;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Notifications\Netmails;
|
||||
use App\Models\Netmail;
|
||||
use App\Traits\{MessagePath,PageTemplate};
|
||||
|
||||
class Help extends Netmails
|
||||
{
|
||||
use MessagePath,PageTemplate;
|
||||
|
||||
private const LOGKEY = 'ACH';
|
||||
|
||||
/**
|
||||
* Reply to a areafix, commands unknown.
|
||||
*
|
||||
* @param Netmail $mo
|
||||
* @param Collection $commands
|
||||
*/
|
||||
public function __construct(private Netmail $mo,private Collection $commands)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return Netmail
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function toNetmail(object $notifiable): Netmail
|
||||
{
|
||||
$o = $this->setupNetmail($notifiable);
|
||||
$ao = $notifiable->routeNotificationFor(static::via);
|
||||
|
||||
Log::info(sprintf('%s:+ Responding to areafix for a node [%s] commands processed',self::LOGKEY,$ao->ftn));
|
||||
|
||||
$o->to = $this->mo->from;
|
||||
$o->replyid = $this->mo->msgid;
|
||||
$o->subject = 'Areafix - Help';
|
||||
|
||||
// Message
|
||||
$msg = $this->page(FALSE,'Areafix');
|
||||
|
||||
$msg->addText("Here are the list of commands available to you:\r\r\r\r");
|
||||
|
||||
foreach ($this->commands as $command) {
|
||||
$msg->addText("$command\r");
|
||||
}
|
||||
|
||||
$msg->addText("\r");
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->set_tagline = 'Why did the robot cross the road? The chicken programmed it.';
|
||||
|
||||
$o->save();
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
64
app/Notifications/Netmails/Areafix/InvalidPassword.php
Normal file
64
app/Notifications/Netmails/Areafix/InvalidPassword.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Netmails\Areafix;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Notifications\Netmails;
|
||||
use App\Models\Netmail;
|
||||
use App\Traits\{MessagePath,PageTemplate};
|
||||
|
||||
class InvalidPassword extends Netmails
|
||||
{
|
||||
use MessagePath,PageTemplate;
|
||||
|
||||
private const LOGKEY = 'AIP';
|
||||
|
||||
private Netmail $mo;
|
||||
|
||||
/**
|
||||
* Reply to a areafix, but the password is incorrect.
|
||||
*
|
||||
* @param Netmail $mo
|
||||
*/
|
||||
public function __construct(Netmail $mo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->mo = $mo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return Netmail
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function toNetmail(object $notifiable): Netmail
|
||||
{
|
||||
$o = $this->setupNetmail($notifiable);
|
||||
$ao = $notifiable->routeNotificationFor(static::via);
|
||||
|
||||
Log::info(sprintf('%s:+ Responding to areafix for a node [%s] invalid password',self::LOGKEY,$ao->ftn));
|
||||
|
||||
$o->to = $this->mo->from;
|
||||
$o->replyid = $this->mo->msgid;
|
||||
$o->subject = 'Areafix - Invalid Password';
|
||||
|
||||
// Message
|
||||
$msg = $this->page(FALSE,'Areafix');
|
||||
|
||||
$msg->addText("Your areafix request has been received, but unfortunately your password was incorrect.\r\r");
|
||||
$msg->addText(sprintf("If you are not aware of your password, head over to %s. Feel free to netmail if you need help.\r\r",config('app.url')));
|
||||
|
||||
$msg->addText($this->message_path($this->mo));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->set_tagline = 'Why did the robot cross the road? The chicken programmed it.';
|
||||
|
||||
$o->save();
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ class NotConfiguredHere extends Netmails
|
||||
{
|
||||
use MessagePath,PageTemplate;
|
||||
|
||||
private const LOGKEY = 'NCH';
|
||||
private const LOGKEY = 'ANC';
|
||||
|
||||
private Netmail $mo;
|
||||
|
||||
|
1344
composer.lock
generated
1344
composer.lock
generated
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user