diff --git a/app/Filament/Pages/Settings/NotificationPage.php b/app/Filament/Pages/Settings/NotificationPage.php index 49dfaeaad..6688ecaff 100755 --- a/app/Filament/Pages/Settings/NotificationPage.php +++ b/app/Filament/Pages/Settings/NotificationPage.php @@ -5,6 +5,7 @@ use App\Forms\Components\TestDatabaseNotification; use App\Forms\Components\TestMailNotification; use App\Forms\Components\TestTelegramNotification; +use App\Forms\Components\TestWebhookNotification; use App\Mail\Test; use App\Notifications\Telegram\TestNotification as TelegramTestNotification; use App\Settings\NotificationSettings; @@ -162,6 +163,45 @@ public function form(Form $form): Form 'default' => 1, 'md' => 2, ]), + + Forms\Components\Section::make('Webhook') + ->schema([ + Forms\Components\Toggle::make('webhook_enabled') + ->label('Enable webhook notifications') + ->reactive() + ->columnSpan(2), + Forms\Components\Grid::make([ + 'default' => 1, ]) + ->hidden(fn (Forms\Get $get) => $get('webhook_enabled') !== true) + ->schema([ + Forms\Components\Fieldset::make('Triggers') + ->schema([ + Forms\Components\Toggle::make('webhook_on_speedtest_run') + ->label('Notify on every speedtest run') + ->columnSpan(2), + Forms\Components\Toggle::make('webhook_on_threshold_failure') + ->label('Notify on threshold failures') + ->columnSpan(2), + ]), + ]), + Forms\Components\Repeater::make('webhook_urls') + ->label('Recipients') + ->schema([ + Forms\Components\TextInput::make('url') + ->maxLength(100) + ->required() + ->columnSpan(['md' => 2]), + ]) + ->hidden(fn (Forms\Get $get) => $get('webhook_enabled') !== true) + ->columnSpan(['md' => 2]), + TestWebhookNotification::make('test channel') + ->hidden(fn (Forms\Get $get) => $get('webhook_enabled') !== true), + ]) + ->compact() + ->columns([ + 'default' => 1, + 'md' => 2, + ]), ]) ->columnSpan([ 'md' => 2, diff --git a/app/Forms/Components/TestWebhookNotification.php b/app/Forms/Components/TestWebhookNotification.php new file mode 100644 index 000000000..bef9b34ee --- /dev/null +++ b/app/Forms/Components/TestWebhookNotification.php @@ -0,0 +1,10 @@ +notificationSettings->webhook_enabled) { + if ($this->notificationSettings->webhook_on_speedtest_run && count($this->notificationSettings->webhook_urls)) { + foreach ($this->notificationSettings->webhook_urls as $url) { + Http::post($url['url'], [ + 'result_id' => $event->result->id, + 'site_name' => $this->generalSettings->site_name, + 'ping' => $event->result->ping, + 'download' => toBits(convertSize($event->result->download)), + 'upload' => toBits(convertSize($event->result->upload)), + ]); + } + } + } } } diff --git a/app/Listeners/Threshold/AbsoluteListener.php b/app/Listeners/Threshold/AbsoluteListener.php index b5a4c3012..b588f0a9c 100644 --- a/app/Listeners/Threshold/AbsoluteListener.php +++ b/app/Listeners/Threshold/AbsoluteListener.php @@ -10,6 +10,7 @@ use App\Telegram\TelegramNotification; use Filament\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; @@ -60,6 +61,11 @@ public function handle(ResultCreated $event): void if ($this->notificationSettings->telegram_enabled == true && $this->notificationSettings->telegram_on_threshold_failure == true) { $this->telegramChannel($event); } + + // Webhook notification channel + if ($this->notificationSettings->webhook_enabled == true && $this->notificationSettings->webhook_on_threshold_failure == true) { + $this->webhookChannel($event); + } } /** @@ -211,4 +217,59 @@ protected function telegramChannel(ResultCreated $event): void } } } + + /** + * Handle webhook notifications. + */ + protected function webhookChannel(ResultCreated $event): void + { + $failedThresholds = []; + + if (! count($this->notificationSettings->webhook_urls) > 0) { + Log::info('Skipping sending webhook notification, no urls.'); + } + + // Download threshold + if ($this->thresholdSettings->absolute_download > 0) { + if (absoluteDownloadThresholdFailed($this->thresholdSettings->absolute_download, $event->result->download)) { + array_push($failedThresholds, [ + 'name' => 'Download', + 'threshold' => $this->thresholdSettings->absolute_download, + 'value' => toBits(convertSize($event->result->download), 2), + ]); + } + } + + // Upload threshold + if ($this->thresholdSettings->absolute_upload > 0) { + if (absoluteUploadThresholdFailed($this->thresholdSettings->absolute_upload, $event->result->upload)) { + array_push($failedThresholds, [ + 'name' => 'Upload', + 'threshold' => $this->thresholdSettings->absolute_upload, + 'value' => toBits(convertSize($event->result->upload), 2), + ]); + } + } + + // Ping threshold + if ($this->thresholdSettings->absolute_ping > 0) { + if (absolutePingThresholdFailed($this->thresholdSettings->absolute_ping, $event->result->ping)) { + array_push($failedThresholds, [ + 'name' => 'Ping', + 'threshold' => $this->thresholdSettings->absolute_ping, + 'value' => round($event->result->ping, 2), + ]); + } + } + + if (count($failedThresholds)) { + foreach ($this->notificationSettings->webhook_urls as $url) { + Http::post($url['url'], [ + 'result_id' => $event->result->id, + 'site_name' => $this->generalSettings->site_name, + 'metrics' => $failedThresholds, + ]); + } + } + } } diff --git a/app/Settings/NotificationSettings.php b/app/Settings/NotificationSettings.php index 182794dc8..f23dfdbf6 100644 --- a/app/Settings/NotificationSettings.php +++ b/app/Settings/NotificationSettings.php @@ -28,6 +28,14 @@ class NotificationSettings extends Settings public ?array $telegram_recipients; + public bool $webhook_enabled; + + public bool $webhook_on_speedtest_run; + + public bool $webhook_on_threshold_failure; + + public ?array $webhook_urls; + public static function group(): string { return 'notification'; diff --git a/database/migrations/2023_09_11_144858_create_webhook_notification_settings.php b/database/migrations/2023_09_11_144858_create_webhook_notification_settings.php new file mode 100644 index 000000000..23d51c5dc --- /dev/null +++ b/database/migrations/2023_09_11_144858_create_webhook_notification_settings.php @@ -0,0 +1,17 @@ +migrator->add('notification.webhook_enabled', false); + $this->migrator->add('notification.webhook_on_speedtest_run', false); + $this->migrator->add('notification.webhook_on_threshold_failure', false); + $this->migrator->add('notification.webhook_urls', null); + } +}; diff --git a/resources/views/forms/components/test-webhook-notification.blade.php b/resources/views/forms/components/test-webhook-notification.blade.php new file mode 100644 index 000000000..8a382fc05 --- /dev/null +++ b/resources/views/forms/components/test-webhook-notification.blade.php @@ -0,0 +1,5 @@ +