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 Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
use App\Classes\FTN\Process;
|
use App\Classes\FTN\Process;
|
||||||
|
use App\Classes\FTN\Process\Netmail\Robot\Unknown;
|
||||||
use App\Models\{Echomail,Netmail};
|
use App\Models\{Echomail,Netmail};
|
||||||
use App\Notifications\Netmails\Areafix as AreafixNotification;
|
use App\Notifications\Netmails\Areafix as AreafixNotification;
|
||||||
use App\Notifications\Netmails\Areafix\NotConfiguredHere as AreafixNotConfiguredHereNotification;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process messages to Ping
|
* Process messages to Ping
|
||||||
@ -19,18 +19,75 @@ final class Areafix extends Process
|
|||||||
{
|
{
|
||||||
private const LOGKEY = 'RP-';
|
private const LOGKEY = 'RP-';
|
||||||
|
|
||||||
|
public const areafix_commands = 'App\\Classes\\FTN\\Process\\Netmail\\Robot\\Areafix\\';
|
||||||
|
|
||||||
public static function handle(Echomail|Netmail $mo): bool
|
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;
|
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 this is not a node we manage, then respond with a sorry can help you
|
||||||
if ($mo->fftn->system->sessions->count())
|
if (! $mo->fftn->system->sessions->count()) {
|
||||||
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotification($mo));
|
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotification\NotConfiguredHere($mo));
|
||||||
else
|
|
||||||
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotConfiguredHereNotification($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;
|
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\Exception\SocketException;
|
||||||
use App\Classes\Sock\SocketClient;
|
use App\Classes\Sock\SocketClient;
|
||||||
use App\Exceptions\{FileGrewException,InvalidFTNException};
|
use App\Exceptions\{FileGrewException,InvalidFTNException};
|
||||||
use App\Models\{Address,Mailer};
|
use App\Models\{Address,Mailer,Setup};
|
||||||
|
|
||||||
final class Binkp extends BaseProtocol
|
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('NDL %d,TCP,BINKP',$this->client->speed));
|
||||||
$this->msgs(self::BPM_NUL,sprintf('TIME %s',Carbon::now()->toRfc2822String()));
|
$this->msgs(self::BPM_NUL,sprintf('TIME %s',Carbon::now()->toRfc2822String()));
|
||||||
$this->msgs(self::BPM_NUL,
|
$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) {
|
if ($this->originate) {
|
||||||
$opt = $this->capGet(self::F_NOREL,self::O_WANT) ? ' NR' : '';
|
$opt = $this->capGet(self::F_NOREL,self::O_WANT) ? ' NR' : '';
|
||||||
|
@ -207,7 +207,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
// Mailer Details
|
// Mailer Details
|
||||||
$makedata .= sprintf('{%s}{%s}{%s}{%s}',
|
$makedata .= sprintf('{%s}{%s}{%s}{%s}',
|
||||||
Setup::product_id(),
|
Setup::product_id(),
|
||||||
config('app.name'),
|
Setup::PRODUCT_NAME_SHORT,
|
||||||
$this->setup->version,
|
$this->setup->version,
|
||||||
'#000000' // Serial Numbers
|
'#000000' // Serial Numbers
|
||||||
);
|
);
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands\Areafix;
|
namespace App\Console\Commands\Areafix;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
use App\Models\{Address,Echoarea,Echomail};
|
use App\Jobs\AreafixRescan;
|
||||||
|
use App\Models\{Address,Echoarea};
|
||||||
|
|
||||||
class Rescan extends Command
|
class Rescan extends Command
|
||||||
{
|
{
|
||||||
@ -18,6 +18,8 @@ class Rescan extends Command
|
|||||||
.' {ftn : FTN Address}'
|
.' {ftn : FTN Address}'
|
||||||
.' {area : Echoarea Tag}'
|
.' {area : Echoarea Tag}'
|
||||||
.' {days? : Limit to messages authored days ago}'
|
.' {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}';
|
.' {--R|export : Re-export previously sent messages}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,67 +49,12 @@ class Rescan extends Command
|
|||||||
if (! $this->argument('area'))
|
if (! $this->argument('area'))
|
||||||
throw new \Exception('Areaname is required');
|
throw new \Exception('Areaname is required');
|
||||||
|
|
||||||
$eao = Echoarea::where('name',$this->argument('area'))->singleOrFail();
|
$eo = Echoarea::where('name',$this->argument('area'))->sole();
|
||||||
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));
|
|
||||||
|
|
||||||
// Check that the user is subscribed
|
if ($this->option('queue'))
|
||||||
if (! $ao->echoareas->contains($eao->id))
|
AreafixRescan::dispatch($ao,$eo,$this->argument('days'))->onQueue($this->option('queuename'));
|
||||||
throw new \Exception(sprintf('FTN [%s] is not subscribed to [%s]',$ao->ftn,$eao->name));
|
else
|
||||||
|
AreafixRescan::dispatchSync($ao,$eo,$this->argument('days'));
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::SUCCESS;
|
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()
|
public function echoareas()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Echoarea::class)
|
return $this->belongsToMany(Echoarea::class)
|
||||||
|
->using(AddressEchoarea::class)
|
||||||
->orderBy('name')
|
->orderBy('name')
|
||||||
->withPivot(['subscribed']);
|
->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');
|
: $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 */
|
/* 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;
|
use MessagePath,PageTemplate;
|
||||||
|
|
||||||
private const LOGKEY = 'NCH';
|
private const LOGKEY = 'ANC';
|
||||||
|
|
||||||
private Netmail $mo;
|
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