Skip to content

Commit 4447651

Browse files
committed
feat: add webhook notifications
1 parent e91ca29 commit 4447651

File tree

7 files changed

+155
-0
lines changed

7 files changed

+155
-0
lines changed

app/Filament/Pages/Settings/NotificationPage.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,45 @@ public function form(Form $form): Form
162162
'default' => 1,
163163
'md' => 2,
164164
]),
165+
166+
Forms\Components\Section::make('Webhook')
167+
->schema([
168+
Forms\Components\Toggle::make('webhook_enabled')
169+
->label('Enable webhook notifications')
170+
->reactive()
171+
->columnSpan(2),
172+
Forms\Components\Grid::make([
173+
'default' => 1, ])
174+
->hidden(fn (Forms\Get $get) => $get('webhook_enabled') !== true)
175+
->schema([
176+
Forms\Components\Fieldset::make('Triggers')
177+
->schema([
178+
Forms\Components\Toggle::make('webhook_on_speedtest_run')
179+
->label('Notify on every speedtest run')
180+
->columnSpan(2),
181+
Forms\Components\Toggle::make('webhook_on_threshold_failure')
182+
->label('Notify on threshold failures')
183+
->columnSpan(2),
184+
]),
185+
]),
186+
Forms\Components\Repeater::make('webhook_urls')
187+
->label('Recipients')
188+
->schema([
189+
Forms\Components\TextInput::make('url')
190+
->maxLength(100)
191+
->required()
192+
->columnSpan(['md' => 2]),
193+
])
194+
->hidden(fn (Forms\Get $get) => $get('webhook_enabled') !== true)
195+
->columnSpan(['md' => 2]),
196+
TestTelegramNotification::make('test channel')
197+
->hidden(fn (Forms\Get $get) => $get('webhook_enabled') !== true),
198+
])
199+
->compact()
200+
->columns([
201+
'default' => 1,
202+
'md' => 2,
203+
]),
165204
])
166205
->columnSpan([
167206
'md' => 2,
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace App\Forms\Components;
4+
5+
use Filament\Forms\Components\Field;
6+
7+
class TestWebhookNotification extends Field
8+
{
9+
protected string $view = 'forms.components.test-webhook-notification';
10+
}

app/Listeners/SpeedtestCompletedListener.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use App\Settings\NotificationSettings;
99
use App\Telegram\TelegramNotification;
1010
use Filament\Notifications\Notification;
11+
use Illuminate\Support\Facades\Http;
1112
use Illuminate\Support\Facades\Mail;
1213

1314
class SpeedtestCompletedListener
@@ -73,5 +74,19 @@ public function handle(ResultCreated $event): void
7374
}
7475
}
7576
}
77+
78+
if ($this->notificationSettings->webhook_enabled) {
79+
if ($this->notificationSettings->webhook_on_speedtest_run && count($this->notificationSettings->webhook_urls)) {
80+
foreach ($this->notificationSettings->webhook_urls as $url) {
81+
Http::post($url['url'], [
82+
'result_id' => $event->result->id,
83+
'site_name' => $this->generalSettings->site_name,
84+
'ping' => $event->result->ping,
85+
'download' => toBits(convertSize($event->result->download)),
86+
'upload' => toBits(convertSize($event->result->upload)),
87+
]);
88+
}
89+
}
90+
}
7691
}
7792
}

app/Listeners/Threshold/AbsoluteListener.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use App\Telegram\TelegramNotification;
1111
use Filament\Notifications\Notification;
1212
use Illuminate\Contracts\Queue\ShouldQueue;
13+
use Illuminate\Support\Facades\Http;
1314
use Illuminate\Support\Facades\Log;
1415
use Illuminate\Support\Facades\Mail;
1516

@@ -60,6 +61,11 @@ public function handle(ResultCreated $event): void
6061
if ($this->notificationSettings->telegram_enabled == true && $this->notificationSettings->telegram_on_threshold_failure == true) {
6162
$this->telegramChannel($event);
6263
}
64+
65+
// Webhook notification channel
66+
if ($this->notificationSettings->webhook_enabled == true && $this->notificationSettings->webhook_on_threshold_failure == true) {
67+
$this->webhookChannel($event);
68+
}
6369
}
6470

6571
/**
@@ -211,4 +217,59 @@ protected function telegramChannel(ResultCreated $event): void
211217
}
212218
}
213219
}
220+
221+
/**
222+
* Handle webhook notifications.
223+
*/
224+
protected function webhookChannel(ResultCreated $event): void
225+
{
226+
$failedThresholds = [];
227+
228+
if (! count($this->notificationSettings->webhook_urls) > 0) {
229+
Log::info('Skipping sending webhook notification, no urls.');
230+
}
231+
232+
// Download threshold
233+
if ($this->thresholdSettings->absolute_download > 0) {
234+
if (absoluteDownloadThresholdFailed($this->thresholdSettings->absolute_download, $event->result->download)) {
235+
array_push($failedThresholds, [
236+
'name' => 'Download',
237+
'threshold' => $this->thresholdSettings->absolute_download,
238+
'value' => toBits(convertSize($event->result->download), 2),
239+
]);
240+
}
241+
}
242+
243+
// Upload threshold
244+
if ($this->thresholdSettings->absolute_upload > 0) {
245+
if (absoluteUploadThresholdFailed($this->thresholdSettings->absolute_upload, $event->result->upload)) {
246+
array_push($failedThresholds, [
247+
'name' => 'Upload',
248+
'threshold' => $this->thresholdSettings->absolute_upload,
249+
'value' => toBits(convertSize($event->result->upload), 2),
250+
]);
251+
}
252+
}
253+
254+
// Ping threshold
255+
if ($this->thresholdSettings->absolute_ping > 0) {
256+
if (absolutePingThresholdFailed($this->thresholdSettings->absolute_ping, $event->result->ping)) {
257+
array_push($failedThresholds, [
258+
'name' => 'Ping',
259+
'threshold' => $this->thresholdSettings->absolute_ping,
260+
'value' => round($event->result->ping, 2),
261+
]);
262+
}
263+
}
264+
265+
if (count($failedThresholds)) {
266+
foreach ($this->notificationSettings->webhook_urls as $url) {
267+
Http::post($url['url'], [
268+
'result_id' => $event->result->id,
269+
'site_name' => $this->generalSettings->site_name,
270+
'metrics' => $failedThresholds,
271+
]);
272+
}
273+
}
274+
}
214275
}

app/Settings/NotificationSettings.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ class NotificationSettings extends Settings
2828

2929
public ?array $telegram_recipients;
3030

31+
public bool $webhook_enabled;
32+
33+
public bool $webhook_on_speedtest_run;
34+
35+
public bool $webhook_on_threshold_failure;
36+
37+
public ?array $webhook_urls;
38+
3139
public static function group(): string
3240
{
3341
return 'notification';
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
use Spatie\LaravelSettings\Migrations\SettingsMigration;
4+
5+
return new class extends SettingsMigration
6+
{
7+
/**
8+
* Run the migrations.
9+
*/
10+
public function up(): void
11+
{
12+
$this->migrator->add('notification.webhook_enabled', false);
13+
$this->migrator->add('notification.webhook_on_speedtest_run', false);
14+
$this->migrator->add('notification.webhook_on_threshold_failure', false);
15+
$this->migrator->add('notification.webhook_urls', null);
16+
}
17+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<div>
2+
<x-filament::button wire:click="sendTestWebhookNotification()">
3+
Test webhook channel
4+
</x-filament::button>
5+
</div>

0 commit comments

Comments
 (0)