Merge branch 'next' into authentik

This commit is contained in:
Andras Bacsai
2024-12-12 08:45:38 +01:00
49 changed files with 1035 additions and 143 deletions

View File

@@ -59,9 +59,10 @@ class NotifyDemo extends Command
<div class="text-yellow-500"> Channels: </div>
<ul class="text-coolify">
<li>email</li>
<li>slack</li>
<li>discord</li>
<li>telegram</li>
<li>slack</li>
<li>pushover</li>
</ul>
</div>
</div>
@@ -72,6 +73,6 @@ class NotifyDemo extends Command
<div class="mr-1">
In which manner you wish a <strong class="text-coolify">coolified</strong> notification?
</div>
HTML, ['email', 'slack', 'discord', 'telegram']);
HTML, ['email', 'discord', 'telegram', 'slack', 'pushover']);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class Seeder extends Command
{
protected $signature = 'start:seeder';
protected $description = 'Start Seeder';
public function handle()
{
if (config('constants.seeder.is_seeder_enabled')) {
$this->info('Seeder is enabled on this server.');
$this->call('db:seed', ['--class' => 'ProductionSeeder', '--force' => true]);
exit(0);
} else {
$this->info('Seeder is disabled on this server.');
exit(0);
}
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace App\Jobs;
use App\Notifications\Dto\PushoverMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
class SendMessageToPushoverJob implements ShouldBeEncrypted, ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* The number of times the job may be attempted.
*
* @var int
*/
public $tries = 5;
public $backoff = 10;
/**
* The maximum number of unhandled exceptions to allow before failing.
*/
public int $maxExceptions = 5;
public function __construct(
public PushoverMessage $message,
public string $token,
public string $user,
) {
$this->onQueue('high');
}
/**
* Execute the job.
*/
public function handle(): void
{
$response = Http::post('https://api.pushover.net/1/messages.json', $this->message->toPayload($this->token, $this->user));
if ($response->failed()) {
throw new \RuntimeException('Pushover notification failed with ' . $response->status() . ' status code.' . $response->body());
}
}
}

View File

@@ -32,7 +32,7 @@ class SendMessageToTelegramJob implements ShouldBeEncrypted, ShouldQueue
public array $buttons,
public string $token,
public string $chatId,
public ?string $topicId = null,
public ?string $threadId = null,
) {
$this->onQueue('high');
}
@@ -67,8 +67,8 @@ class SendMessageToTelegramJob implements ShouldBeEncrypted, ShouldQueue
'chat_id' => $this->chatId,
'text' => $this->text,
];
if ($this->topicId) {
$payload['message_thread_id'] = $this->topicId;
if ($this->threadId) {
$payload['message_thread_id'] = $this->threadId;
}
$response = Http::post($url, $payload);
if ($response->failed()) {

View File

@@ -14,8 +14,10 @@ class Email extends Component
{
protected $listeners = ['refresh' => '$refresh'];
#[Locked]
public Team $team;
#[Locked]
public EmailNotificationSettings $settings;
#[Locked]

View File

@@ -0,0 +1,184 @@
<?php
namespace App\Livewire\Notifications;
use App\Models\PushoverNotificationSettings;
use App\Models\Team;
use App\Notifications\Test;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Pushover extends Component
{
protected $listeners = ['refresh' => '$refresh'];
#[Locked]
public Team $team;
#[Locked]
public PushoverNotificationSettings $settings;
#[Validate(['boolean'])]
public bool $pushoverEnabled = false;
#[Validate(['nullable', 'string'])]
public ?string $pushoverUserKey = null;
#[Validate(['nullable', 'string'])]
public ?string $pushoverApiToken = null;
#[Validate(['boolean'])]
public bool $deploymentSuccessPushoverNotifications = false;
#[Validate(['boolean'])]
public bool $deploymentFailurePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $statusChangePushoverNotifications = false;
#[Validate(['boolean'])]
public bool $backupSuccessPushoverNotifications = false;
#[Validate(['boolean'])]
public bool $backupFailurePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $scheduledTaskSuccessPushoverNotifications = false;
#[Validate(['boolean'])]
public bool $scheduledTaskFailurePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $dockerCleanupSuccessPushoverNotifications = false;
#[Validate(['boolean'])]
public bool $dockerCleanupFailurePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $serverDiskUsagePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $serverReachablePushoverNotifications = false;
#[Validate(['boolean'])]
public bool $serverUnreachablePushoverNotifications = true;
public function mount()
{
try {
$this->team = auth()->user()->currentTeam();
$this->settings = $this->team->pushoverNotificationSettings;
$this->syncData();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function syncData(bool $toModel = false)
{
if ($toModel) {
$this->validate();
$this->settings->pushover_enabled = $this->pushoverEnabled;
$this->settings->pushover_user_key = $this->pushoverUserKey;
$this->settings->pushover_api_token = $this->pushoverApiToken;
$this->settings->deployment_success_pushover_notifications = $this->deploymentSuccessPushoverNotifications;
$this->settings->deployment_failure_pushover_notifications = $this->deploymentFailurePushoverNotifications;
$this->settings->status_change_pushover_notifications = $this->statusChangePushoverNotifications;
$this->settings->backup_success_pushover_notifications = $this->backupSuccessPushoverNotifications;
$this->settings->backup_failure_pushover_notifications = $this->backupFailurePushoverNotifications;
$this->settings->scheduled_task_success_pushover_notifications = $this->scheduledTaskSuccessPushoverNotifications;
$this->settings->scheduled_task_failure_pushover_notifications = $this->scheduledTaskFailurePushoverNotifications;
$this->settings->docker_cleanup_success_pushover_notifications = $this->dockerCleanupSuccessPushoverNotifications;
$this->settings->docker_cleanup_failure_pushover_notifications = $this->dockerCleanupFailurePushoverNotifications;
$this->settings->server_disk_usage_pushover_notifications = $this->serverDiskUsagePushoverNotifications;
$this->settings->server_reachable_pushover_notifications = $this->serverReachablePushoverNotifications;
$this->settings->server_unreachable_pushover_notifications = $this->serverUnreachablePushoverNotifications;
$this->settings->save();
refreshSession();
} else {
$this->pushoverEnabled = $this->settings->pushover_enabled;
$this->pushoverUserKey = $this->settings->pushover_user_key;
$this->pushoverApiToken = $this->settings->pushover_api_token;
$this->deploymentSuccessPushoverNotifications = $this->settings->deployment_success_pushover_notifications;
$this->deploymentFailurePushoverNotifications = $this->settings->deployment_failure_pushover_notifications;
$this->statusChangePushoverNotifications = $this->settings->status_change_pushover_notifications;
$this->backupSuccessPushoverNotifications = $this->settings->backup_success_pushover_notifications;
$this->backupFailurePushoverNotifications = $this->settings->backup_failure_pushover_notifications;
$this->scheduledTaskSuccessPushoverNotifications = $this->settings->scheduled_task_success_pushover_notifications;
$this->scheduledTaskFailurePushoverNotifications = $this->settings->scheduled_task_failure_pushover_notifications;
$this->dockerCleanupSuccessPushoverNotifications = $this->settings->docker_cleanup_success_pushover_notifications;
$this->dockerCleanupFailurePushoverNotifications = $this->settings->docker_cleanup_failure_pushover_notifications;
$this->serverDiskUsagePushoverNotifications = $this->settings->server_disk_usage_pushover_notifications;
$this->serverReachablePushoverNotifications = $this->settings->server_reachable_pushover_notifications;
$this->serverUnreachablePushoverNotifications = $this->settings->server_unreachable_pushover_notifications;
}
}
public function instantSavePushoverEnabled()
{
try {
$this->validate([
'pushoverUserKey' => 'required',
'pushoverApiToken' => 'required',
], [
'pushoverUserKey.required' => 'Pushover User Key is required.',
'pushoverApiToken.required' => 'Pushover API Token is required.',
]);
$this->saveModel();
} catch (\Throwable $e) {
$this->pushoverEnabled = false;
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
public function instantSave()
{
try {
$this->syncData(true);
} catch (\Throwable $e) {
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
public function submit()
{
try {
$this->resetErrorBag();
$this->syncData(true);
$this->saveModel();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function saveModel()
{
$this->syncData(true);
refreshSession();
$this->dispatch('success', 'Settings saved.');
}
public function sendTestNotification()
{
try {
$this->team->notify(new Test(channel: 'pushover'));
$this->dispatch('success', 'Test notification sent.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function render()
{
return view('livewire.notifications.pushover');
}
}

View File

@@ -5,13 +5,18 @@ namespace App\Livewire\Notifications;
use App\Models\SlackNotificationSettings;
use App\Models\Team;
use App\Notifications\Test;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Slack extends Component
{
protected $listeners = ['refresh' => '$refresh'];
#[Locked]
public Team $team;
#[Locked]
public SlackNotificationSettings $settings;
#[Validate(['boolean'])]
@@ -121,6 +126,8 @@ class Slack extends Component
$this->slackEnabled = false;
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
@@ -130,6 +137,8 @@ class Slack extends Component
$this->syncData(true);
} catch (\Throwable $e) {
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}

View File

@@ -5,13 +5,18 @@ namespace App\Livewire\Notifications;
use App\Models\Team;
use App\Models\TelegramNotificationSettings;
use App\Notifications\Test;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Telegram extends Component
{
protected $listeners = ['refresh' => '$refresh'];
#[Locked]
public Team $team;
#[Locked]
public TelegramNotificationSettings $settings;
#[Validate(['boolean'])]
@@ -60,40 +65,40 @@ class Telegram extends Component
public bool $serverUnreachableTelegramNotifications = true;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDeploymentSuccessTopicId = null;
public ?string $telegramNotificationsDeploymentSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDeploymentFailureTopicId = null;
public ?string $telegramNotificationsDeploymentFailureThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsStatusChangeTopicId = null;
public ?string $telegramNotificationsStatusChangeThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsBackupSuccessTopicId = null;
public ?string $telegramNotificationsBackupSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsBackupFailureTopicId = null;
public ?string $telegramNotificationsBackupFailureThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsScheduledTaskSuccessTopicId = null;
public ?string $telegramNotificationsScheduledTaskSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsScheduledTaskFailureTopicId = null;
public ?string $telegramNotificationsScheduledTaskFailureThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDockerCleanupSuccessTopicId = null;
public ?string $telegramNotificationsDockerCleanupSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDockerCleanupFailureTopicId = null;
public ?string $telegramNotificationsDockerCleanupFailureThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsServerDiskUsageTopicId = null;
public ?string $telegramNotificationsServerDiskUsageThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsServerReachableTopicId = null;
public ?string $telegramNotificationsServerReachableThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsServerUnreachableTopicId = null;
public ?string $telegramNotificationsServerUnreachableThreadId = null;
public function mount()
{
@@ -127,21 +132,20 @@ class Telegram extends Component
$this->settings->server_reachable_telegram_notifications = $this->serverReachableTelegramNotifications;
$this->settings->server_unreachable_telegram_notifications = $this->serverUnreachableTelegramNotifications;
$this->settings->telegram_notifications_deployment_success_topic_id = $this->telegramNotificationsDeploymentSuccessTopicId;
$this->settings->telegram_notifications_deployment_failure_topic_id = $this->telegramNotificationsDeploymentFailureTopicId;
$this->settings->telegram_notifications_status_change_topic_id = $this->telegramNotificationsStatusChangeTopicId;
$this->settings->telegram_notifications_backup_success_topic_id = $this->telegramNotificationsBackupSuccessTopicId;
$this->settings->telegram_notifications_backup_failure_topic_id = $this->telegramNotificationsBackupFailureTopicId;
$this->settings->telegram_notifications_scheduled_task_success_topic_id = $this->telegramNotificationsScheduledTaskSuccessTopicId;
$this->settings->telegram_notifications_scheduled_task_failure_topic_id = $this->telegramNotificationsScheduledTaskFailureTopicId;
$this->settings->telegram_notifications_docker_cleanup_success_topic_id = $this->telegramNotificationsDockerCleanupSuccessTopicId;
$this->settings->telegram_notifications_docker_cleanup_failure_topic_id = $this->telegramNotificationsDockerCleanupFailureTopicId;
$this->settings->telegram_notifications_server_disk_usage_topic_id = $this->telegramNotificationsServerDiskUsageTopicId;
$this->settings->telegram_notifications_server_reachable_topic_id = $this->telegramNotificationsServerReachableTopicId;
$this->settings->telegram_notifications_server_unreachable_topic_id = $this->telegramNotificationsServerUnreachableTopicId;
$this->settings->telegram_notifications_deployment_success_thread_id = $this->telegramNotificationsDeploymentSuccessThreadId;
$this->settings->telegram_notifications_deployment_failure_thread_id = $this->telegramNotificationsDeploymentFailureThreadId;
$this->settings->telegram_notifications_status_change_thread_id = $this->telegramNotificationsStatusChangeThreadId;
$this->settings->telegram_notifications_backup_success_thread_id = $this->telegramNotificationsBackupSuccessThreadId;
$this->settings->telegram_notifications_backup_failure_thread_id = $this->telegramNotificationsBackupFailureThreadId;
$this->settings->telegram_notifications_scheduled_task_success_thread_id = $this->telegramNotificationsScheduledTaskSuccessThreadId;
$this->settings->telegram_notifications_scheduled_task_failure_thread_id = $this->telegramNotificationsScheduledTaskFailureThreadId;
$this->settings->telegram_notifications_docker_cleanup_success_thread_id = $this->telegramNotificationsDockerCleanupSuccessThreadId;
$this->settings->telegram_notifications_docker_cleanup_failure_thread_id = $this->telegramNotificationsDockerCleanupFailureThreadId;
$this->settings->telegram_notifications_server_disk_usage_thread_id = $this->telegramNotificationsServerDiskUsageThreadId;
$this->settings->telegram_notifications_server_reachable_thread_id = $this->telegramNotificationsServerReachableThreadId;
$this->settings->telegram_notifications_server_unreachable_thread_id = $this->telegramNotificationsServerUnreachableThreadId;
$this->settings->save();
refreshSession();
} else {
$this->telegramEnabled = $this->settings->telegram_enabled;
$this->telegramToken = $this->settings->telegram_token;
@@ -160,18 +164,18 @@ class Telegram extends Component
$this->serverReachableTelegramNotifications = $this->settings->server_reachable_telegram_notifications;
$this->serverUnreachableTelegramNotifications = $this->settings->server_unreachable_telegram_notifications;
$this->telegramNotificationsDeploymentSuccessTopicId = $this->settings->telegram_notifications_deployment_success_topic_id;
$this->telegramNotificationsDeploymentFailureTopicId = $this->settings->telegram_notifications_deployment_failure_topic_id;
$this->telegramNotificationsStatusChangeTopicId = $this->settings->telegram_notifications_status_change_topic_id;
$this->telegramNotificationsBackupSuccessTopicId = $this->settings->telegram_notifications_backup_success_topic_id;
$this->telegramNotificationsBackupFailureTopicId = $this->settings->telegram_notifications_backup_failure_topic_id;
$this->telegramNotificationsScheduledTaskSuccessTopicId = $this->settings->telegram_notifications_scheduled_task_success_topic_id;
$this->telegramNotificationsScheduledTaskFailureTopicId = $this->settings->telegram_notifications_scheduled_task_failure_topic_id;
$this->telegramNotificationsDockerCleanupSuccessTopicId = $this->settings->telegram_notifications_docker_cleanup_success_topic_id;
$this->telegramNotificationsDockerCleanupFailureTopicId = $this->settings->telegram_notifications_docker_cleanup_failure_topic_id;
$this->telegramNotificationsServerDiskUsageTopicId = $this->settings->telegram_notifications_server_disk_usage_topic_id;
$this->telegramNotificationsServerReachableTopicId = $this->settings->telegram_notifications_server_reachable_topic_id;
$this->telegramNotificationsServerUnreachableTopicId = $this->settings->telegram_notifications_server_unreachable_topic_id;
$this->telegramNotificationsDeploymentSuccessThreadId = $this->settings->telegram_notifications_deployment_success_thread_id;
$this->telegramNotificationsDeploymentFailureThreadId = $this->settings->telegram_notifications_deployment_failure_thread_id;
$this->telegramNotificationsStatusChangeThreadId = $this->settings->telegram_notifications_status_change_thread_id;
$this->telegramNotificationsBackupSuccessThreadId = $this->settings->telegram_notifications_backup_success_thread_id;
$this->telegramNotificationsBackupFailureThreadId = $this->settings->telegram_notifications_backup_failure_thread_id;
$this->telegramNotificationsScheduledTaskSuccessThreadId = $this->settings->telegram_notifications_scheduled_task_success_thread_id;
$this->telegramNotificationsScheduledTaskFailureThreadId = $this->settings->telegram_notifications_scheduled_task_failure_thread_id;
$this->telegramNotificationsDockerCleanupSuccessThreadId = $this->settings->telegram_notifications_docker_cleanup_success_thread_id;
$this->telegramNotificationsDockerCleanupFailureThreadId = $this->settings->telegram_notifications_docker_cleanup_failure_thread_id;
$this->telegramNotificationsServerDiskUsageThreadId = $this->settings->telegram_notifications_server_disk_usage_thread_id;
$this->telegramNotificationsServerReachableThreadId = $this->settings->telegram_notifications_server_reachable_thread_id;
$this->telegramNotificationsServerUnreachableThreadId = $this->settings->telegram_notifications_server_unreachable_thread_id;
}
}
@@ -181,6 +185,8 @@ class Telegram extends Component
$this->syncData(true);
} catch (\Throwable $e) {
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
@@ -210,6 +216,8 @@ class Telegram extends Component
$this->telegramEnabled = false;
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
class PushoverNotificationSettings extends Model
{
use Notifiable;
public $timestamps = false;
protected $fillable = [
'team_id',
'pushover_enabled',
'pushover_user_key',
'pushover_api_token',
'deployment_success_pushover_notifications',
'deployment_failure_pushover_notifications',
'status_change_pushover_notifications',
'backup_success_pushover_notifications',
'backup_failure_pushover_notifications',
'scheduled_task_success_pushover_notifications',
'scheduled_task_failure_pushover_notifications',
'docker_cleanup_pushover_notifications',
'server_disk_usage_pushover_notifications',
'server_reachable_pushover_notifications',
'server_unreachable_pushover_notifications',
];
protected $casts = [
'pushover_enabled' => 'boolean',
'pushover_user_key' => 'encrypted',
'pushover_api_token' => 'encrypted',
'deployment_success_pushover_notifications' => 'boolean',
'deployment_failure_pushover_notifications' => 'boolean',
'status_change_pushover_notifications' => 'boolean',
'backup_success_pushover_notifications' => 'boolean',
'backup_failure_pushover_notifications' => 'boolean',
'scheduled_task_success_pushover_notifications' => 'boolean',
'scheduled_task_failure_pushover_notifications' => 'boolean',
'docker_cleanup_pushover_notifications' => 'boolean',
'server_disk_usage_pushover_notifications' => 'boolean',
'server_reachable_pushover_notifications' => 'boolean',
'server_unreachable_pushover_notifications' => 'boolean',
];
public function team()
{
return $this->belongsTo(Team::class);
}
public function isEnabled()
{
return $this->pushover_enabled;
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Models;
use App\Notifications\Channels\SendsDiscord;
use App\Notifications\Channels\SendsEmail;
use App\Notifications\Channels\SendsPushover;
use App\Notifications\Channels\SendsSlack;
use App\Traits\HasNotificationSettings;
use Illuminate\Database\Eloquent\Casts\Attribute;
@@ -32,7 +33,7 @@ use OpenApi\Attributes as OA;
]
)]
class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack
class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, SendsSlack
{
use HasNotificationSettings, Notifiable;
@@ -49,6 +50,7 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack
$team->discordNotificationSettings()->create();
$team->slackNotificationSettings()->create();
$team->telegramNotificationSettings()->create();
$team->pushoverNotificationSettings()->create();
});
static::saving(function ($team) {
@@ -155,6 +157,14 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack
return data_get($this, 'slack_webhook_url', null);
}
public function routeNotificationForPushover()
{
return [
'user' => data_get($this, 'pushover_user_key', null),
'token' => data_get($this, 'pushover_api_token', null),
];
}
public function getRecipients($notification)
{
$recipients = data_get($notification, 'emails', null);
@@ -174,7 +184,8 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack
return $this->getNotificationSettings('email')?->isEnabled() ||
$this->getNotificationSettings('discord')?->isEnabled() ||
$this->getNotificationSettings('slack')?->isEnabled() ||
$this->getNotificationSettings('telegram')?->isEnabled();
$this->getNotificationSettings('telegram')?->isEnabled() ||
$this->getNotificationSettings('pushover')?->isEnabled();
}
public function subscriptionEnded()
@@ -276,4 +287,9 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack
{
return $this->hasOne(SlackNotificationSettings::class);
}
public function pushoverNotificationSettings()
{
return $this->hasOne(PushoverNotificationSettings::class);
}
}

View File

@@ -30,17 +30,17 @@ class TelegramNotificationSettings extends Model
'server_reachable_telegram_notifications',
'server_unreachable_telegram_notifications',
'telegram_notifications_deployment_success_topic_id',
'telegram_notifications_deployment_failure_topic_id',
'telegram_notifications_status_change_topic_id',
'telegram_notifications_backup_success_topic_id',
'telegram_notifications_backup_failure_topic_id',
'telegram_notifications_scheduled_task_success_topic_id',
'telegram_notifications_scheduled_task_failure_topic_id',
'telegram_notifications_docker_cleanup_topic_id',
'telegram_notifications_server_disk_usage_topic_id',
'telegram_notifications_server_reachable_topic_id',
'telegram_notifications_server_unreachable_topic_id',
'telegram_notifications_deployment_success_thread_id',
'telegram_notifications_deployment_failure_thread_id',
'telegram_notifications_status_change_thread_id',
'telegram_notifications_backup_success_thread_id',
'telegram_notifications_backup_failure_thread_id',
'telegram_notifications_scheduled_task_success_thread_id',
'telegram_notifications_scheduled_task_failure_thread_id',
'telegram_notifications_docker_cleanup_thread_id',
'telegram_notifications_server_disk_usage_thread_id',
'telegram_notifications_server_reachable_thread_id',
'telegram_notifications_server_unreachable_thread_id',
];
protected $casts = [
@@ -60,17 +60,17 @@ class TelegramNotificationSettings extends Model
'server_reachable_telegram_notifications' => 'boolean',
'server_unreachable_telegram_notifications' => 'boolean',
'telegram_notifications_deployment_success_topic_id' => 'encrypted',
'telegram_notifications_deployment_failure_topic_id' => 'encrypted',
'telegram_notifications_status_change_topic_id' => 'encrypted',
'telegram_notifications_backup_success_topic_id' => 'encrypted',
'telegram_notifications_backup_failure_topic_id' => 'encrypted',
'telegram_notifications_scheduled_task_success_topic_id' => 'encrypted',
'telegram_notifications_scheduled_task_failure_topic_id' => 'encrypted',
'telegram_notifications_docker_cleanup_topic_id' => 'encrypted',
'telegram_notifications_server_disk_usage_topic_id' => 'encrypted',
'telegram_notifications_server_reachable_topic_id' => 'encrypted',
'telegram_notifications_server_unreachable_topic_id' => 'encrypted',
'telegram_notifications_deployment_success_thread_id' => 'encrypted',
'telegram_notifications_deployment_failure_thread_id' => 'encrypted',
'telegram_notifications_status_change_thread_id' => 'encrypted',
'telegram_notifications_backup_success_thread_id' => 'encrypted',
'telegram_notifications_backup_failure_thread_id' => 'encrypted',
'telegram_notifications_scheduled_task_success_thread_id' => 'encrypted',
'telegram_notifications_scheduled_task_failure_thread_id' => 'encrypted',
'telegram_notifications_docker_cleanup_thread_id' => 'encrypted',
'telegram_notifications_server_disk_usage_thread_id' => 'encrypted',
'telegram_notifications_server_reachable_thread_id' => 'encrypted',
'telegram_notifications_server_unreachable_thread_id' => 'encrypted',
];
public function team()

View File

@@ -6,6 +6,7 @@ use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -130,6 +131,31 @@ class DeploymentFailed extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
if ($this->preview) {
$title = "Pull request #{$this->preview->pull_request_id} deployment failed";
$message = "Pull request deployment failed for {$this->application_name}";
} else {
$title = 'Deployment failed';
$message = "Deployment failed for {$this->application_name}";
}
$buttons[] = [
'text' => 'Deployment logs',
'url' => $this->deployment_url,
];
return new PushoverMessage(
title: $title,
level: 'error',
message: $message,
buttons: [
...$buttons,
],
);
}
public function toSlack(): SlackMessage
{
if ($this->preview) {

View File

@@ -6,6 +6,7 @@ use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -139,6 +140,42 @@ class DeploymentSuccess extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
if ($this->preview) {
$title = "Pull request #{$this->preview->pull_request_id} successfully deployed";
$message = 'New PR' . $this->preview->pull_request_id . ' version successfully deployed of ' . $this->application_name . '';
if ($this->preview->fqdn) {
$buttons[] = [
'text' => 'Open Application',
'url' => $this->preview->fqdn,
];
}
} else {
$title = 'New version successfully deployed';
$message = 'New version successfully deployed of ' . $this->application_name . '';
if ($this->fqdn) {
$buttons[] = [
'text' => 'Open Application',
'url' => $this->fqdn,
];
}
}
$buttons[] = [
'text' => 'Deployment logs',
'url' => $this->deployment_url,
];
return new PushoverMessage(
title: $title,
level: 'success',
message: $message,
buttons: [
...$buttons,
],
);
}
public function toSlack(): SlackMessage
{
if ($this->preview) {

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Application;
use App\Models\Application;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -77,6 +78,23 @@ class StatusChanged extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
$message = $this->resource_name . ' has been stopped.';
return new PushoverMessage(
title: 'Application stopped',
level: 'error',
message: $message,
buttons: [
[
'text' => 'Open Application in Coolify',
'url' => $this->resource_url,
],
],
);
}
public function toSlack(): SlackMessage
{
$title = 'Application stopped';

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Notifications\Channels;
use App\Jobs\SendMessageToPushoverJob;
use Illuminate\Notifications\Notification;
class PushoverChannel
{
public function send(SendsPushover $notifiable, Notification $notification): void
{
$message = $notification->toPushover();
$pushoverSettings = $notifiable->pushoverNotificationSettings;
if (! $pushoverSettings || ! $pushoverSettings->isEnabled() || ! $pushoverSettings->pushover_user_key || ! $pushoverSettings->pushover_api_token) {
return;
}
SendMessageToPushoverJob::dispatch($message, $pushoverSettings->pushover_api_token, $pushoverSettings->pushover_user_key);
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace App\Notifications\Channels;
interface SendsPushover
{
public function routeNotificationForPushover();
}

View File

@@ -16,18 +16,25 @@ class TelegramChannel
$telegramToken = $settings->telegram_token;
$chatId = $settings->telegram_chat_id;
$topicId = match (get_class($notification)) {
\App\Notifications\Test::class => $settings->telegram_notifications_test_topic_id,
$threadId = match (get_class($notification)) {
\App\Notifications\Application\DeploymentSuccess::class => $settings->telegram_notifications_deployment_success_thread_id,
\App\Notifications\Application\DeploymentFailed::class => $settings->telegram_notifications_deployment_failure_thread_id,
\App\Notifications\Application\StatusChanged::class,
\App\Notifications\Container\ContainerRestarted::class,
\App\Notifications\Container\ContainerStopped::class => $settings->telegram_notifications_status_change_topic_id,
\App\Notifications\Application\DeploymentSuccess::class => $settings->telegram_notifications_deployment_success_topic_id,
\App\Notifications\Application\DeploymentFailed::class => $settings->telegram_notifications_deployment_failure_topic_id,
\App\Notifications\Database\BackupSuccess::class => $settings->telegram_notifications_backup_success_topic_id,
\App\Notifications\Database\BackupFailed::class => $settings->telegram_notifications_backup_failure_topic_id,
\App\Notifications\ScheduledTask\TaskFailed::class => $settings->telegram_notifications_scheduled_task_failure_topic_id,
\App\Notifications\Server\Unreachable::class => $settings->telegram_notifications_server_unreachable_topic_id,
\App\Notifications\Server\Reachable::class => $settings->telegram_notifications_server_reachable_topic_id,
\App\Notifications\Container\ContainerStopped::class => $settings->telegram_notifications_status_change_thread_id,
\App\Notifications\Database\BackupSuccess::class => $settings->telegram_notifications_backup_success_thread_id,
\App\Notifications\Database\BackupFailed::class => $settings->telegram_notifications_backup_failure_thread_id,
\App\Notifications\ScheduledTask\TaskSuccess::class => $settings->telegram_notifications_scheduled_task_success_thread_id,
\App\Notifications\ScheduledTask\TaskFailed::class => $settings->telegram_notifications_scheduled_task_failure_thread_id,
\App\Notifications\Server\DockerCleanupSuccess::class => $settings->telegram_notifications_docker_cleanup_success_thread_id,
\App\Notifications\Server\DockerCleanupFailed::class => $settings->telegram_notifications_docker_cleanup_failure_thread_id,
\App\Notifications\Server\HighDiskUsage::class => $settings->telegram_notifications_server_disk_usage_thread_id,
\App\Notifications\Server\Unreachable::class => $settings->telegram_notifications_server_unreachable_thread_id,
\App\Notifications\Server\Reachable::class => $settings->telegram_notifications_server_reachable_thread_id,
default => null,
};
@@ -35,6 +42,6 @@ class TelegramChannel
return;
}
SendMessageToTelegramJob::dispatch($message, $buttons, $telegramToken, $chatId, $topicId);
SendMessageToTelegramJob::dispatch($message, $buttons, $telegramToken, $chatId, $threadId);
}
}

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Container;
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -68,6 +69,24 @@ class ContainerRestarted extends CustomEmailNotification
return $payload;
}
public function toPushover(): PushoverMessage
{
$buttons = [];
if ($this->url) {
$buttons[] = [
'text' => 'Check Proxy in Coolify',
'url' => $this->url,
];
}
return new PushoverMessage(
title: 'Resource restarted',
level: 'warning',
message: "A resource ({$this->name}) has been restarted automatically on {$this->server->name}",
buttons: $buttons,
);
}
public function toSlack(): SlackMessage
{
$title = 'Resource restarted';

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Container;
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -68,6 +69,25 @@ class ContainerStopped extends CustomEmailNotification
return $payload;
}
public function toPushover(): PushoverMessage
{
$buttons = [];
if ($this->url) {
$buttons[] = [
'text' => 'Open Application in Coolify',
'url' => $this->url,
];
}
return new PushoverMessage(
title: 'Resource stopped',
level: 'error',
message: "A resource ({$this->name}) has been stopped unexpectedly on {$this->server->name}",
buttons: $buttons,
);
}
public function toSlack(): SlackMessage
{
$title = 'Resource stopped';

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Database;
use App\Models\ScheduledDatabaseBackup;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -64,6 +65,15 @@ class BackupFailed extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'Database backup failed',
level: 'error',
message: "Database backup for {$this->name} (db:{$this->database_name}) was FAILED<br/><br/><b>Frequency:</b> {$this->frequency} .<br/><b>Reason:</b> {$this->output}",
);
}
public function toSlack(): SlackMessage
{
$title = 'Database backup failed';

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Database;
use App\Models\ScheduledDatabaseBackup;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -62,6 +63,17 @@ class BackupSuccess extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'Database backup successful',
level: 'success',
message: "Database backup for {$this->name} (db:{$this->database_name}) was successful.<br/><br/><b>Frequency:</b> {$this->frequency}.",
);
}
public function toSlack(): SlackMessage
{
$title = 'Database backup successful';

View File

@@ -0,0 +1,50 @@
<?php
namespace App\Notifications\Dto;
use Illuminate\Support\Facades\Log;
class PushoverMessage
{
public function __construct(
public string $title,
public string $message,
public array $buttons = [],
public string $level = 'info',
) {}
public function getLevelIcon(): string
{
return match ($this->level) {
'info' => '',
'error' => '❌',
'success' => '✅ ',
'warning' => '⚠️',
};
}
public function toPayload(string $token, string $user): array
{
$levelIcon = $this->getLevelIcon();
$payload = [
'token' => $token,
'user' => $user,
'title' => "{$levelIcon} {$this->title}",
'message' => $this->message,
'html' => 1,
];
foreach ($this->buttons as $button) {
$buttonUrl = data_get($button, 'url');
$text = data_get($button, 'text', 'Click here');
if ($buttonUrl && str_contains($buttonUrl, 'http://localhost')) {
$buttonUrl = str_replace('http://localhost', config('app.url'), $buttonUrl);
}
$payload['message'] .= "&nbsp;<a href='" . $buttonUrl . "'>" . $text . '</a>';
}
Log::info('Pushover message', $payload);
return $payload;
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Notifications\Internal;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
@@ -40,6 +41,15 @@ class GeneralNotification extends Notification implements ShouldQueue
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'General Notification',
level: 'info',
message: $this->message,
);
}
public function toSlack(): SlackMessage
{
return new SlackMessage(

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\ScheduledTask;
use App\Models\ScheduledTask;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -70,6 +71,30 @@ class TaskFailed extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
$message = "Scheduled task ({$this->task->name}) failed<br/>";
if ($this->output) {
$message .= "<br/><b>Error Output:</b>{$this->output}";
}
$buttons = [];
if ($this->url) {
$buttons[] = [
'text' => 'Open task in Coolify',
'url' => (string) $this->url,
];
}
return new PushoverMessage(
title: 'Scheduled task failed',
level: 'error',
message: $message,
buttons: $buttons,
);
}
public function toSlack(): SlackMessage
{
$title = 'Scheduled task failed';

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\ScheduledTask;
use App\Models\ScheduledTask;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -70,6 +71,25 @@ class TaskSuccess extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
$message = "Coolify: Scheduled task ({$this->task->name}) succeeded.";
$buttons = [];
if ($this->url) {
$buttons[] = [
'text' => 'Open task in Coolify',
'url' => (string) $this->url,
];
}
return new PushoverMessage(
title: 'Scheduled task succeeded',
level: 'success',
message: $message,
buttons: $buttons,
);
}
public function toSlack(): SlackMessage
{
$title = 'Scheduled task succeeded';

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Server;
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -48,6 +49,15 @@ class DockerCleanupFailed extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'Docker cleanup job failed',
level: 'error',
message: "[ACTION REQUIRED] Docker cleanup job failed on {$this->server->name}!\n\n{$this->message}",
);
}
public function toSlack(): SlackMessage
{
return new SlackMessage(

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Server;
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -48,6 +49,15 @@ class DockerCleanupSuccess extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'Docker cleanup job succeeded',
level: 'success',
message: "Docker cleanup job succeeded on {$this->server->name}!\n\n{$this->message}",
);
}
public function toSlack(): SlackMessage
{
return new SlackMessage(

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Server;
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -51,6 +52,15 @@ class ForceDisabled extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'Server disabled',
level: 'error',
message: "Server ({$this->server->name}) disabled because it is not paid!\n All automations and integrations are stopped.<br/>Please update your subscription to enable the server again [here](https://app.coolify.io/subscriptions).",
);
}
public function toSlack(): SlackMessage
{
$title = 'Server disabled';

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Server;
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -47,6 +48,15 @@ class ForceEnabled extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'Server enabled',
level: 'success',
message: "Server ({$this->server->name}) enabled again!",
);
}
public function toSlack(): SlackMessage
{
return new SlackMessage(

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Server;
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -57,6 +58,19 @@ class HighDiskUsage extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'High disk usage detected',
level: 'warning',
message: "Server '{$this->server->name}' high disk usage detected!<br/><br/><b>Disk usage:</b> {$this->disk_usage}%.<br/><b>Threshold:</b> {$this->server_disk_usage_notification_threshold}%.<br/>Please cleanup your disk to prevent data-loss.",
buttons: [
'Change settings' => base_url().'/server/'.$this->server->uuid."#advanced",
'Tips for cleanup' => "https://coolify.io/docs/knowledge-base/server/automated-cleanup",
],
);
}
public function toSlack(): SlackMessage
{
$description = "Server '{$this->server->name}' high disk usage detected!\n";

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Server;
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -49,6 +50,15 @@ class Reachable extends CustomEmailNotification
);
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'Server revived',
message: "Server '{$this->server->name}' revived. All automations & integrations are turned on again!",
level: 'success',
);
}
public function toTelegram(): array
{
return [

View File

@@ -5,6 +5,7 @@ namespace App\Notifications\Server;
use App\Models\Server;
use App\Notifications\CustomEmailNotification;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Notifications\Messages\MailMessage;
@@ -60,6 +61,15 @@ class Unreachable extends CustomEmailNotification
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'Server unreachable',
level: 'error',
message: "Your server '{$this->server->name}' is unreachable.<br/>All automations & integrations are turned off!<br/><br/><b>IMPORTANT:</b> We automatically try to revive your server and turn on all automations & integrations.",
);
}
public function toSlack(): SlackMessage
{
$description = "Your server '{$this->server->name}' is unreachable.\n";

View File

@@ -6,7 +6,9 @@ use App\Notifications\Channels\DiscordChannel;
use App\Notifications\Channels\EmailChannel;
use App\Notifications\Channels\SlackChannel;
use App\Notifications\Channels\TelegramChannel;
use App\Notifications\Channels\PushoverChannel;
use App\Notifications\Dto\DiscordMessage;
use App\Notifications\Dto\PushoverMessage;
use App\Notifications\Dto\SlackMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
@@ -33,6 +35,7 @@ class Test extends Notification implements ShouldQueue
'discord' => [DiscordChannel::class],
'telegram' => [TelegramChannel::class],
'slack' => [SlackChannel::class],
'pushover' => [PushoverChannel::class],
default => [],
};
} else {
@@ -85,6 +88,20 @@ class Test extends Notification implements ShouldQueue
];
}
public function toPushover(): PushoverMessage
{
return new PushoverMessage(
title: 'Test Pushover Notification',
message: 'This is a test Pushover notification from Coolify.',
buttons: [
[
'text' => 'Go to your dashboard',
'url' => base_url(),
],
],
);
}
public function toSlack(): SlackMessage
{
return new SlackMessage(

View File

@@ -6,6 +6,7 @@ use App\Notifications\Channels\DiscordChannel;
use App\Notifications\Channels\EmailChannel;
use App\Notifications\Channels\SlackChannel;
use App\Notifications\Channels\TelegramChannel;
use App\Notifications\Channels\PushoverChannel;
use Illuminate\Database\Eloquent\Model;
trait HasNotificationSettings
@@ -27,6 +28,7 @@ trait HasNotificationSettings
'discord' => $this->discordNotificationSettings,
'telegram' => $this->telegramNotificationSettings,
'slack' => $this->slackNotificationSettings,
'pushover' => $this->pushoverNotificationSettings,
default => null,
};
}
@@ -73,6 +75,7 @@ trait HasNotificationSettings
'discord' => DiscordChannel::class,
'telegram' => TelegramChannel::class,
'slack' => SlackChannel::class,
'pushover' => PushoverChannel::class,
];
if ($event === 'general') {