Skip to content

Commit 6efa8f4

Browse files
[Feature] Discord Webhook Functionality (alexjustesen#1196)
Co-authored-by: Alex Justesen <[email protected]>
1 parent f3a29bf commit 6efa8f4

File tree

6 files changed

+178
-0
lines changed

6 files changed

+178
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace App\Actions\Notifications;
4+
5+
use Filament\Notifications\Notification;
6+
use Illuminate\Support\Facades\Http;
7+
use Lorisleiva\Actions\Concerns\AsAction;
8+
9+
class SendDiscordTestNotification
10+
{
11+
use AsAction;
12+
13+
public function handle(array $webhooks)
14+
{
15+
if (! count($webhooks)) {
16+
Notification::make()
17+
->title('You need to add webhook urls!')
18+
->warning()
19+
->send();
20+
21+
return;
22+
}
23+
24+
foreach ($webhooks as $webhook) {
25+
$payload = [
26+
'content' => '👋 Testing the Webhook notification channel.',
27+
];
28+
// Send the request using Laravel's HTTP client
29+
$response = Http::post($webhook['discord_webhook_url'], $payload);
30+
}
31+
32+
Notification::make()
33+
->title('Test webhook notification sent.')
34+
->success()
35+
->send();
36+
}
37+
}

app/Filament/Pages/Settings/NotificationPage.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace App\Filament\Pages\Settings;
44

55
use App\Actions\Notifications\SendDatabaseTestNotification;
6+
use App\Actions\Notifications\SendDiscordTestNotification;
67
use App\Actions\Notifications\SendMailTestNotification;
78
use App\Actions\Notifications\SendTelegramTestNotification;
89
use App\Actions\Notifications\SendWebhookTestNotification;
@@ -85,6 +86,48 @@ public function form(Form $form): Form
8586
'md' => 2,
8687
]),
8788

89+
Forms\Components\Section::make('Discord')
90+
->schema([
91+
Forms\Components\Toggle::make('discord_enabled')
92+
->label('Enable Discord webhook notifications')
93+
->reactive()
94+
->columnSpanFull(),
95+
Forms\Components\Grid::make([
96+
'default' => 1,
97+
])
98+
->hidden(fn (Forms\Get $get) => $get('discord_enabled') !== true)
99+
->schema([
100+
Forms\Components\Fieldset::make('Triggers')
101+
->schema([
102+
Forms\Components\Toggle::make('discord_on_speedtest_run')
103+
->label('Notify on every speedtest run')
104+
->columnSpanFull(),
105+
Forms\Components\Toggle::make('discord_on_threshold_failure')
106+
->label('Notify on threshold failures')
107+
->columnSpanFull(),
108+
]),
109+
Forms\Components\Repeater::make('discord_webhooks')
110+
->label('Webhooks')
111+
->schema([
112+
Forms\Components\TextInput::make('discord_webhook_url')
113+
->label('Webhook URL')
114+
->required(),
115+
])
116+
->columnSpanFull(),
117+
Forms\Components\Actions::make([
118+
Forms\Components\Actions\Action::make('test discord')
119+
->label('Test Discord webhook')
120+
->action(fn (Forms\Get $get) => SendDiscordTestNotification::run(webhooks: $get('discord_webhooks')))
121+
->hidden(fn (Forms\Get $get) => ! count($get('discord_webhooks'))),
122+
]),
123+
]),
124+
])
125+
->compact()
126+
->columns([
127+
'default' => 1,
128+
'md' => 2,
129+
]),
130+
88131
Forms\Components\Section::make('Mail')
89132
->schema([
90133
Forms\Components\Toggle::make('mail_enabled')

app/Listeners/SpeedtestCompletedListener.php

Lines changed: 19 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
use Spatie\WebhookServer\WebhookCall;
1314

@@ -75,6 +76,24 @@ public function handle(ResultCreated $event): void
7576
}
7677
}
7778

