Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
14e47b8
Add mail average jobs
svenvg93 Dec 1, 2025
32e3b7e
add server stats
svenvg93 Dec 1, 2025
23a6f21
external service for dry
svenvg93 Dec 1, 2025
e1afdba
add lang strings
svenvg93 Dec 1, 2025
243994f
chnage text
svenvg93 Dec 1, 2025
48b43d4
add packet loss
svenvg93 Dec 1, 2025
4dd7e58
set schedule in console and update table header in mail
svenvg93 Dec 1, 2025
3d1ad12
Merge branch 'alexjustesen:main' into feat/avg-notifications
svenvg93 Dec 2, 2025
8f3aec7
Merge branch 'alexjustesen:main' into feat/avg-notifications
svenvg93 Dec 2, 2025
370e0ef
Merge branch 'alexjustesen:main' into feat/avg-notifications
svenvg93 Dec 3, 2025
a2fa465
Merge remote-tracking branch 'origin/main' into feat/avg-notifications
svenvg93 Dec 6, 2025
22686c0
Add apprise support
svenvg93 Dec 6, 2025
8c6a98a
update console
svenvg93 Dec 6, 2025
3ca4802
Merge branch 'alexjustesen:main' into feat/avg-notifications
svenvg93 Dec 6, 2025
3e085f7
add reports for webhooks
svenvg93 Dec 6, 2025
2456c89
Averag with Enums
svenvg93 Dec 6, 2025
e008a8f
refactor to one action
svenvg93 Dec 8, 2025
ead48c0
Merge branch 'alexjustesen:main' into feat/avg-with-enums
svenvg93 Dec 8, 2025
7cfb487
remove seeder
svenvg93 Dec 8, 2025
a462b09
update console
svenvg93 Dec 8, 2025
d945b08
Merge branch 'alexjustesen:main' into feat/avg-with-enums
svenvg93 Dec 9, 2025
96910dd
Merge branch 'alexjustesen:main' into feat/avg-with-enums
svenvg93 Dec 10, 2025
353eeeb
Merge branch 'main' into feat/avg-with-enums
svenvg93 Dec 12, 2025
ec3e895
Merge branch 'main' into feat/avg-with-enums
svenvg93 Dec 15, 2025
814d51a
Merge branch 'main' into feat/avg-with-enums
svenvg93 Dec 16, 2025
5a93f04
Merge branch 'main' into feat/avg-with-enums
svenvg93 Dec 16, 2025
9571e2d
Merge branch 'main' into feat/avg-with-enums
svenvg93 Dec 19, 2025
83bed7c
use grid
svenvg93 Dec 20, 2025
f3fdd2a
Merge branch 'main' into feat/avg-with-enums
alexjustesen Dec 21, 2025
f47bead
Merge branch 'main' into feat/avg-with-enums
svenvg93 Dec 26, 2025
02434ac
Merge branch 'alexjustesen:main' into feat/avg-with-enums
svenvg93 Dec 28, 2025
9c6fb4c
Merge branch 'main' into feat/avg-with-enums
svenvg93 Jan 4, 2026
8c2b390
Merge branch 'main' into feat/avg-with-enums
svenvg93 Jan 9, 2026
4164151
remove webhook average logic
svenvg93 Jan 9, 2026
f84eb67
remove per server stats
svenvg93 Jan 9, 2026
695ee6b
move settings check to job
svenvg93 Jan 9, 2026
4b72865
clean up logic
svenvg93 Jan 9, 2026
85c7b66
restore console schedule
svenvg93 Jan 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace App\Actions\Notifications\Average;

use App\Enums\ReportPeriod;
use App\Jobs\Notifications\SendPeriodicAverageReportJob;
use App\Settings\NotificationSettings;

class CheckAndSendPeriodicAverageNotifications
{
public static function run(ReportPeriod $period): void
{
$settings = new NotificationSettings;

$mailEnabled = match ($period) {
ReportPeriod::Daily => $settings->mail_enabled && $settings->mail_daily_average_enabled,
ReportPeriod::Weekly => $settings->mail_enabled && $settings->mail_weekly_average_enabled,
ReportPeriod::Monthly => $settings->mail_enabled && $settings->mail_monthly_average_enabled,
};

$appriseEnabled = match ($period) {
ReportPeriod::Daily => $settings->apprise_enabled && $settings->apprise_daily_average_enabled,
ReportPeriod::Weekly => $settings->apprise_enabled && $settings->apprise_weekly_average_enabled,
ReportPeriod::Monthly => $settings->apprise_enabled && $settings->apprise_monthly_average_enabled,
};

if (! $mailEnabled && ! $appriseEnabled) {
return;
}

SendPeriodicAverageReportJob::dispatch($period, $mailEnabled, $appriseEnabled);
}
}
48 changes: 48 additions & 0 deletions app/Enums/ReportPeriod.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace App\Enums;

