Compare commits
5 Commits
fdede4fca9
...
8fb3a21fcd
Author | SHA1 | Date | |
---|---|---|---|
8fb3a21fcd | |||
1d354da6e3 | |||
0bc3d4cf60 | |||
38795b83bf | |||
73cf421739 |
@ -5,20 +5,19 @@ namespace App\Casts;
|
||||
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CompressedString implements CastsAttributes
|
||||
class CompressedStringOrNull implements CastsAttributes
|
||||
{
|
||||
/**
|
||||
* Cast the given value.
|
||||
*
|
||||
* For postgresl bytea columns the value is a resource stream
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
* @return string|null
|
||||
* @note postgres bytea columns the value is a resource stream
|
||||
*/
|
||||
public function get($model,string $key,mixed $value,array $attributes): string
|
||||
public function get(Model $model,string $key,mixed $value,array $attributes): ?string
|
||||
{
|
||||
// For stream resources, we to fseek in case we've already read it.
|
||||
if (is_resource($value))
|
||||
@ -28,13 +27,7 @@ class CompressedString implements CastsAttributes
|
||||
? stream_get_contents($value)
|
||||
: $value;
|
||||
|
||||
// If we get an error decompressing, it might not be zstd (or its already been done)
|
||||
try {
|
||||
return $value ? zstd_uncompress(base64_decode($value)) : '';
|
||||
|
||||
} catch (\ErrorException $e) {
|
||||
return $value;
|
||||
}
|
||||
return $value ? zstd_uncompress(base64_decode($value)) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,10 +37,10 @@ class CompressedString implements CastsAttributes
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function set($model,string $key,$value,array $attributes): string
|
||||
public function set(Model $model,string $key,$value,array $attributes): ?string
|
||||
{
|
||||
return $value ? base64_encode(zstd_compress($value)) : '';
|
||||
return $value ? base64_encode(zstd_compress($value)) : NULL;
|
||||
}
|
||||
}
|
29
app/Casts/UTF8StringOrNull.php
Normal file
29
app/Casts/UTF8StringOrNull.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Casts;
|
||||
|
||||
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class UTF8StringOrNull implements CastsAttributes
|
||||
{
|
||||
/**
|
||||
* Cast the given value.
|
||||
*
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function get(Model $model,string $key,mixed $value,array $attributes): ?string
|
||||
{
|
||||
return $value ? utf8_decode($value) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the given value for storage.
|
||||
*
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function set(Model $model,string $key,mixed $value,array $attributes): ?string
|
||||
{
|
||||
return $value ? utf8_encode($value) : NULL;
|
||||
}
|
||||
}
|
@ -673,7 +673,7 @@ class Message extends FTNBase
|
||||
* @return Echomail|Netmail
|
||||
* @throws InvalidPacketException
|
||||
*/
|
||||
private function unpackMessage(string $message,Echomail|Netmail $o): Echomail|Netmail
|
||||
public function unpackMessage(string $message,Echomail|Netmail $o): Echomail|Netmail
|
||||
{
|
||||
// Remove DOS \n\r
|
||||
$message = preg_replace("/\n\r/","\r",$message);
|
||||
@ -796,6 +796,9 @@ class Message extends FTNBase
|
||||
$ptr_content_start = $ptr_end-$ptr_start;
|
||||
}
|
||||
|
||||
// Trim any right \r from the message
|
||||
$o->msg = rtrim($o->msg,"\r");
|
||||
|
||||
// Quick validation that we are done
|
||||
if ($ptr_content_start !== strlen($content))
|
||||
throw new InvalidPacketException('There is more data in the message content?');
|
||||
@ -847,9 +850,6 @@ class Message extends FTNBase
|
||||
'replyid' => 'sometimes|min:1',
|
||||
'msg' => 'required|min:1', // @todo max message length?
|
||||
'msg_crc' => 'required|size:32',
|
||||
'tagline' => 'sometimes|min:1|max:255',
|
||||
'tearline' => 'sometimes|min:1|max:255',
|
||||
'origin' => 'sometimes|min:1|max:255',
|
||||
'local' => 'sometimes|boolean',
|
||||
'fftn_id' => 'required|exists:App\Models\Address,id',
|
||||
'tftn_id' => $this->isNetmail() ? 'required|exists:App\Models\Address,id' : 'prohibited',
|
||||
|
@ -7,8 +7,8 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\File\{Receive,Send};
|
||||
use App\Classes\Protocol\EMSI;
|
||||
use App\Classes\Sock\Exception\SocketException;
|
||||
use App\Classes\Sock\SocketClient;
|
||||
use App\Classes\Sock\SocketException;
|
||||
use App\Models\{Address,Mailer,Setup,System,SystemLog};
|
||||
|
||||
// @todo after receiving a mail packet/file, dont acknowledge it until we can validate that we can read it properly.
|
||||
|
@ -11,8 +11,8 @@ use League\Flysystem\UnreadableFileEncountered;
|
||||
use App\Classes\Crypt;
|
||||
use App\Classes\Node;
|
||||
use App\Classes\Protocol as BaseProtocol;
|
||||
use App\Classes\Sock\Exception\SocketException;
|
||||
use App\Classes\Sock\SocketClient;
|
||||
use App\Classes\Sock\SocketException;
|
||||
use App\Exceptions\{FileGrewException,InvalidFTNException};
|
||||
use App\Models\{Address,Mailer};
|
||||
|
||||
|
@ -110,7 +110,7 @@ final class DNS extends BaseProtocol
|
||||
$this->query = new BaseProtocol\DNS\Query($this->client->read(0,512));
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error(sprintf('%s:! Ignoring bad DNS query (%s)',self::LOGKEY,$e->getMessage()));
|
||||
Log::notice(sprintf('%s:! Ignoring bad DNS query (%s)',self::LOGKEY,$e->getMessage()));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -119,7 +119,7 @@ final class DNS extends BaseProtocol
|
||||
|
||||
// If the wrong class
|
||||
if ($this->query->class !== self::DNS_QUERY_IN) {
|
||||
Log::error(sprintf('%s:! We only service Internet queries [%d]',self::LOGKEY,$this->query->class));
|
||||
Log::notice(sprintf('%s:! We only service Internet queries [%d]',self::LOGKEY,$this->query->class));
|
||||
return $this->reply(self::DNS_NOTIMPLEMENTED,[],$this->soa());
|
||||
}
|
||||
|
||||
@ -272,7 +272,7 @@ final class DNS extends BaseProtocol
|
||||
|
||||
// Other attributes return NOTIMPL
|
||||
default:
|
||||
Log::error(sprintf('%s:! We dont support DNS query types [%d]',self::LOGKEY,$this->query->type));
|
||||
Log::notice(sprintf('%s:! We dont support DNS query types [%d]',self::LOGKEY,$this->query->type));
|
||||
|
||||
return $this->reply(self::DNS_NOTIMPLEMENTED,[],$this->soa());
|
||||
}
|
||||
@ -309,14 +309,14 @@ final class DNS extends BaseProtocol
|
||||
|
||||
private function nameerr(): int
|
||||
{
|
||||
Log::error(sprintf('%s:! DNS query for a resource we dont manage [%s]',self::LOGKEY,$this->query->domain));
|
||||
Log::notice(sprintf('%s:! DNS query for a resource we dont manage [%s]',self::LOGKEY,$this->query->domain));
|
||||
|
||||
return $this->reply(self::DNS_NAMEERR,[],$this->soa());
|
||||
}
|
||||
|
||||
private function nodata(): int
|
||||
{
|
||||
Log::error(sprintf('%s:! DNS query for a resource we dont manage [%s] in our zone(s)',self::LOGKEY,$this->query->domain));
|
||||
Log::notice(sprintf('%s:! DNS query for a resource we dont manage [%s] in our zone(s)',self::LOGKEY,$this->query->domain));
|
||||
|
||||
return $this->reply(self::DNS_NOERROR,[],$this->soa());
|
||||
}
|
||||
|
@ -6,12 +6,12 @@ use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\Protocol as BaseProtocol;
|
||||
use App\Classes\Sock\Exception\SocketException;
|
||||
use App\Classes\Sock\SocketClient;
|
||||
use App\Classes\Sock\SocketException;
|
||||
use App\Exceptions\InvalidFTNException;
|
||||
use App\Models\{Address,Mailer,Setup};
|
||||
use App\Interfaces\CRC as CRCInterface;
|
||||
use App\Interfaces\Zmodem as ZmodemInterface;
|
||||
use App\Models\{Address,Mailer,Setup};
|
||||
use App\Traits\CRC as CRCTrait;
|
||||
|
||||
// http://ftsc.org/docs/fsc-0056.001
|
||||
|
@ -5,9 +5,9 @@ namespace App\Classes\Protocol;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\{Node,Protocol};
|
||||
use App\Classes\Protocol\Zmodem as ZmodemClass;
|
||||
use App\Classes\File\{Receive,Send};
|
||||
use App\Classes\Sock\{SocketClient,SocketException};
|
||||
use App\Classes\Sock\Exception\SocketException;
|
||||
use App\Classes\Sock\SocketClient;
|
||||
use App\Interfaces\CRC as CRCInterface;
|
||||
use App\Interfaces\Zmodem as ZmodemInterface;
|
||||
use App\Models\{Address,Mailer};
|
||||
|
6
app/Classes/Sock/Exception/HAproxyException.php
Normal file
6
app/Classes/Sock/Exception/HAproxyException.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Sock\Exception;
|
||||
|
||||
final class HAproxyException extends \Exception {
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Sock;
|
||||
namespace App\Classes\Sock\Exception;
|
||||
|
||||
// @todo Can we change this to use socket_strerr() && socket_last_error()
|
||||
final class SocketException extends \Exception {
|
@ -6,6 +6,8 @@ use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Classes\Sock\Exception\{HAproxyException,SocketException};
|
||||
|
||||
/**
|
||||
* Class SocketClient
|
||||
*
|
||||
@ -57,34 +59,26 @@ final class SocketClient {
|
||||
if (config('fido.haproxy')) {
|
||||
Log::debug(sprintf('%s:+ HAPROXY connection host [%s] on port [%d] (%s)',self::LOGKEY,$this->address_remote,$this->port_remote,$this->type));
|
||||
|
||||
if ($this->read(5,12) !== "\x0d\x0a\x0d\x0a\x00\x0d\x0aQUIT\x0a") {
|
||||
Log::error(sprintf('%s:! Failed to initialise HAPROXY connection',self::LOGKEY));
|
||||
throw new SocketException(SocketException::CANT_CONNECT,'Failed to initialise HAPROXY connection');
|
||||
}
|
||||
if ($this->read(5,12) !== "\x0d\x0a\x0d\x0a\x00\x0d\x0aQUIT\x0a")
|
||||
throw new HAproxyException('Failed to initialise HAPROXY connection');
|
||||
|
||||
// Version/Command
|
||||
$vc = $this->read_ch(5);
|
||||
|
||||
if (($x=($vc>>4)&0x7) !== 2) {
|
||||
Log::error(sprintf('%s:! HAPROXY version [%d] is not handled',self::LOGKEY,$x));
|
||||
|
||||
throw new SocketException(SocketException::CANT_CONNECT,'Unknown HAPROXY version');
|
||||
}
|
||||
if (($x=($vc>>4)&0x7) !== 2)
|
||||
throw new HAproxyException(sprintf('Unknown HAPROXY version [%d]',$x));
|
||||
|
||||
switch ($x=($vc&0x7)) {
|
||||
// HAPROXY internal
|
||||
case 0:
|
||||
Log::debug(sprintf('%s:! HAPROXY internal health-check',self::LOGKEY));
|
||||
throw new SocketException(SocketException::CANT_CONNECT,'Healthcheck');
|
||||
throw new HAproxyException('HAPROXY internal health-check');
|
||||
|
||||
// PROXY connection
|
||||
case 1:
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::error(sprintf('%s:! HAPROXY command [%d] is not handled',self::LOGKEY,$x));
|
||||
|
||||
throw new SocketException(SocketException::CANT_CONNECT,'Unknown HAPROXY command');
|
||||
throw new HAproxyException(sprintf('HAPROXY command [%d] is not handled',$x));
|
||||
}
|
||||
|
||||
// Protocol/Address Family
|
||||
@ -101,8 +95,7 @@ final class SocketClient {
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::error(sprintf('%s:! HAPROXY protocol [%d] is not handled',self::LOGKEY,$x));
|
||||
throw new SocketException(SocketException::CANT_CONNECT,'Unknown HAPROXY protocol');
|
||||
throw new HAproxyException(sprintf('HAPROXY protocol [%d] is not handled',$x));
|
||||
}
|
||||
|
||||
switch ($x=($pa&0x7)) {
|
||||
@ -110,8 +103,7 @@ final class SocketClient {
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::error(sprintf('%s:! HAPROXY address family [%d] is not handled',self::LOGKEY,$x));
|
||||
throw new SocketException(SocketException::CANT_CONNECT,'Unknown HAPROXY address family');
|
||||
throw new HAproxyException(sprintf('HAPROXY address family [%d] is not handled',$x));
|
||||
}
|
||||
|
||||
$len = Arr::get(unpack('n',$this->read(5,2)),1);
|
||||
@ -126,8 +118,7 @@ final class SocketClient {
|
||||
$dst = inet_ntop($this->read(5,16));
|
||||
|
||||
} else {
|
||||
Log::error(sprintf('%s:! HAPROXY address len [%d:%d] is not handled',self::LOGKEY,$p,$len));
|
||||
throw new SocketException(SocketException::CANT_CONNECT,'Unknown HAPROXY address length');
|
||||
throw new HAproxyException(sprintf('HAPROXY address len [%d:%d] is not handled',$p,$len));
|
||||
}
|
||||
|
||||
$src_port = unpack('n',$this->read(5,2));
|
||||
|
@ -4,6 +4,8 @@ namespace App\Classes\Sock;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\Sock\Exception\{HAproxyException,SocketException};
|
||||
|
||||
final class SocketServer {
|
||||
private const LOGKEY = 'SS-';
|
||||
|
||||
@ -128,8 +130,13 @@ final class SocketServer {
|
||||
try {
|
||||
$r = new SocketClient($accept);
|
||||
|
||||
} catch (HAproxyException $e) {
|
||||
Log::notice(sprintf('%s:! HAPROXY Exception [%s]',self::LOGKEY,$e->getMessage()));
|
||||
socket_close($accept);
|
||||
continue;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error(sprintf('%s:! Creating Socket client failed? [%s]',self::LOGKEY,$e->getMessage()));
|
||||
Log::notice(sprintf('%s:! Creating Socket client failed? [%s]',self::LOGKEY,$e->getMessage()));
|
||||
socket_close($accept);
|
||||
continue;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\Protocol\Binkp;
|
||||
use App\Classes\Sock\SocketException;
|
||||
use App\Classes\Sock\Exception\SocketException;
|
||||
use App\Classes\Sock\SocketServer;
|
||||
use App\Models\Setup;
|
||||
|
||||
|
@ -6,7 +6,7 @@ use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\Protocol\EMSI;
|
||||
use App\Classes\Sock\SocketException;
|
||||
use App\Classes\Sock\Exception\SocketException;
|
||||
use App\Classes\Sock\SocketServer;
|
||||
use App\Models\Setup;
|
||||
|
||||
|
@ -6,7 +6,8 @@ use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Classes\Protocol\{Binkp,DNS,EMSI};
|
||||
use App\Classes\Sock\{SocketException,SocketServer};
|
||||
use App\Classes\Sock\Exception\SocketException;
|
||||
use App\Classes\Sock\SocketServer;
|
||||
use App\Models\Setup;
|
||||
|
||||
class ServerStart extends Command
|
||||
|
@ -31,7 +31,7 @@ class SystemController extends Controller
|
||||
public function add_edit(SystemRegisterRequest $request, System $o)
|
||||
{
|
||||
if ($request->validated()) {
|
||||
foreach (['name','location','phone','address','port','active','method','pkt_type'] as $key)
|
||||
foreach (['name','location','phone','address','port','active','method','pkt_msgs','pkt_type'] as $key)
|
||||
$o->{$key} = $request->validated($key);
|
||||
|
||||
// Sometimes items
|
||||
@ -507,7 +507,7 @@ class SystemController extends Controller
|
||||
$no->flags = (Message::FLAG_LOCAL|Message::FLAG_PRIVATE|Message::FLAG_CRASH);
|
||||
$no->cost = 0;
|
||||
|
||||
$no->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
||||
$no->set_tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
||||
$no->save();
|
||||
|
||||
Log::info(sprintf('%s:= Areafix to [%s], scheduling a poll',self::LOGKEY,$no->tftn->ftn));
|
||||
|
@ -73,6 +73,7 @@ class SystemRegisterRequest extends FormRequest
|
||||
'hold' => 'sometimes|boolean',
|
||||
'pollmode' => 'required|integer|min:0|max:2',
|
||||
'heartbeat' => 'nullable|integer|min:0|max:48',
|
||||
'pkt_msgs' => 'nullable|integer|min:5',
|
||||
] : []));
|
||||
}
|
||||
}
|
@ -15,8 +15,8 @@ use Illuminate\Support\Facades\Notification;
|
||||
|
||||
use App\Classes\Protocol;
|
||||
use App\Classes\Protocol\{Binkp,EMSI};
|
||||
use App\Classes\Sock\Exception\SocketException;
|
||||
use App\Classes\Sock\SocketClient;
|
||||
use App\Classes\Sock\SocketException;
|
||||
use App\Models\{Address,Mailer,Setup};
|
||||
use App\Notifications\Netmails\PollingFailed;
|
||||
use App\Traits\ObjectIssetFix;
|
||||
|
@ -14,21 +14,17 @@ use Illuminate\Support\Facades\Notification;
|
||||
use App\Classes\FTN\Message;
|
||||
use App\Models\{Echomail,Netmail,User};
|
||||
use App\Notifications\Netmails\{EchoareaNotExist,EchoareaNotSubscribed,EchoareaNoWrite,NetmailForward,NetmailHubNoUser};
|
||||
use App\Traits\{EncodeUTF8,ParseAddresses};
|
||||
use App\Traits\ParseAddresses;
|
||||
|
||||
class MessageProcess implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'JMP';
|
||||
|
||||
use Dispatchable,InteractsWithQueue,Queueable,SerializesModels,ParseAddresses,EncodeUTF8;
|
||||
use Dispatchable,InteractsWithQueue,Queueable,SerializesModels,ParseAddresses;
|
||||
|
||||
private Echomail|Netmail|string $mo;
|
||||
private bool $skipbot;
|
||||
|
||||
private const cast_utf8 = [
|
||||
'mo',
|
||||
];
|
||||
|
||||
/**
|
||||
* Process a message from a packet
|
||||
*
|
||||
@ -54,16 +50,6 @@ class MessageProcess implements ShouldQueue
|
||||
}
|
||||
}
|
||||
|
||||
public function __serialize()
|
||||
{
|
||||
return $this->encode();
|
||||
}
|
||||
|
||||
public function __unserialize(array $values)
|
||||
{
|
||||
$this->decode($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* At this point, we know that the packet is from a system we know about, and the packet is to us:
|
||||
* + From a system that is configured with us, and the password has been validated
|
||||
@ -144,8 +130,8 @@ class MessageProcess implements ShouldQueue
|
||||
// Check if the netmail is to a user, with netmail forwarding enabled
|
||||
$uo = User::active()
|
||||
->where(function($query) {
|
||||
return $query->whereRaw(sprintf("LOWER(name)='%s'",strtolower($this->mo->to)))
|
||||
->orWhereRaw(sprintf("LOWER(alias)='%s'",strtolower($this->mo->to)));
|
||||
return $query->whereRaw(sprintf("LOWER(name)='%s'",strtolower(utf8_encode($this->mo->to))))
|
||||
->orWhereRaw(sprintf("LOWER(alias)='%s'",strtolower(utf8_encode($this->mo->to))));
|
||||
})
|
||||
->whereNotNull('system_id')
|
||||
->single();
|
||||
|
@ -139,7 +139,7 @@ class PacketProcess implements ShouldQueue
|
||||
$count++;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error(sprintf('%s:! Got error dispatching message [%s] (%d:%s-%s).',self::LOGKEY,$msg->msgid,$e->getLine(),$e->getFile(),$e->getMessage()));
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1045,15 +1045,13 @@ class Address extends Model
|
||||
public function getEchomail(): ?Packet
|
||||
{
|
||||
if (($num=$this->echomailWaiting())->count()) {
|
||||
$s = Setup::findOrFail(config('app.id'));
|
||||
|
||||
Log::info(sprintf('%s:= Got [%d] echomails for [%s] for sending',self::LOGKEY,$num->count(),$this->ftn));
|
||||
|
||||
// Limit to max messages
|
||||
if ($num->count() > $s->msgs_pkt)
|
||||
Log::notice(sprintf('%s:= Only sending [%d] echomails for [%s]',self::LOGKEY,$s->msgs_pkt,$this->ftn));
|
||||
if ($num->count() > $this->system->pkt_msgs)
|
||||
Log::notice(sprintf('%s:= Only sending [%d] echomails for [%s]',self::LOGKEY,$this->system->pkt_msgs,$this->ftn));
|
||||
|
||||
return $this->system->packet($this)->mail($num->take($s->msgs_pkt));
|
||||
return $this->system->packet($this)->mail($num->take($this->system->pkt_msgs));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -1103,15 +1101,13 @@ class Address extends Model
|
||||
}
|
||||
|
||||
if (($num=$this->netmailWaiting())->count()) {
|
||||
$s = Setup::findOrFail(config('app.id'));
|
||||
|
||||
Log::debug(sprintf('%s:= Got [%d] netmails for [%s] for sending',self::LOGKEY,$num->count(),$this->ftn));
|
||||
|
||||
// Limit to max messages
|
||||
if ($num->count() > $s->msgs_pkt)
|
||||
Log::alert(sprintf('%s:= Only sending [%d] netmails for [%s]',self::LOGKEY,$num->count(),$this->ftn));
|
||||
if ($num->count() > $this->system->pkt_msgs)
|
||||
Log::alert(sprintf('%s:= Only sending [%d] netmails for [%s]',self::LOGKEY,$this->system->pkt_msgs,$this->ftn));
|
||||
|
||||
return $this->system->packet($this)->mail($num->take($s->msgs_pkt));
|
||||
return $this->system->packet($this)->mail($num->take($this->system->pkt_msgs));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -1145,7 +1141,7 @@ class Address extends Model
|
||||
$c = 0;
|
||||
foreach ($msgs as $oo) {
|
||||
// Only bundle up to max messages
|
||||
if (++$c > $s->msgs_pkt)
|
||||
if (++$c > $s->pkt_msgs)
|
||||
break;
|
||||
|
||||
$o->addMail($oo->packet($this,$passwd));
|
||||
|
@ -11,7 +11,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
use App\Casts\CompressedString;
|
||||
use App\Casts\CompressedStringOrNull;
|
||||
use App\Traits\{QueryCacheableConfig,ScopeActive};
|
||||
|
||||
class Domain extends Model
|
||||
@ -22,7 +22,7 @@ class Domain extends Model
|
||||
private const STATS_MONTHS = 6;
|
||||
|
||||
protected $casts = [
|
||||
'homepage' => CompressedString::class,
|
||||
'homepage' => CompressedStringOrNull::class,
|
||||
];
|
||||
|
||||
/* SCOPES */
|
||||
|
@ -9,7 +9,7 @@ use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Casts\{CollectionOrNull,CompressedString};
|
||||
use App\Casts\{CollectionOrNull,CompressedStringOrNull,UTF8StringOrNull};
|
||||
use App\Classes\FTN\Message;
|
||||
use App\Interfaces\Packet;
|
||||
use App\Traits\{MessageAttributes,MsgID,ParseAddresses,QueryCacheableConfig};
|
||||
@ -32,14 +32,41 @@ final class Echomail extends Model implements Packet
|
||||
public Address $tftn;
|
||||
|
||||
protected $casts = [
|
||||
'to' => UTF8StringOrNull::class,
|
||||
'from' => UTF8StringOrNull::class,
|
||||
'subject' => UTF8StringOrNull::class,
|
||||
'origin' => UTF8StringOrNull::class,
|
||||
'tearline' => UTF8StringOrNull::class,
|
||||
'tagline' => UTF8StringOrNull::class,
|
||||
'datetime' => 'datetime:Y-m-d H:i:s',
|
||||
'kludges' => CollectionOrNull::class,
|
||||
'msg' => CompressedString::class,
|
||||
'msg_src' => CompressedString::class,
|
||||
'msg' => CompressedStringOrNull::class,
|
||||
'msg_src' => CompressedStringOrNull::class,
|
||||
'rogue_seenby' => CollectionOrNull::class,
|
||||
'rogue_path' => CollectionOrNull::class, // @deprecated?
|
||||
];
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'set_echoarea':
|
||||
case 'set_fftn':
|
||||
case 'set_path':
|
||||
case 'set_pkt':
|
||||
case 'set_recvtime':
|
||||
case 'set_seenby':
|
||||
case 'set_sender':
|
||||
|
||||
case 'set_tagline':
|
||||
case 'set_tearline':
|
||||
case 'set_origin':
|
||||
return $this->set->get($key);
|
||||
|
||||
default:
|
||||
return parent::__get($key);
|
||||
}
|
||||
}
|
||||
|
||||
public function __set($key,$value)
|
||||
{
|
||||
switch ($key) {
|
||||
@ -65,7 +92,7 @@ final class Echomail extends Model implements Packet
|
||||
case 'set_pkt':
|
||||
case 'set_recvtime':
|
||||
case 'set_sender':
|
||||
// @todo We'll normalise these values when saving the netmail
|
||||
|
||||
case 'set_tagline':
|
||||
case 'set_tearline':
|
||||
case 'set_origin':
|
||||
@ -95,6 +122,26 @@ final class Echomail extends Model implements Packet
|
||||
static::creating(function($model) {
|
||||
if (isset($model->errors) && $model->errors->count())
|
||||
throw new \Exception('Cannot save, validation errors exist');
|
||||
|
||||
if ($model->set->has('set_tagline'))
|
||||
$model->tagline_id = Tagline::firstOrCreate(['value'=>$model->set_tagline])->id;
|
||||
|
||||
if ($model->set->has('set_tearline'))
|
||||
$model->tearline_id = Tearline::firstOrCreate(['value'=>$model->set_tearline])->id;
|
||||
|
||||
if ($model->set->has('set_origin')) {
|
||||
// Make sure our origin contains our FTN
|
||||
$m = [];
|
||||
if ((preg_match('#^(.*)\s+\(([0-9]+:[0-9]+/[0-9]+.*)\)+\s*$#',$model->set_origin,$m))
|
||||
&& (Address::findFTN($m[2])->id === $model->fftn_id))
|
||||
$model->origin_id = Origin::firstOrCreate(['value'=>$m[1]])->id;
|
||||
}
|
||||
|
||||
// If we can rebuild the message content, then we can do away with msg_src
|
||||
if (md5($model->rebuildMessage()) === $model->msg_crc) {
|
||||
Log::debug(sprintf('%s:- Pruning message source, since we can rebuild the message [%s]',self::LOGKEY,$model->msgid));
|
||||
$model->msg_src = NULL;
|
||||
}
|
||||
});
|
||||
|
||||
// @todo if the message is updated with new SEEN-BY's from another route, we'll delete the pending export for systems (if there is one)
|
||||
@ -207,12 +254,6 @@ final class Echomail extends Model implements Packet
|
||||
return $this->belongsTo(Echoarea::class);
|
||||
}
|
||||
|
||||
public function fftn()
|
||||
{
|
||||
return $this->belongsTo(Address::class)
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function seenby()
|
||||
{
|
||||
return $this->belongsToMany(Address::class,'echomail_seenby')
|
||||
|
@ -11,12 +11,11 @@ use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
use App\Casts\{CollectionOrNull,CompressedString};
|
||||
use App\Traits\EncodeUTF8;
|
||||
use App\Casts\{CollectionOrNull,CompressedStringOrNull};
|
||||
|
||||
class File extends Model
|
||||
{
|
||||
use SoftDeletes,EncodeUTF8;
|
||||
use SoftDeletes;
|
||||
|
||||
private const LOGKEY = 'MF-';
|
||||
private bool $no_export = FALSE;
|
||||
@ -28,18 +27,13 @@ class File extends Model
|
||||
protected $casts = [
|
||||
'kludges' => CollectionOrNull::class,
|
||||
'datetime' => 'datetime:Y-m-d H:i:s',
|
||||
'desc' => CompressedString::class,
|
||||
'ldesc' => CompressedString::class,
|
||||
'desc' => CompressedStringOrNull::class,
|
||||
'ldesc' => CompressedStringOrNull::class,
|
||||
'rogue_seenby' => CollectionOrNull::class,
|
||||
'rogue_path' => CollectionOrNull::class,
|
||||
'size' => 'int',
|
||||
];
|
||||
|
||||
private const cast_utf8 = [
|
||||
'desc',
|
||||
'ldesc',
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
@ -10,7 +10,7 @@ use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Casts\{CollectionOrNull,CompressedString};
|
||||
use App\Casts\{CollectionOrNull,CompressedStringOrNull,UTF8StringOrNull};
|
||||
use App\Interfaces\Packet;
|
||||
use App\Pivots\ViaPivot;
|
||||
use App\Traits\{MessageAttributes,MsgID};
|
||||
@ -32,13 +32,40 @@ final class Netmail extends Model implements Packet
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'to' => UTF8StringOrNull::class,
|
||||
'from' => UTF8StringOrNull::class,
|
||||
'subject' => UTF8StringOrNull::class,
|
||||
'origin' => UTF8StringOrNull::class,
|
||||
'tearline' => UTF8StringOrNull::class,
|
||||
'tagline' => UTF8StringOrNull::class,
|
||||
'datetime' => 'datetime:Y-m-d H:i:s',
|
||||
'kludges' => CollectionOrNull::class,
|
||||
'msg' => CompressedString::class,
|
||||
'msg_src' => CompressedString::class,
|
||||
'msg' => CompressedStringOrNull::class,
|
||||
'msg_src' => CompressedStringOrNull::class,
|
||||
'sent_at' => 'datetime:Y-m-d H:i:s',
|
||||
];
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'set_fftn':
|
||||
case 'set_tftn':
|
||||
case 'set_path':
|
||||
case 'set_pkt':
|
||||
case 'set_recvtime':
|
||||
case 'set_seenby':
|
||||
case 'set_sender':
|
||||
|
||||
case 'set_tagline':
|
||||
case 'set_tearline':
|
||||
case 'set_origin':
|
||||
return $this->set->get($key);
|
||||
|
||||
default:
|
||||
return parent::__get($key);
|
||||
}
|
||||
}
|
||||
|
||||
public function __set($key,$value)
|
||||
{
|
||||
switch ($key) {
|
||||
@ -61,7 +88,7 @@ final class Netmail extends Model implements Packet
|
||||
case 'set_pkt':
|
||||
case 'set_recvtime':
|
||||
case 'set_sender':
|
||||
// @todo We'll normalise these values when saving the netmail
|
||||
|
||||
case 'set_tagline':
|
||||
case 'set_tearline':
|
||||
case 'set_origin':
|
||||
@ -88,6 +115,26 @@ final class Netmail extends Model implements Packet
|
||||
static::creating(function($model) {
|
||||
if (isset($model->errors) && $model->errors->count())
|
||||
throw new \Exception('Cannot save, validation errors exist');
|
||||
|
||||
if ($model->set->has('set_tagline'))
|
||||
$model->tagline_id = Tagline::firstOrCreate(['value'=>$model->set_tagline])->id;
|
||||
|
||||
if ($model->set->has('set_tearline'))
|
||||
$model->tearline_id = Tearline::firstOrCreate(['value'=>$model->set_tearline])->id;
|
||||
|
||||
if ($model->set->has('set_origin')) {
|
||||
// Make sure our origin contains our FTN
|
||||
$m = [];
|
||||
if ((preg_match('#^(.*)\s+\(([0-9]+:[0-9]+/[0-9]+.*)\)+\s*$#',$model->set_origin,$m))
|
||||
&& (Address::findFTN($m[2])->id === $model->fftn_id))
|
||||
$model->origin_id = Origin::firstOrCreate(['value'=>$m[1]])->id;
|
||||
}
|
||||
|
||||
// If we can rebuild the message content, then we can do away with msg_src
|
||||
if (md5($model->rebuildMessage()) === $model->msg_crc) {
|
||||
Log::debug(sprintf('%s:- Pruning message source, since we can rebuild the message [%s]',self::LOGKEY,$model->msgid));
|
||||
$model->msg_src = NULL;
|
||||
}
|
||||
});
|
||||
|
||||
static::created(function($model) {
|
||||
@ -154,27 +201,12 @@ final class Netmail extends Model implements Packet
|
||||
]);
|
||||
}
|
||||
|
||||
// Save our origin, tearline & tagline
|
||||
if ($model->set->has('set_tagline'))
|
||||
$model->tagline = $model->set->get('set_tagline');
|
||||
if ($model->set->has('set_tearline'))
|
||||
$model->tearline = $model->set->get('set_tearline');
|
||||
if ($model->set->has('set_origin'))
|
||||
$model->origin = $model->set->get('set_origin');
|
||||
|
||||
$model->save();
|
||||
});
|
||||
}
|
||||
|
||||
/* RELATIONS */
|
||||
|
||||
public function fftn()
|
||||
{
|
||||
return $this
|
||||
->belongsTo(Address::class)
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function path()
|
||||
{
|
||||
return $this->belongsToMany(Address::class,'netmail_path')
|
||||
|
20
app/Models/Origin.php
Normal file
20
app/Models/Origin.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Origin extends Model
|
||||
{
|
||||
//use HasFactory;
|
||||
|
||||
public const UPDATED_AT = NULL;
|
||||
|
||||
protected $fillable = ['value'];
|
||||
|
||||
public function complete(Address $o): string
|
||||
{
|
||||
return sprintf(' * Origin: %s (%s)',$this->value,$o->point_id ? $o->ftn4d : $o->ftn3d);
|
||||
}
|
||||
}
|
@ -170,6 +170,11 @@ class System extends Model
|
||||
}
|
||||
}
|
||||
|
||||
public function getPktMsgsAttribute(?int $val): int
|
||||
{
|
||||
return $val ?: Setup::findOrFail(config('app.id'))->msgs_pkt;
|
||||
}
|
||||
|
||||
/* METHODS */
|
||||
|
||||
public function echoareas()
|
||||
|
20
app/Models/Tagline.php
Normal file
20
app/Models/Tagline.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Tagline extends Model
|
||||
{
|
||||
//use HasFactory;
|
||||
|
||||
public const UPDATED_AT = NULL;
|
||||
|
||||
protected $fillable = ['value'];
|
||||
|
||||
public function complete(): string
|
||||
{
|
||||
return sprintf('... %s',$this->value);
|
||||
}
|
||||
}
|
20
app/Models/Tearline.php
Normal file
20
app/Models/Tearline.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Tearline extends Model
|
||||
{
|
||||
//use HasFactory;
|
||||
|
||||
public const UPDATED_AT = NULL;
|
||||
|
||||
protected $fillable = ['value'];
|
||||
|
||||
public function complete(): string
|
||||
{
|
||||
return sprintf('--- %s',$this->value);
|
||||
}
|
||||
}
|
@ -58,7 +58,7 @@ abstract class Echomails extends Notification //implements ShouldQueue
|
||||
|
||||
$o->flags = (Message::FLAG_LOCAL);
|
||||
|
||||
$o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
||||
$o->set_tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ class AbsentNodes extends Echomails
|
||||
$o->subject = 'Status changes for nodes';
|
||||
$o->fftn_id = ($x=our_address($echoarea->domain)->last())->id;
|
||||
$o->kludges->put('CHRS:','CP437 2');
|
||||
$o->origin = sprintf('%s (%s)',Setup::PRODUCT_NAME,$x->ftn4d);
|
||||
|
||||
// Message
|
||||
$msg = new Page;
|
||||
@ -95,7 +94,8 @@ class AbsentNodes extends Echomails
|
||||
$msg->addText("\rEmails and/or Netmails have been sent to these nodes. If you can help let them know that they have outstanding mail on the Hub, that would be helpful :)");
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'When life gives you lemons, freeze them and throw them back.';
|
||||
$o->set_tagline = 'When life gives you lemons, freeze them and throw them back.';
|
||||
$o->set_origin = sprintf('%s (%s)',Setup::PRODUCT_NAME,$x->ftn4d);
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -50,7 +50,6 @@ class Test extends Echomails
|
||||
$o->replyid = $this->mo->msgid;
|
||||
$o->subject = 'Test Reply';
|
||||
$o->kludges->put('CHRS:',$this->mo->kludges->get('chrs') ?: 'CP437 2');
|
||||
$o->origin = sprintf('%s (%s)',Setup::PRODUCT_NAME,$x->ftn4d);
|
||||
|
||||
// Message
|
||||
$msg = new Page;
|
||||
@ -74,7 +73,8 @@ class Test extends Echomails
|
||||
$msg->addText($this->message_path($this->mo));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'I ate a clock yesterday, it was very time-consuming.';
|
||||
$o->set_tagline = 'I ate a clock yesterday, it was very time-consuming.';
|
||||
$o->set_origin = sprintf('%s (%s)',Setup::PRODUCT_NAME,$x->ftn4d);
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -64,7 +64,7 @@ abstract class Netmails extends Notification //implements ShouldQueue
|
||||
$o->flags = (Message::FLAG_LOCAL|Message::FLAG_PRIVATE);
|
||||
$o->cost = 0;
|
||||
|
||||
$o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
||||
$o->set_tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ class AddressLink extends Netmails
|
||||
));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'Address Linking...';
|
||||
$o->set_tagline = 'Address Linking...';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -55,7 +55,7 @@ class Areafix extends Netmails
|
||||
$msg->addText($this->message_path($this->mo));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'Why did the robot cross the road? The chicken programmed it.';
|
||||
$o->set_tagline = 'Why did the robot cross the road? The chicken programmed it.';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -55,7 +55,7 @@ class NotConfiguredHere extends Netmails
|
||||
$msg->addText($this->message_path($this->mo));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'Why did the robot cross the road? The chicken programmed it.';
|
||||
$o->set_tagline = 'Why did the robot cross the road? The chicken programmed it.';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -63,7 +63,7 @@ class EchoareaNoWrite extends Netmails
|
||||
$msg->addText($this->message_path($this->mo));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'See something wrong? Do something right.';
|
||||
$o->set_tagline = 'See something wrong? Do something right.';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -65,7 +65,7 @@ class EchoareaNotExist extends Netmails
|
||||
$msg->addText($this->message_path($this->mo));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'Don\'t let your trash become someone else\'s treasure. Feed your shredder often.';
|
||||
$o->set_tagline = 'Don\'t let your trash become someone else\'s treasure. Feed your shredder often.';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -64,7 +64,7 @@ class EchoareaNotSubscribed extends Netmails
|
||||
$msg->addText($this->message_path($this->mo));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'Don\'t let your trash become someone else\'s treasure. Feed your shredder.';
|
||||
$o->set_tagline = 'Don\'t let your trash become someone else\'s treasure. Feed your shredder.';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -64,7 +64,7 @@ class EchomailBadAddress extends Netmails
|
||||
$msg->addText($this->message_path($this->mo));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'I enjoyed reading your message, even though nobody else will get it :)';
|
||||
$o->set_tagline = 'I enjoyed reading your message, even though nobody else will get it :)';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -61,7 +61,7 @@ class NetmailForward extends Netmails
|
||||
$msg->addText(sprintf("To avoid receiving this netmail, send messages to [%s] to [%s].\r\r",$this->mo->to,$this->ao->ftn3d));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'Thank you so much for your mail. I love it already.';
|
||||
$o->set_tagline = 'Thank you so much for your mail. I love it already.';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -64,7 +64,7 @@ class NetmailHubNoUser extends Netmails
|
||||
$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->set_tagline = 'Do you think it was fate which brought us together? Nah, bad luck :(';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -50,7 +50,7 @@ class NodeDelisted extends Netmails //implements ShouldQueue
|
||||
->addText(sprintf('If you think about returning to %s, then reach out and we can get you back online pretty quickly.',$x));
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'You\'ve been DE-LISTED';
|
||||
$o->set_tagline = 'You\'ve been DE-LISTED';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -55,7 +55,7 @@ class NodeMarkedDown extends Netmails //implements ShouldQueue
|
||||
->addText("If you think you've received this netmail by mistake or need help, please let me know.\r");
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'Pending de-list';
|
||||
$o->set_tagline = 'Pending de-list';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -55,7 +55,7 @@ class NodeMarkedHold extends Netmails //implements ShouldQueue
|
||||
->addText("If you think you've received this netmail by mistake or need help, please let me know.\r");
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'You\'ve been marked HOLD';
|
||||
$o->set_tagline = 'You\'ve been marked HOLD';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -62,7 +62,7 @@ class PacketPasswordInvalid extends Netmails
|
||||
$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->set_tagline = 'Safety first, password second.';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -63,7 +63,7 @@ class Ping extends Netmails
|
||||
$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->set_tagline = 'My ping pong opponent was not happy with my serve. He kept returning it.';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -47,7 +47,7 @@ class PollingFailed extends Netmails
|
||||
$msg->addText("To fix this, update your details that I use in the web interface, or change your system to HOLD while you are there.\r\r");
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'Painful? We can make that painless :)';
|
||||
$o->set_tagline = 'Painful? We can make that painless :)';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -40,7 +40,7 @@ class Test extends Netmails
|
||||
);
|
||||
|
||||
$o->msg = $msg->render();
|
||||
$o->tagline = 'Testing, testing, 1 2 3.';
|
||||
$o->set_tagline = 'Testing, testing, 1 2 3.';
|
||||
|
||||
$o->save();
|
||||
|
||||
|
@ -1,99 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Encode our data so that it can be serialised
|
||||
*/
|
||||
namespace App\Traits;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait EncodeUTF8
|
||||
{
|
||||
private array $_encoded = []; // Remember what we've decoded - when calling getAttribute()
|
||||
|
||||
private function decode(array $values): void
|
||||
{
|
||||
$properties = (new \ReflectionClass($this))->getProperties();
|
||||
|
||||
$class = get_class($this);
|
||||
|
||||
foreach ($properties as $property) {
|
||||
if ($property->isStatic())
|
||||
continue;
|
||||
|
||||
$name = $property->getName();
|
||||
$decode = in_array($name,self::cast_utf8);
|
||||
|
||||
if ($property->isPrivate())
|
||||
$name = "\0{$class}\0{$name}";
|
||||
elseif ($property->isProtected())
|
||||
$name = "\0*\0{$name}";
|
||||
|
||||
if (! array_key_exists($name,$values))
|
||||
continue;
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
try {
|
||||
$property->setValue(
|
||||
$this,$decode ? utf8_decode($values[$name]) : $values[$name]
|
||||
);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
dd(['e'=>$e->getMessage(),'name'=>$name,'values'=>$values[$name],'decode'=>$decode]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function encode(): array
|
||||
{
|
||||
$values = [];
|
||||
|
||||
$properties = (new \ReflectionClass($this))->getProperties();
|
||||
|
||||
$class = get_class($this);
|
||||
|
||||
foreach ($properties as $property) {
|
||||
// Dont serialize the validation error
|
||||
if (($property->name === 'errors') || $property->isStatic())
|
||||
continue;
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
if (! $property->isInitialized($this))
|
||||
continue;
|
||||
|
||||
$name = $property->getName();
|
||||
$encode = in_array($name,self::cast_utf8);
|
||||
|
||||
if ($property->isPrivate())
|
||||
$name = "\0{$class}\0{$name}";
|
||||
elseif ($property->isProtected())
|
||||
$name = "\0*\0{$name}";
|
||||
|
||||
$property->setAccessible(true);
|
||||
$value = $property->getValue($this);
|
||||
$values[$name] = $encode ? utf8_encode($value) : $value;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
public function getAttribute($key)
|
||||
{
|
||||
if (in_array($key,self::cast_utf8) && Arr::get($this->attributes,$key) && (! Arr::get($this->_encoded,$key))) {
|
||||
// We need to get it from the parent first, taking into account any casting
|
||||
$this->attributes[$key] = utf8_decode(parent::getAttribute($key));
|
||||
$this->_encoded[$key] = TRUE;
|
||||
|
||||
return $this->attributes[$key];
|
||||
}
|
||||
|
||||
return Arr::get($this->_encoded,$key) ? $this->attributes[$key] : parent::getAttribute($key);
|
||||
}
|
||||
|
||||
public function setAttribute($key,$value)
|
||||
{
|
||||
return parent::setAttribute($key,in_array($key,self::cast_utf8) ? utf8_encode($value) : $value);
|
||||
}
|
||||
}
|
@ -11,28 +11,15 @@ use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\MessageBag;
|
||||
|
||||
use App\Classes\FTN\Message;
|
||||
use App\Models\{Address,Echomail};
|
||||
use App\Models\{Address,Echomail,Origin,Tagline,Tearline};
|
||||
|
||||
trait MessageAttributes
|
||||
{
|
||||
use EncodeUTF8;
|
||||
|
||||
// Items we need to set when creating()
|
||||
public Collection $set;
|
||||
// Validation Errors
|
||||
public ?MessageBag $errors = NULL;
|
||||
|
||||
private const cast_utf8 = [
|
||||
'to',
|
||||
'from',
|
||||
'subject',
|
||||
'msg',
|
||||
'msg_src',
|
||||
'origin',
|
||||
'tearline',
|
||||
'tagline',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
@ -41,26 +28,35 @@ trait MessageAttributes
|
||||
$this->set = collect();
|
||||
}
|
||||
|
||||
/* RELATIONS */
|
||||
|
||||
public function fftn()
|
||||
{
|
||||
return $this
|
||||
->belongsTo(Address::class)
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function origin()
|
||||
{
|
||||
return $this->belongsTo(Origin::class);
|
||||
}
|
||||
|
||||
public function tagline()
|
||||
{
|
||||
return $this->belongsTo(Tagline::class);
|
||||
}
|
||||
|
||||
public function tearline()
|
||||
{
|
||||
return $this->belongsTo(Tearline::class);
|
||||
}
|
||||
|
||||
/* ATTRIBUTES */
|
||||
|
||||
public function getContentAttribute(): string
|
||||
{
|
||||
if ($this->msg_src)
|
||||
return $this->msg_src;
|
||||
|
||||
// If we have a msg_src attribute, we'll use that
|
||||
$result = $this->msg."\r\r";
|
||||
|
||||
if ($this->tagline)
|
||||
$result .= sprintf("%s\r",$this->tagline);
|
||||
|
||||
if ($this->tearline)
|
||||
$result .= sprintf("%s\r",$this->tearline);
|
||||
|
||||
if ($this->origin)
|
||||
$result .= sprintf("%s",$this->origin);
|
||||
|
||||
return rtrim($result,"\r");
|
||||
return ($this->msg_src) ? $this->msg_src : $this->rebuildMessage();
|
||||
}
|
||||
|
||||
public function getDateAttribute(): Carbon
|
||||
@ -70,38 +66,35 @@ trait MessageAttributes
|
||||
|
||||
public function getOriginAttribute(string $val=NULL): ?string
|
||||
{
|
||||
if ($this->exists && (! $val))
|
||||
return $val;
|
||||
if (($x=$this->getRelationValue('origin')) && $x->value)
|
||||
return $x->complete($this->fftn);
|
||||
|
||||
// If $val is not set, then it may be an unsaved object
|
||||
return sprintf(' * Origin: %s',
|
||||
((! $this->exists) && $this->set->has('set_origin'))
|
||||
? $this->set->get('set_origin')
|
||||
: $val);
|
||||
if (($this->set->has('set_origin')) || ($val))
|
||||
return sprintf(' * Origin: %s',$this->set->get('set_origin',$val));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public function getTaglineAttribute(string $val=NULL): ?string
|
||||
{
|
||||
if ($this->exists && (! $val))
|
||||
return $val;
|
||||
if (($x=$this->getRelationValue('tagline')) && $x->value)
|
||||
return $x->complete();
|
||||
|
||||
// If $val is not set, then it may be an unsaved object
|
||||
return sprintf('... %s',
|
||||
((! $this->exists) && $this->set->has('set_tagline'))
|
||||
? $this->set->get('set_tagline')
|
||||
: $val);
|
||||
if (($this->set->has('set_tagline')) || ($val))
|
||||
return sprintf('... %s',$this->set->get('set_tagline',$val));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public function getTearlineAttribute(string $val=NULL): ?string
|
||||
{
|
||||
if ($this->exists && (! $val))
|
||||
return $val;
|
||||
if (($x=$this->getRelationValue('tearline')) && $x->value)
|
||||
return $x->complete();
|
||||
|
||||
// If $val is not set, then it may be an unsaved object
|
||||
return sprintf('--- %s',
|
||||
((! $this->exists) && $this->set->has('set_tearline'))
|
||||
? $this->set->get('set_tearline')
|
||||
: $val);
|
||||
if (($this->set->has('set_tearline')) || ($val))
|
||||
return sprintf('--- %s',$this->set->get('set_tearline',$val));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* METHODS */
|
||||
@ -177,6 +170,23 @@ trait MessageAttributes
|
||||
return Message::packMessage($this);
|
||||
}
|
||||
|
||||
public function rebuildMessage(): string
|
||||
{
|
||||
// If we have a msg_src attribute, we'll use that
|
||||
$result = $this->msg."\r";
|
||||
|
||||
if ($x=$this->tagline)
|
||||
$result .= sprintf("%s\r",$x);
|
||||
|
||||
if ($x=$this->tearline)
|
||||
$result .= sprintf("%s\r",$x);
|
||||
|
||||
if ($x=$this->origin)
|
||||
$result .= sprintf("%s",$x);
|
||||
|
||||
return rtrim($result,"\r");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return our path in order
|
||||
*
|
||||
|
28
database/migrations/2024_06_01_162644_pktsize_to_systems.php
Normal file
28
database/migrations/2024_06_01_162644_pktsize_to_systems.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('systems', function (Blueprint $table) {
|
||||
$table->integer('pkt_msgs')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('systems', function (Blueprint $table) {
|
||||
$table->dropColumn(['pkt_msgs']);
|
||||
});
|
||||
}
|
||||
};
|
81
database/migrations/2024_06_03_072631_msg_attributes.php
Normal file
81
database/migrations/2024_06_03_072631_msg_attributes.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('taglines', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->timestamp('created_at');
|
||||
$table->softDeletes();
|
||||
$table->string('value')->unique();
|
||||
});
|
||||
|
||||
Schema::create('tearlines', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->timestamp('created_at');
|
||||
$table->softDeletes();
|
||||
$table->string('value')->unique();
|
||||
});
|
||||
|
||||
Schema::create('origins', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->timestamp('created_at');
|
||||
$table->softDeletes();
|
||||
$table->string('value')->unique();
|
||||
});
|
||||
|
||||
Schema::table('echomails', function (Blueprint $table) {
|
||||
$table->bigInteger('tagline_id')->nullable();
|
||||
$table->foreign('tagline_id')->references('id')->on('taglines');
|
||||
|
||||
$table->bigInteger('tearline_id')->nullable();
|
||||
$table->foreign('tearline_id')->references('id')->on('tearlines');
|
||||
|
||||
$table->bigInteger('origin_id')->nullable();
|
||||
$table->foreign('origin_id')->references('id')->on('origins');
|
||||
});
|
||||
|
||||
Schema::table('netmails', function (Blueprint $table) {
|
||||
$table->bigInteger('tagline_id')->nullable();
|
||||
$table->foreign('tagline_id')->references('id')->on('taglines');
|
||||
|
||||
$table->bigInteger('tearline_id')->nullable();
|
||||
$table->foreign('tearline_id')->references('id')->on('tearlines');
|
||||
|
||||
$table->bigInteger('origin_id')->nullable();
|
||||
$table->foreign('origin_id')->references('id')->on('origins');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('netmails', function (Blueprint $table) {
|
||||
$table->dropForeign(['tagline_id']);
|
||||
$table->dropForeign(['tearline_id']);
|
||||
$table->dropForeign(['origin_id']);
|
||||
$table->dropColumn(['tagline_id','tearline_id','origin_id']);
|
||||
});
|
||||
|
||||
Schema::table('echomails', function (Blueprint $table) {
|
||||
$table->dropForeign(['tagline_id']);
|
||||
$table->dropForeign(['tearline_id']);
|
||||
$table->dropForeign(['origin_id']);
|
||||
$table->dropColumn(['tagline_id','tearline_id','origin_id']);
|
||||
});
|
||||
|
||||
Schema::dropIfExists('origins');
|
||||
Schema::dropIfExists('tearlines');
|
||||
Schema::dropIfExists('taglines');
|
||||
}
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
@php
|
||||
use App\Classes\FTN\Packet;
|
||||
use App\Models\{Mailer,User};
|
||||
use App\Models\{Mailer,Setup,User};
|
||||
@endphp
|
||||
|
||||
<!-- $o=System::class -->
|
||||
@ -189,6 +189,20 @@ use App\Models\{Mailer,User};
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Packet Msgs -->
|
||||
<div class="col-2">
|
||||
<label for="pkt_msgs" class="form-label w-100">Packet Msgs</label>
|
||||
<div class="input-group has-validation">
|
||||
<span class="input-group-text"><i class="bi bi-hash"></i></span>
|
||||
<input type="text" class="form-control text-end @error('pkt_msgs') is-invalid @enderror" id="pkt_msgs" placeholder="{{ Setup::MAX_MSGS_PKT }}" name="pkt_msgs" value="{{ old('pkt_msgs',$o->pkt_msgs) }}" @cannot($action,$o)readonly @endcannot>
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@error('pkt_msgs')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user