79+
if ($this->notificationSettings->discord_enabled) {
80+
if ($this->notificationSettings->discord_on_speedtest_run && count($this->notificationSettings->discord_webhooks)) {
81+
foreach ($this->notificationSettings->discord_webhooks as $webhook) {
82+
// Construct the payload
83+
$payload = [
84+
'content' => 'There are new speedtest results for your network.'.
85+
"\nResult ID: ".$event->result->id.
86+
"\nSite Name: ".$this->generalSettings->site_name.
87+
"\nPing: ".$event->result->ping.' ms'.
88+
"\nDownload: ".($event->result->downloadBits / 1000000).' (Mbps)'.
89+
"\nUpload: ".($event->result->uploadBits / 1000000).' (Mbps)',
90+
];
91+
// Send the request using Laravel's HTTP client
92+
$response = Http::post($webhook['discord_webhook_url'], $payload);
93+
}
94+
}
95+
}
96+
7897
if ($this->notificationSettings->webhook_enabled) {
7998
if ($this->notificationSettings->webhook_on_speedtest_run && count($this->notificationSettings->webhook_urls)) {
8099
foreach ($this->notificationSettings->webhook_urls as $url) {

app/Listeners/Threshold/AbsoluteListener.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ public function handle(ResultCreated $event): void
6363
$this->telegramChannel($event);
6464
}
6565

66+
// Discord notification channel
67+
if ($this->notificationSettings->discord_enabled == true && $this->notificationSettings->discord_on_threshold_failure == true) {
68+
$this->discordChannel($event);
69+
}
70+
6671
// Webhook notification channel
6772
if ($this->notificationSettings->webhook_enabled == true && $this->notificationSettings->webhook_on_threshold_failure == true) {
6873
$this->webhookChannel($event);
@@ -219,6 +224,55 @@ protected function telegramChannel(ResultCreated $event): void
219224
}
220225
}
221226

227+
/**
228+
* Handle Discord notifications.
229+
*/
230+
protected function discordChannel(ResultCreated $event): void
231+
{
232+
if ($this->notificationSettings->discord_enabled) {
233+
$failedThresholds = []; // Initialize an array to keep track of failed thresholds
234+
235+
// Check Download threshold
236+
if ($this->thresholdSettings->absolute_download > 0 && absoluteDownloadThresholdFailed($this->thresholdSettings->absolute_download, $event->result->downloadBits)) {
237+
$failedThresholds['Download'] = ($event->result->downloadBits / 1000000).' (Mbps)';
238+
}
239+
240+
// Check Upload threshold
241+
if ($this->thresholdSettings->absolute_upload > 0 && absoluteUploadThresholdFailed($this->thresholdSettings->absolute_upload, $event->result->uploadBits)) {
242+
$failedThresholds['Upload'] = ($event->result->uploadBits / 1000000).' (Mbps)';
243+
}
244+
245+
// Check Ping threshold
246+
if ($this->thresholdSettings->absolute_ping > 0 && absolutePingThresholdFailed($this->thresholdSettings->absolute_ping, $event->result->ping)) {
247+
$failedThresholds['Ping'] = $event->result->ping.' ms';
248+
}
249+
250+
// Proceed with sending notifications only if there are any failed thresholds
251+
if (count($failedThresholds) > 0) {
252+
if ($this->notificationSettings->discord_on_threshold_failure && count($this->notificationSettings->discord_webhooks)) {
253+
foreach ($this->notificationSettings->discord_webhooks as $webhook) {
254+
// Construct the payload with the failed thresholds information
255+
$contentLines = [
256+
'Result ID: '.$event->result->id,
257+
'Site Name: '.$this->generalSettings->site_name,
258+
];
259+
260+
foreach ($failedThresholds as $metric => $result) {
261+
$contentLines[] = "{$metric} threshold failed with result: {$result}.";
262+
}
263+
264+
$payload = [
265+
'content' => implode("\n", $contentLines),
266+
];
267+
268+
// Send the request using Laravel's HTTP client
269+
$response = Http::post($webhook['discord_webhook_url'], $payload);
270+
}
271+
}
272+
}
273+
}
274+
}
275+
222276
/**
223277
* Handle webhook notifications.
224278
*

app/Settings/NotificationSettings.php

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

3939
public ?array $webhook_urls;
4040

41+
public bool $discord_enabled;
42+
43+
public bool $discord_on_speedtest_run;
44+
45+
public bool $discord_on_threshold_failure;
46+
47+
public ?array $discord_webhooks;
48+
4149
public static function group(): string
4250
{
4351
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.discord_enabled', false);
13+
$this->migrator->add('notification.discord_on_speedtest_run', false);
14+
$this->migrator->add('notification.discord_on_threshold_failure', false);
15+
$this->migrator->add('notification.discord_webhooks', null);
16+
}
17+
};

0 commit comments

Comments
 (0)