use Carbon\Carbon;

enum ReportPeriod: string
{
case Daily = 'daily';
case Weekly = 'weekly';
case Monthly = 'monthly';

public function getStartDate(): Carbon
{
return match ($this) {
self::Daily => now()->subDay()->startOfDay(),
self::Weekly => now()->subWeek()->startOfWeek(),
self::Monthly => now()->subMonth()->startOfMonth(),
};
}

public function getEndDate(): Carbon
{
return match ($this) {
self::Daily => now()->subDay()->endOfDay(),
self::Weekly => now()->subWeek()->endOfWeek(),
self::Monthly => now()->subMonth()->endOfMonth(),
};
}

public function getLabel(): string
{
return match ($this) {
self::Daily => now()->subDay()->format('F j, Y'),
self::Weekly => $this->getStartDate()->format('M j').' - '.$this->getEndDate()->format('M j, Y'),
self::Monthly => $this->getStartDate()->format('F Y'),
};
}

public function getName(): string
{
return match ($this) {
self::Daily => 'Daily',
self::Weekly => 'Weekly',
self::Monthly => 'Monthly',
};
}
}
71 changes: 55 additions & 16 deletions app/Filament/Pages/Settings/Notification.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,13 @@ public function form(Schema $schema): Schema
->live(),

Grid::make([
'default' => 1,
'default' => 2,
])
->hidden(fn (Get $get) => $get('mail_enabled') !== true)
->schema([
Fieldset::make(__('settings.triggers'))
->columns(1)
->columnSpan(1)
->schema([
Checkbox::make('mail_on_speedtest_run')
->label(__('settings/notifications.notify_on_every_speedtest_run'))
Expand All @@ -126,21 +127,38 @@ public function form(Schema $schema): Schema
->helpertext(__('settings/notifications.notify_on_threshold_failures_helper')),
]),

Fieldset::make(__('settings/notifications.periodic_reports'))
->columns(1)
->columnSpan(1)
->schema([
Checkbox::make('mail_daily_average_enabled')
->label(__('settings/notifications.daily_average_report'))
->helperText(__('settings/notifications.daily_average_report_helper')),

Checkbox::make('mail_weekly_average_enabled')
->label(__('settings/notifications.weekly_average_report'))
->helperText(__('settings/notifications.weekly_average_report_helper')),

Checkbox::make('mail_monthly_average_enabled')
->label(__('settings/notifications.monthly_average_report'))
->helperText(__('settings/notifications.monthly_average_report_helper')),
]),

Repeater::make('mail_recipients')
->label(__('settings/notifications.recipients'))
->schema([
TextInput::make('email_address')
->placeholder('[email protected]')
->email()
->required(),
]),
])->columnSpan('full'),

Actions::make([
Action::make('test mail')
->label(__('settings/notifications.test_mail_channel'))
->action(fn (Get $get) => SendMailTestNotification::run(recipients: $get('mail_recipients')))
->hidden(fn (Get $get) => ! count($get('mail_recipients'))),
]),
])->columnSpan('full'),
]),

// ...
Expand Down Expand Up @@ -193,14 +211,14 @@ public function form(Schema $schema): Schema
->maxLength(2000)
->required()
->url(),
]),
])->columnSpan('full'),

Actions::make([
Action::make('test webhook')
->label(__('settings/notifications.test_webhook_channel'))
->action(fn (Get $get) => SendWebhookTestNotification::run(webhooks: $get('webhook_urls')))
->hidden(fn (Get $get) => ! count($get('webhook_urls'))),
]),
])->columnSpan('full'),
]),

