[Feature] Discord Webhook Functionality (#1196)

Co-authored-by: Alex Justesen <alexjustesen@users.noreply.github.com>
This commit is contained in:
Justin Jones
2024-02-22 09:36:57 -05:00
committed by GitHub
parent f3a29bffb7
commit 6efa8f4c9d
6 changed files with 178 additions and 0 deletions
@@ -0,0 +1,37 @@
<?php
namespace App\Actions\Notifications;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Http;
use Lorisleiva\Actions\Concerns\AsAction;
class SendDiscordTestNotification
{
use AsAction;
public function handle(array $webhooks)
{
if (! count($webhooks)) {
Notification::make()
->title('You need to add webhook urls!')
->warning()
->send();
return;
}
foreach ($webhooks as $webhook) {
$payload = [
'content' => '👋 Testing the Webhook notification channel.',
];
// Send the request using Laravel's HTTP client
$response = Http::post($webhook['discord_webhook_url'], $payload);
}
Notification::make()
->title('Test webhook notification sent.')
->success()
->send();
}
}
@@ -3,6 +3,7 @@
namespace App\Filament\Pages\Settings;
use App\Actions\Notifications\SendDatabaseTestNotification;
use App\Actions\Notifications\SendDiscordTestNotification;
use App\Actions\Notifications\SendMailTestNotification;
use App\Actions\Notifications\SendTelegramTestNotification;
use App\Actions\Notifications\SendWebhookTestNotification;
@@ -85,6 +86,48 @@ class NotificationPage extends SettingsPage
'md' => 2,
]),
Forms\Components\Section::make('Discord')
->schema([
Forms\Components\Toggle::make('discord_enabled')
->label('Enable Discord webhook notifications')
->reactive()
->columnSpanFull(),
Forms\Components\Grid::make([
'default' => 1,
])
->hidden(fn (Forms\Get $get) => $get('discord_enabled') !== true)
->schema([
Forms\Components\Fieldset::make('Triggers')
->schema([
Forms\Components\Toggle::make('discord_on_speedtest_run')
->label('Notify on every speedtest run')
->columnSpanFull(),
Forms\Components\Toggle::make('discord_on_threshold_failure')
->label('Notify on threshold failures')
->columnSpanFull(),
]),
Forms\Components\Repeater::make('discord_webhooks')
->label('Webhooks')
->schema([
Forms\Components\TextInput::make('discord_webhook_url')
->label('Webhook URL')
->required(),
])
->columnSpanFull(),
Forms\Components\Actions::make([
Forms\Components\Actions\Action::make('test discord')
->label('Test Discord webhook')
->action(fn (Forms\Get $get) => SendDiscordTestNotification::run(webhooks: $get('discord_webhooks')))
->hidden(fn (Forms\Get $get) => ! count($get('discord_webhooks'))),
]),
]),
])
->compact()
->columns([
'default' => 1,
'md' => 2,
]),
Forms\Components\Section::make('Mail')
->schema([
Forms\Components\Toggle::make('mail_enabled')
@@ -8,6 +8,7 @@ use App\Settings\GeneralSettings;
use App\Settings\NotificationSettings;
use App\Telegram\TelegramNotification;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Spatie\WebhookServer\WebhookCall;
@@ -75,6 +76,24 @@ class SpeedtestCompletedListener
}
}
if ($this->notificationSettings->discord_enabled) {
if ($this->notificationSettings->discord_on_speedtest_run && count($this->notificationSettings->discord_webhooks)) {
foreach ($this->notificationSettings->discord_webhooks as $webhook) {
// Construct the payload
$payload = [
'content' => 'There are new speedtest results for your network.'.
"\nResult ID: ".$event->result->id.
"\nSite Name: ".$this->generalSettings->site_name.
"\nPing: ".$event->result->ping.' ms'.
"\nDownload: ".($event->result->downloadBits / 1000000).' (Mbps)'.
"\nUpload: ".($event->result->uploadBits / 1000000).' (Mbps)',
];
// Send the request using Laravel's HTTP client
$response = Http::post($webhook['discord_webhook_url'], $payload);
}
}
}
if ($this->notificationSettings->webhook_enabled) {
if ($this->notificationSettings->webhook_on_speedtest_run && count($this->notificationSettings->webhook_urls)) {
foreach ($this->notificationSettings->webhook_urls as $url) {
@@ -63,6 +63,11 @@ class AbsoluteListener implements ShouldQueue
$this->telegramChannel($event);
}
// Discord notification channel
if ($this->notificationSettings->discord_enabled == true && $this->notificationSettings->discord_on_threshold_failure == true) {
$this->discordChannel($event);
}
// Webhook notification channel
if ($this->notificationSettings->webhook_enabled == true && $this->notificationSettings->webhook_on_threshold_failure == true) {
$this->webhookChannel($event);
@@ -219,6 +224,55 @@ class AbsoluteListener implements ShouldQueue
}
}
/**
* Handle Discord notifications.
*/
protected function discordChannel(ResultCreated $event): void
{
if ($this->notificationSettings->discord_enabled) {
$failedThresholds = []; // Initialize an array to keep track of failed thresholds
// Check Download threshold
if ($this->thresholdSettings->absolute_download > 0 && absoluteDownloadThresholdFailed($this->thresholdSettings->absolute_download, $event->result->downloadBits)) {
$failedThresholds['Download'] = ($event->result->downloadBits / 1000000).' (Mbps)';
}
// Check Upload threshold
if ($this->thresholdSettings->absolute_upload > 0 && absoluteUploadThresholdFailed($this->thresholdSettings->absolute_upload, $event->result->uploadBits)) {
$failedThresholds['Upload'] = ($event->result->uploadBits / 1000000).' (Mbps)';
}
// Check Ping threshold
if ($this->thresholdSettings->absolute_ping > 0 && absolutePingThresholdFailed($this->thresholdSettings->absolute_ping, $event->result->ping)) {
$failedThresholds['Ping'] = $event->result->ping.' ms';
}
// Proceed with sending notifications only if there are any failed thresholds
if (count($failedThresholds) > 0) {
if ($this->notificationSettings->discord_on_threshold_failure && count($this->notificationSettings->discord_webhooks)) {
foreach ($this->notificationSettings->discord_webhooks as $webhook) {
// Construct the payload with the failed thresholds information
$contentLines = [
'Result ID: '.$event->result->id,
'Site Name: '.$this->generalSettings->site_name,
];
foreach ($failedThresholds as $metric => $result) {
$contentLines[] = "{$metric} threshold failed with result: {$result}.";
}
$payload = [
'content' => implode("\n", $contentLines),
];
// Send the request using Laravel's HTTP client
$response = Http::post($webhook['discord_webhook_url'], $payload);
}
}
}
}
}
/**
* Handle webhook notifications.
*
+8
View File
@@ -38,6 +38,14 @@ class NotificationSettings extends Settings
public ?array $webhook_urls;
public bool $discord_enabled;
public bool $discord_on_speedtest_run;
public bool $discord_on_threshold_failure;
public ?array $discord_webhooks;
public static function group(): string
{
return 'notification';
@@ -0,0 +1,17 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
return new class extends SettingsMigration
{
/**
* Run the migrations.
*/
public function up(): void
{
$this->migrator->add('notification.discord_enabled', false);
$this->migrator->add('notification.discord_on_speedtest_run', false);
$this->migrator->add('notification.discord_on_threshold_failure', false);
$this->migrator->add('notification.discord_webhooks', null);
}
};