Correctly storing netmail flags (intransit, local, recv) with senders ID and packet name
This commit is contained in:
parent
7bf957df3a
commit
61ab0614b6
@ -161,9 +161,9 @@ final class Receive extends Item
|
|||||||
try {
|
try {
|
||||||
// Dispatch job.
|
// Dispatch job.
|
||||||
if ($queue)
|
if ($queue)
|
||||||
MessageProcess::dispatch($msg,$f->pktName());
|
MessageProcess::dispatch($msg,$f->pktName(),$this->ao);
|
||||||
else
|
else
|
||||||
MessageProcess::dispatchSync($msg,$f->pktName());
|
MessageProcess::dispatchSync($msg,$f->pktName(),$this->ao);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} 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 dispatching message [%s] (%d:%s-%s).',self::LOGKEY,$msg->msgid,$e->getLine(),$e->getFile(),$e->getMessage()));
|
||||||
|
@ -19,7 +19,7 @@ class PacketProcess extends Command
|
|||||||
protected $signature = 'packet:process'
|
protected $signature = 'packet:process'
|
||||||
.' {file : Packet to process}'
|
.' {file : Packet to process}'
|
||||||
.' {--N|nobot : Dont process bots}'
|
.' {--N|nobot : Dont process bots}'
|
||||||
.' {ftn? : System the packet is from}';
|
.' {ftn : System the packet is from}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
@ -37,17 +37,17 @@ class PacketProcess extends Command
|
|||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$f = new File($this->argument('file'));
|
$f = new File($this->argument('file'));
|
||||||
$s = $this->argument('ftn') ? Address::findFTN($this->argument('ftn'))->system : NULL;
|
$a = Address::findFTN($this->argument('ftn'));
|
||||||
|
|
||||||
foreach ($f as $packet) {
|
foreach ($f as $packet) {
|
||||||
foreach (Packet::process($packet,$f->itemName(),$f->itemSize(),$s) as $msg) {
|
foreach (Packet::process($packet,$f->itemName(),$f->itemSize(),$a->system) as $msg) {
|
||||||
// @todo Quick check that the packet should be processed by us.
|
// @todo Quick check that the packet should be processed by us.
|
||||||
// @todo validate that the packet's zone is in the domain.
|
// @todo validate that the packet's zone is in the domain.
|
||||||
|
|
||||||
$this->info(sprintf('Processing message from [%s] with msgid [%s] in (%s)',$msg->fboss,$msg->msgid,$f->pktName()));
|
$this->info(sprintf('Processing message from [%s] with msgid [%s] in (%s)',$msg->fboss,$msg->msgid,$f->pktName()));
|
||||||
|
|
||||||
// Dispatch job.
|
// Dispatch job.
|
||||||
Job::dispatchSync($msg,$f->pktName(),$this->option('nobot'));
|
Job::dispatchSync($msg,$f->pktName(),$a,$this->option('nobot'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ use Illuminate\Queue\SerializesModels;
|
|||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
use App\Classes\FTN\{Message,Process};
|
use App\Classes\FTN\{Message,Process};
|
||||||
use App\Models\{Echoarea,Echomail,Netmail,Setup};
|
use App\Models\{Address,Echoarea,Echomail,Netmail,Setup};
|
||||||
|
|
||||||
class MessageProcess implements ShouldQueue
|
class MessageProcess implements ShouldQueue
|
||||||
{
|
{
|
||||||
@ -19,16 +19,17 @@ class MessageProcess implements ShouldQueue
|
|||||||
|
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
private Address $sender;
|
||||||
private Message $msg;
|
private Message $msg;
|
||||||
private bool $skipbot;
|
private bool $skipbot;
|
||||||
private string $packet;
|
private string $packet;
|
||||||
|
|
||||||
public function __construct(Message $msg,string $packet,bool $skipbot=FALSE)
|
public function __construct(Message $msg,string $packet,Address $sender,bool $skipbot=FALSE)
|
||||||
{
|
{
|
||||||
// Some checks
|
|
||||||
$this->msg = $msg;
|
$this->msg = $msg;
|
||||||
$this->skipbot = $skipbot;
|
|
||||||
$this->packet = $packet;
|
$this->packet = $packet;
|
||||||
|
$this->sender = $sender;
|
||||||
|
$this->skipbot = $skipbot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,7 +42,7 @@ class MessageProcess implements ShouldQueue
|
|||||||
|
|
||||||
// If we are a netmail
|
// If we are a netmail
|
||||||
if ($this->msg->isNetmail()) {
|
if ($this->msg->isNetmail()) {
|
||||||
Log::info(sprintf('%s:Processing Netmail [%s] to (%s) [%s] from (%s) [%s].',
|
Log::info(sprintf('%s:- Processing Netmail [%s] to (%s) [%s] from (%s) [%s].',
|
||||||
self::LOGKEY,
|
self::LOGKEY,
|
||||||
$this->msg->msgid,
|
$this->msg->msgid,
|
||||||
$this->msg->user_to,$this->msg->tftn,
|
$this->msg->user_to,$this->msg->tftn,
|
||||||
@ -49,12 +50,44 @@ class MessageProcess implements ShouldQueue
|
|||||||
));
|
));
|
||||||
|
|
||||||
// @todo Enable checks to reject old messages
|
// @todo Enable checks to reject old messages
|
||||||
// @todo Enable checks to reject duplicate
|
|
||||||
|
// Check for duplicate messages
|
||||||
|
|
||||||
|
// FTS-0009.001
|
||||||
|
if ($this->msg->msgid) {
|
||||||
|
$o = Netmail::where('msgid',$this->msg->msgid)
|
||||||
|
->where('fftn_id',($x=$this->msg->fboss_o) ? $x->id : NULL)
|
||||||
|
->where('datetime','>',Carbon::now()->subYears(3))
|
||||||
|
->single();
|
||||||
|
|
||||||
|
Log::debug(sprintf('%s:- Checking for duplicate from host id [%d].',self::LOGKEY,($x=$this->msg->fboss_o) ? $x->id : NULL));
|
||||||
|
|
||||||
|
if ($o) {
|
||||||
|
Log::alert(sprintf('%s:! Duplicate netmail [%s] in [%s] from (%s) [%s] to (%s) - ignorning.',
|
||||||
|
self::LOGKEY,
|
||||||
|
$this->msg->msgid,
|
||||||
|
$this->msg->echoarea,
|
||||||
|
$this->msg->user_from,$this->msg->fftn,
|
||||||
|
$this->msg->user_to,
|
||||||
|
));
|
||||||
|
|
||||||
|
if (! $o->msg_crc)
|
||||||
|
$o->msg_crc = md5($this->msg->message);
|
||||||
|
|
||||||
|
$o->save();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @todo Enable checks to see if this is a file request or file send
|
// @todo Enable checks to see if this is a file request or file send
|
||||||
|
|
||||||
$o = $this->create_netmail($this->msg);
|
$o = $this->create_netmail($this->msg);
|
||||||
$o->recv_pkt = $this->packet;
|
$o->set_pkt = $this->packet;
|
||||||
|
$o->set_sender = $this->sender;
|
||||||
$o->set_path = $this->msg->pathaddress;
|
$o->set_path = $this->msg->pathaddress;
|
||||||
|
// Strip any local flag
|
||||||
|
$o->flags &= ~Message::FLAG_LOCAL;
|
||||||
|
|
||||||
// Determine if the message is to this system, or in transit
|
// Determine if the message is to this system, or in transit
|
||||||
if ($ftns->search(function($item) { return $this->msg->tftn === $item->ftn; }) !== FALSE) {
|
if ($ftns->search(function($item) { return $this->msg->tftn === $item->ftn; }) !== FALSE) {
|
||||||
@ -67,7 +100,7 @@ class MessageProcess implements ShouldQueue
|
|||||||
if (! $this->skipbot)
|
if (! $this->skipbot)
|
||||||
foreach (config('process.robots') as $class) {
|
foreach (config('process.robots') as $class) {
|
||||||
if ($processed = $class::handle($this->msg)) {
|
if ($processed = $class::handle($this->msg)) {
|
||||||
$o->local = TRUE;
|
$o->flags |= Message::FLAG_RECD;
|
||||||
$o->save();
|
$o->save();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -76,16 +109,16 @@ class MessageProcess implements ShouldQueue
|
|||||||
|
|
||||||
// We'll ignore messages from *fix users
|
// We'll ignore messages from *fix users
|
||||||
if (in_array(strtolower($this->msg->user_from),['filefix','areafix'])) {
|
if (in_array(strtolower($this->msg->user_from),['filefix','areafix'])) {
|
||||||
$o->local = TRUE;
|
$o->flags |= Message::FLAG_RECD;
|
||||||
$o->save();
|
$o->save();
|
||||||
|
|
||||||
Log::info(sprintf('%s:Ignoring Netmail [%d-%s] to the Hub from (%s) [%s] - its from a bot.',
|
Log::alert(sprintf('%s:! Ignoring Netmail [%s] to the Hub from (%s:%s) - its from a bot [%d].',
|
||||||
self::LOGKEY,
|
self::LOGKEY,
|
||||||
$o->id,
|
|
||||||
$this->msg->msgid,
|
$this->msg->msgid,
|
||||||
$this->msg->user_from,
|
$this->msg->user_from,
|
||||||
$this->msg->fftn)
|
$this->msg->fftn,
|
||||||
);
|
$o->id,
|
||||||
|
));
|
||||||
|
|
||||||
$processed = TRUE;
|
$processed = TRUE;
|
||||||
}
|
}
|
||||||
@ -98,7 +131,7 @@ class MessageProcess implements ShouldQueue
|
|||||||
'Á ÀÄÙÀÄÙÀÄÙÀÄÙ Á '
|
'Á ÀÄÙÀÄÙÀÄÙÀÄÙ Á '
|
||||||
];
|
];
|
||||||
|
|
||||||
Log::info(sprintf('Netmail to the Hub from (%s) [%s] but no users here.',$this->msg->user_from,$this->msg->fftn));
|
Log::alert(sprintf('%s:! Netmail to the Hub from (%s) [%s] but no users here.',self::LOGKEY,$this->msg->user_from,$this->msg->fftn));
|
||||||
|
|
||||||
$reply = "Your Netmail was not processed by the hub and cannot be delivered to anybody (as there are no users here).\r";
|
$reply = "Your Netmail was not processed by the hub and cannot be delivered to anybody (as there are no users here).\r";
|
||||||
|
|
||||||
@ -146,14 +179,15 @@ class MessageProcess implements ShouldQueue
|
|||||||
// @todo In transit loop checking
|
// @todo In transit loop checking
|
||||||
// @todo In transit TRACE response
|
// @todo In transit TRACE response
|
||||||
|
|
||||||
|
$o->flags |= Message::FLAG_INTRANSIT;
|
||||||
$o->save();
|
$o->save();
|
||||||
|
|
||||||
Log::info(sprintf('%s:Netmail [%d-%s] in transit to (%s) [%s] from (%s) [%s].',
|
Log::info(sprintf('%s:= Netmail [%s] in transit to (%s:%s) from (%s:%s) [%d].',
|
||||||
self::LOGKEY,
|
self::LOGKEY,
|
||||||
$o->id,
|
|
||||||
$this->msg->msgid,
|
$this->msg->msgid,
|
||||||
$this->msg->user_to,$this->msg->tftn,
|
$this->msg->user_to,$this->msg->tftn,
|
||||||
$this->msg->user_from,$this->msg->fftn,
|
$this->msg->user_from,$this->msg->fftn,
|
||||||
|
$o->id,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,10 +288,11 @@ class MessageProcess implements ShouldQueue
|
|||||||
$o->rogue_path = $this->msg->rogue_path;
|
$o->rogue_path = $this->msg->rogue_path;
|
||||||
$o->set_path = $this->msg->pathaddress;
|
$o->set_path = $this->msg->pathaddress;
|
||||||
$o->set_seenby = $this->msg->seenaddress;
|
$o->set_seenby = $this->msg->seenaddress;
|
||||||
|
// Record receiving packet and sender
|
||||||
|
|
||||||
$o->save();
|
$o->save();
|
||||||
|
|
||||||
Log::info(sprintf('%s: - Echomail [%s] in [%s] from (%s) [%s] to (%s) - [%s].',
|
Log::info(sprintf('%s:= Echomail [%s] in [%s] from (%s) [%s] to (%s) - [%s].',
|
||||||
self::LOGKEY,
|
self::LOGKEY,
|
||||||
$this->msg->msgid,
|
$this->msg->msgid,
|
||||||
$this->msg->echoarea,
|
$this->msg->echoarea,
|
||||||
|
@ -191,7 +191,7 @@ class Address extends Model
|
|||||||
public function echomails()
|
public function echomails()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Echomail::class,'echomail_seenby')
|
return $this->belongsToMany(Echomail::class,'echomail_seenby')
|
||||||
->withPivot(['sent_at','export_at','packet']);
|
->withPivot(['export_at','sent_at','sent_pkt']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function echomail_from()
|
public function echomail_from()
|
||||||
@ -743,6 +743,6 @@ class Address extends Model
|
|||||||
*/
|
*/
|
||||||
public function session(string $type): ?string
|
public function session(string $type): ?string
|
||||||
{
|
{
|
||||||
return ($x=$this->system->sessions->where('id',$this->zone_id)->first()) ? $x->pivot->{$type} : NULL;
|
return ($this->exists && ($x=$this->system->sessions->where('id',$this->zone_id)->first())) ? $x->pivot->{$type} : NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ namespace App\Models;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@ -14,6 +15,8 @@ use App\Classes\FTN\Message;
|
|||||||
use App\Interfaces\Packet;
|
use App\Interfaces\Packet;
|
||||||
use App\Traits\{EncodeUTF8,MsgID};
|
use App\Traits\{EncodeUTF8,MsgID};
|
||||||
|
|
||||||
|
// @deprecated recv_pkt now in netmail_path
|
||||||
|
// @deprecated local - use flags
|
||||||
final class Netmail extends Model implements Packet
|
final class Netmail extends Model implements Packet
|
||||||
{
|
{
|
||||||
private const LOGKEY = 'MN-';
|
private const LOGKEY = 'MN-';
|
||||||
@ -21,6 +24,8 @@ final class Netmail extends Model implements Packet
|
|||||||
use SoftDeletes,EncodeUTF8,MsgID;
|
use SoftDeletes,EncodeUTF8,MsgID;
|
||||||
|
|
||||||
private Collection $set_path;
|
private Collection $set_path;
|
||||||
|
private Address $set_sender;
|
||||||
|
private string $set_pkt;
|
||||||
|
|
||||||
private const cast_utf8 = [
|
private const cast_utf8 = [
|
||||||
'to',
|
'to',
|
||||||
@ -44,6 +49,8 @@ final class Netmail extends Model implements Packet
|
|||||||
{
|
{
|
||||||
switch ($key) {
|
switch ($key) {
|
||||||
case 'set_path':
|
case 'set_path':
|
||||||
|
case 'set_pkt':
|
||||||
|
case 'set_sender':
|
||||||
$this->{$key} = $value;
|
$this->{$key} = $value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -60,7 +67,12 @@ final class Netmail extends Model implements Packet
|
|||||||
// Save the Path
|
// Save the Path
|
||||||
$ppoid = NULL;
|
$ppoid = NULL;
|
||||||
|
|
||||||
if (isset($model->set_path))
|
if (isset($model->set_path)) {
|
||||||
|
// If there are no details (Mystic), we'll create a blank
|
||||||
|
if (! $model->set_path->count()) {
|
||||||
|
$model->set_path->push(['node'=>$model->set_sender,'datetime'=>Carbon::now(),'program'=>'Unknown']);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($model->set_path as $path) {
|
foreach ($model->set_path as $path) {
|
||||||
$po = DB::select('INSERT INTO netmail_path (netmail_id,address_id,parent_id,datetime,program) VALUES (?,?,?,?,?) RETURNING id',[
|
$po = DB::select('INSERT INTO netmail_path (netmail_id,address_id,parent_id,datetime,program) VALUES (?,?,?,?,?) RETURNING id',[
|
||||||
$model->id,
|
$model->id,
|
||||||
@ -72,6 +84,15 @@ final class Netmail extends Model implements Packet
|
|||||||
|
|
||||||
$ppoid = $po[0]->id;
|
$ppoid = $po[0]->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($model->set_pkt) && isset($model->set_sender)) {
|
||||||
|
DB::update('UPDATE netmail_path set recv_pkt=?,recv_id=? where address_id=?',[
|
||||||
|
$model->set_pkt,
|
||||||
|
$model->set_sender->id,
|
||||||
|
Arr::get($model->set_path->last(),'node')->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +108,13 @@ final class Netmail extends Model implements Packet
|
|||||||
public function path()
|
public function path()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Address::class,'netmail_path')
|
return $this->belongsToMany(Address::class,'netmail_path')
|
||||||
->withPivot(['id','parent_id','datetime','program']);
|
->withPivot(['id','parent_id','datetime','program','recv_pkt','recv_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function received()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Address::class,'netmail_path','netmail_id','recv_id')
|
||||||
|
->withPivot(['id','parent_id','datetime','program','recv_pkt','recv_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tftn()
|
public function tftn()
|
||||||
|
71
database/migrations/2023_07_11_222130_packet_logging.php
Normal file
71
database/migrations/2023_07_11_222130_packet_logging.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?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('system_transfers',function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->string('packet')->nullable();
|
||||||
|
$table->bigInteger('file_id')->nullable();
|
||||||
|
$table->foreign('file_id')->references('id')->on('files');
|
||||||
|
|
||||||
|
$table->bigInteger('address_id');
|
||||||
|
$table->foreign('address_id')->references('id')->on('addresses');
|
||||||
|
|
||||||
|
$table->unique(['address_id','packet']);
|
||||||
|
$table->unique(['address_id','file_id']);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
Schema::table('netmails',function (Blueprint $table) {
|
||||||
|
$table->bigInteger('send_id')->nullable()->after('send_pkt');
|
||||||
|
$table->foreign('send_id')->references('id')->on('addresses');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('netmail_path',function (Blueprint $table) {
|
||||||
|
$table->string('recv_pkt')->nullable();
|
||||||
|
|
||||||
|
$table->bigInteger('recv_id')->nullable();
|
||||||
|
$table->foreign('recv_id')->references('id')->on('addresses');
|
||||||
|
|
||||||
|
$table->unique(['recv_id','netmail_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
DB::statement('ALTER TABLE echomail_seenby RENAME COLUMN packet TO sent_pkt');
|
||||||
|
|
||||||
|
Schema::table('echomail_seenby',function (Blueprint $table) {
|
||||||
|
$table->bigInteger('sent_id')->nullable();
|
||||||
|
$table->foreign('sent_id')->references('id')->on('addresses');
|
||||||
|
|
||||||
|
$table->unique(['sent_id','echomail_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('echomail_path',function (Blueprint $table) {
|
||||||
|
$table->string('recv_pkt')->nullable();
|
||||||
|
|
||||||
|
$table->bigInteger('recv_id')->nullable();
|
||||||
|
$table->foreign('recv_id')->references('id')->on('addresses');
|
||||||
|
|
||||||
|
$table->unique(['recv_id','echomail_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
//Schema::dropIfExists('system_transfers');
|
||||||
|
}
|
||||||
|
};
|
@ -43,8 +43,26 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if ($msg->flags & \App\Classes\FTN\Message::FLAG_LOCAL)
|
||||||
|
<div class="row pb-2">
|
||||||
|
<div class="col-8">
|
||||||
|
<strong class="highlight">Local message</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@elseif ($msg->flags & (\App\Classes\FTN\Message::FLAG_INTRANSIT|\App\Classes\FTN\Message::FLAG_RECD))
|
||||||
<div class="row pb-2">
|
<div class="row pb-2">
|
||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
PATH: <br><strong class="highlight">{!! optimize_path($msg->pathorder())->join('</strong> -> <strong class="highlight">') !!}</strong>
|
PATH: <br><strong class="highlight">{!! optimize_path($msg->pathorder())->join('</strong> -> <strong class="highlight">') !!}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row pb-2">
|
||||||
|
<div class="col-8">
|
||||||
|
RECEIVED:
|
||||||
|
@foreach ($msg->received as $path)
|
||||||
|
<strong class="highlight">{{ $path->pivot->recv_pkt }}</strong> by <strong class="highlight">{{ $path->ftn }}</strong> {{ $msg->created_at }}
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
Loading…
Reference in New Issue
Block a user