// ...
Expand Down Expand Up @@ -248,18 +266,39 @@ public function form(Schema $schema): Schema
->label(__('settings/notifications.apprise_verify_ssl'))
->default(true)
->columnSpanFull(),
]),
Fieldset::make(__('settings.triggers'))
])
->columnSpanFull(),
Grid::make([
'default' => 2,
])
->schema([
Checkbox::make('apprise_on_speedtest_run')
->label(__('settings/notifications.notify_on_every_speedtest_run'))
->helpertext(__('settings/notifications.notify_on_every_speedtest_run_helper'))
->columnSpanFull(),
Checkbox::make('apprise_on_threshold_failure')
->label(__('settings/notifications.notify_on_threshold_failures'))
->helpertext(__('settings/notifications.notify_on_threshold_failures_helper'))
->columnSpanFull(),
]),
Fieldset::make(__('settings.triggers'))
->columns(1)
->columnSpan(1)
->schema([
Checkbox::make('apprise_on_speedtest_run')
->label(__('settings/notifications.notify_on_every_speedtest_run'))
->helpertext(__('settings/notifications.notify_on_every_speedtest_run_helper')),
Checkbox::make('apprise_on_threshold_failure')
->label(__('settings/notifications.notify_on_threshold_failures'))
->helpertext(__('settings/notifications.notify_on_threshold_failures_helper')),
]),
Fieldset::make(__('settings/notifications.periodic_reports'))
->columns(1)
->columnSpan(1)
->schema([
Checkbox::make('apprise_daily_average_enabled')
->label(__('settings/notifications.daily_average_report'))
->helperText(__('settings/notifications.daily_average_report_helper')),
Checkbox::make('apprise_weekly_average_enabled')
->label(__('settings/notifications.weekly_average_report'))
->helperText(__('settings/notifications.weekly_average_report_helper')),
Checkbox::make('apprise_monthly_average_enabled')
->label(__('settings/notifications.monthly_average_report'))
->helperText(__('settings/notifications.monthly_average_report_helper')),
]),
])
->columnSpanFull(),
Repeater::make('apprise_channel_urls')
->label(__('settings/notifications.apprise_channels'))
->helperText(__('settings/notifications.apprise_save_to_test'))
Expand Down
52 changes: 52 additions & 0 deletions app/Jobs/Notifications/SendPeriodicAverageReportJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace App\Jobs\Notifications;

use App\Enums\ReportPeriod;
use App\Services\PeriodicNotificationService;
use App\Services\PeriodicReportService;
use App\Settings\NotificationSettings;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class SendPeriodicAverageReportJob implements ShouldQueue
{
use Queueable;

public function __construct(
public ReportPeriod $period,
public bool $sendMail,
public bool $sendApprise
) {}

/**
* Execute the job.
*/
public function handle(
NotificationSettings $settings,
PeriodicReportService $reportService,
PeriodicNotificationService $notificationService
): void {
$start = $this->period->getStartDate();
$end = $this->period->getEndDate();

$results = $reportService->getResults($start, $end);

if ($results->isEmpty()) {
return;
}

$stats = $reportService->calculateStats($results);

$periodName = $this->period->getName();
$periodLabel = $this->period->getLabel();

if ($this->sendMail) {
$notificationService->sendMail($settings, $stats, $periodName, $periodLabel);
}

if ($this->sendApprise) {
$notificationService->sendApprise($settings, $stats, $periodName, $periodLabel);
}
}
}
44 changes: 44 additions & 0 deletions app/Mail/PeriodicAverageMail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class PeriodicAverageMail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;

/**
* Create a new message instance.
*/
public function __construct(
public array $stats,
public string $period,
public string $periodLabel
) {}

/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: "{$this->period} Speedtest Average Report - {$this->periodLabel}",
);
}

/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
markdown: 'mail.speedtest.periodic-average',
);
}
}
46 changes: 46 additions & 0 deletions app/Notifications/Apprise/PeriodicAverageNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace App\Notifications\Apprise;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;

class PeriodicAverageNotification extends Notification implements ShouldQueue
{
use Queueable;

public function __construct(
public array $stats,
public string $period,
public string $periodLabel
) {}

/**
* Get the notification's delivery channels.
*
* @return array<int, string>
*/
public function via(object $notifiable): array
{
return ['apprise'];
}

/**
* Get the Apprise message representation of the notification.
*/
public function toApprise(object $notifiable): AppriseMessage
{
$body = view('apprise.periodic-average', [
'stats' => $this->stats,
'period' => $this->period,
'periodLabel' => $this->periodLabel,
])->render();

return AppriseMessage::create()
->urls($notifiable->routes['apprise_urls'])
->title($this->period.' Speedtest Average Report')
->body($body)
->type('info');
}
}
Loading