From ef354295331ea38838ec577c486c74e6ea1a5f38 Mon Sep 17 00:00:00 2001 From: Zao Soula Date: Wed, 11 Dec 2024 15:54:11 +0100 Subject: [PATCH 01/18] feat(notification): add Pushover --- app/Console/Commands/NotifyDemo.php | 3 +- app/Jobs/SendMessageToPushoverJob.php | 50 +++++ app/Livewire/Notifications/Pushover.php | 176 ++++++++++++++++++ app/Models/PushoverNotificationSettings.php | 61 ++++++ app/Models/Team.php | 20 +- .../Application/DeploymentFailed.php | 26 +++ .../Application/DeploymentSuccess.php | 37 ++++ .../Application/StatusChanged.php | 18 ++ .../Channels/PushoverChannel.php | 21 +++ app/Notifications/Channels/SendsPushover.php | 8 + .../Container/ContainerRestarted.php | 19 ++ .../Container/ContainerStopped.php | 20 ++ app/Notifications/Database/BackupFailed.php | 10 + app/Notifications/Database/BackupSuccess.php | 12 ++ app/Notifications/Dto/PushoverMessage.php | 50 +++++ .../Internal/GeneralNotification.php | 10 + .../ScheduledTask/TaskFailed.php | 25 +++ .../ScheduledTask/TaskSuccess.php | 20 ++ .../Server/DockerCleanupFailed.php | 10 + .../Server/DockerCleanupSuccess.php | 10 + app/Notifications/Server/ForceDisabled.php | 10 + app/Notifications/Server/ForceEnabled.php | 10 + app/Notifications/Server/HighDiskUsage.php | 14 ++ app/Notifications/Server/Reachable.php | 10 + app/Notifications/Server/Unreachable.php | 10 + app/Notifications/Test.php | 17 ++ app/Traits/HasNotificationSettings.php | 3 + ...e_pushover_notification_settings_table.php | 47 +++++ .../components/notification/navbar.blade.php | 6 +- .../livewire/notifications/pushover.blade.php | 84 +++++++++ routes/web.php | 2 + 31 files changed, 815 insertions(+), 4 deletions(-) create mode 100644 app/Jobs/SendMessageToPushoverJob.php create mode 100644 app/Livewire/Notifications/Pushover.php create mode 100644 app/Models/PushoverNotificationSettings.php create mode 100644 app/Notifications/Channels/PushoverChannel.php create mode 100644 app/Notifications/Channels/SendsPushover.php create mode 100644 app/Notifications/Dto/PushoverMessage.php create mode 100644 database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php create mode 100644 resources/views/livewire/notifications/pushover.blade.php diff --git a/app/Console/Commands/NotifyDemo.php b/app/Console/Commands/NotifyDemo.php index f0131b7b2..b6e5015f8 100644 --- a/app/Console/Commands/NotifyDemo.php +++ b/app/Console/Commands/NotifyDemo.php @@ -62,6 +62,7 @@ private function showHelp()
  • slack
  • discord
  • telegram
  • +
  • pushover
  • @@ -72,6 +73,6 @@ private function showHelp()
    In which manner you wish a coolified notification?
    - HTML, ['email', 'slack', 'discord', 'telegram']); + HTML, ['email', 'slack', 'discord', 'telegram', 'pushover']); } } diff --git a/app/Jobs/SendMessageToPushoverJob.php b/app/Jobs/SendMessageToPushoverJob.php new file mode 100644 index 000000000..834a32b07 --- /dev/null +++ b/app/Jobs/SendMessageToPushoverJob.php @@ -0,0 +1,50 @@ +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()); + } + } +} diff --git a/app/Livewire/Notifications/Pushover.php b/app/Livewire/Notifications/Pushover.php new file mode 100644 index 000000000..7a3b294a2 --- /dev/null +++ b/app/Livewire/Notifications/Pushover.php @@ -0,0 +1,176 @@ +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 = $this->pushoverUser; + $this->settings->pushover_token = $this->pushoverToken; + + $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->pushoverUser = $this->settings->pushover_user; + $this->pushoverToken = $this->settings->pushover_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([ + 'pushoverUser' => 'required', + 'pushoverToken' => 'required', + ], [ + 'pushoverUser.required' => 'Pushover User is required.', + 'pushoverToken.required' => 'Pushover Token is required.', + ]); + $this->saveModel(); + } catch (\Throwable $e) { + $this->pushoverEnabled = false; + + return handleError($e, $this); + } + } + + public function instantSave() + { + try { + $this->syncData(true); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + 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'); + } +} diff --git a/app/Models/PushoverNotificationSettings.php b/app/Models/PushoverNotificationSettings.php new file mode 100644 index 000000000..7576a6040 --- /dev/null +++ b/app/Models/PushoverNotificationSettings.php @@ -0,0 +1,61 @@ + 'boolean', + 'pushover_user' => 'encrypted', + 'pushover_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; + } +} diff --git a/app/Models/Team.php b/app/Models/Team.php index 07424a55f..fc10892a4 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -5,6 +5,7 @@ use App\Notifications\Channels\SendsDiscord; use App\Notifications\Channels\SendsEmail; use App\Notifications\Channels\SendsSlack; +use App\Notifications\Channels\SendsPushover; use App\Traits\HasNotificationSettings; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; @@ -32,7 +33,7 @@ ] )] -class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack +class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack, SendsPushover { use HasNotificationSettings, Notifiable; @@ -49,6 +50,7 @@ protected static function booted() $team->discordNotificationSettings()->create(); $team->slackNotificationSettings()->create(); $team->telegramNotificationSettings()->create(); + $team->pushoverNotificationSettings()->create(); }); static::saving(function ($team) { @@ -154,6 +156,14 @@ public function routeNotificationForSlack() { return data_get($this, 'slack_webhook_url', null); } + + public function routeNotificationForPushover() + { + return [ + 'user' => data_get($this, 'pushover_user', null), + 'token' => data_get($this, 'pushover_token', null), + ]; + } public function getRecipients($notification) { @@ -174,7 +184,8 @@ public function isAnyNotificationEnabled() 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 @@ public function slackNotificationSettings() { return $this->hasOne(SlackNotificationSettings::class); } + + public function pushoverNotificationSettings() + { + return $this->hasOne(PushoverNotificationSettings::class); + } } diff --git a/app/Notifications/Application/DeploymentFailed.php b/app/Notifications/Application/DeploymentFailed.php index 06a2b48e3..80c1c421c 100644 --- a/app/Notifications/Application/DeploymentFailed.php +++ b/app/Notifications/Application/DeploymentFailed.php @@ -6,6 +6,7 @@ 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 @@ public function toTelegram(): array ]; } + 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) { diff --git a/app/Notifications/Application/DeploymentSuccess.php b/app/Notifications/Application/DeploymentSuccess.php index 548f5c6e5..b1a3d5225 100644 --- a/app/Notifications/Application/DeploymentSuccess.php +++ b/app/Notifications/Application/DeploymentSuccess.php @@ -6,6 +6,7 @@ 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 @@ public function toTelegram(): array ]; } + 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) { diff --git a/app/Notifications/Application/StatusChanged.php b/app/Notifications/Application/StatusChanged.php index 32a6a659a..c9c7344c4 100644 --- a/app/Notifications/Application/StatusChanged.php +++ b/app/Notifications/Application/StatusChanged.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + 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'; diff --git a/app/Notifications/Channels/PushoverChannel.php b/app/Notifications/Channels/PushoverChannel.php new file mode 100644 index 000000000..56d3cb03d --- /dev/null +++ b/app/Notifications/Channels/PushoverChannel.php @@ -0,0 +1,21 @@ +toPushover(); + $pushoverSettings = $notifiable->pushoverNotificationSettings; + + if (! $pushoverSettings || ! $pushoverSettings->isEnabled() || ! $pushoverSettings->pushover_user || ! $pushoverSettings->pushover_token) { + return; + } + + SendMessageToPushoverJob::dispatch($message, $pushoverSettings->pushover_token, $pushoverSettings->pushover_user); + } +} diff --git a/app/Notifications/Channels/SendsPushover.php b/app/Notifications/Channels/SendsPushover.php new file mode 100644 index 000000000..7922eefb4 --- /dev/null +++ b/app/Notifications/Channels/SendsPushover.php @@ -0,0 +1,8 @@ +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'; diff --git a/app/Notifications/Container/ContainerStopped.php b/app/Notifications/Container/ContainerStopped.php index bc6e52b6d..49aea196d 100644 --- a/app/Notifications/Container/ContainerStopped.php +++ b/app/Notifications/Container/ContainerStopped.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array 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'; diff --git a/app/Notifications/Database/BackupFailed.php b/app/Notifications/Database/BackupFailed.php index 2208f7b1d..6dcb70583 100644 --- a/app/Notifications/Database/BackupFailed.php +++ b/app/Notifications/Database/BackupFailed.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + 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

    Frequency: {$this->frequency} .
    Reason: {$this->output}", + ); + } + public function toSlack(): SlackMessage { $title = 'Database backup failed'; diff --git a/app/Notifications/Database/BackupSuccess.php b/app/Notifications/Database/BackupSuccess.php index 10b4ff3df..4c3e8e060 100644 --- a/app/Notifications/Database/BackupSuccess.php +++ b/app/Notifications/Database/BackupSuccess.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + + 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.

    Frequency: {$this->frequency}.", + ); + } + + public function toSlack(): SlackMessage { $title = 'Database backup successful'; diff --git a/app/Notifications/Dto/PushoverMessage.php b/app/Notifications/Dto/PushoverMessage.php new file mode 100644 index 000000000..6022c2885 --- /dev/null +++ b/app/Notifications/Dto/PushoverMessage.php @@ -0,0 +1,50 @@ +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'] .= " " . $text . ''; + } + + Log::info('Pushover message', $payload); + + return $payload; + } +} diff --git a/app/Notifications/Internal/GeneralNotification.php b/app/Notifications/Internal/GeneralNotification.php index 7049e3055..1d2367210 100644 --- a/app/Notifications/Internal/GeneralNotification.php +++ b/app/Notifications/Internal/GeneralNotification.php @@ -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 @@ public function toTelegram(): array ]; } + public function toPushover(): PushoverMessage + { + return new PushoverMessage( + title: 'General Notification', + level: 'info', + message: $this->message, + ); + } + public function toSlack(): SlackMessage { return new SlackMessage( diff --git a/app/Notifications/ScheduledTask/TaskFailed.php b/app/Notifications/ScheduledTask/TaskFailed.php index 56c410ecb..c4d92f213 100644 --- a/app/Notifications/ScheduledTask/TaskFailed.php +++ b/app/Notifications/ScheduledTask/TaskFailed.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + public function toPushover(): PushoverMessage + { + $message = "Scheduled task ({$this->task->name}) failed
    "; + + if ($this->output) { + $message .= "
    Error Output:{$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'; diff --git a/app/Notifications/ScheduledTask/TaskSuccess.php b/app/Notifications/ScheduledTask/TaskSuccess.php index fc79aea37..5d4154e7a 100644 --- a/app/Notifications/ScheduledTask/TaskSuccess.php +++ b/app/Notifications/ScheduledTask/TaskSuccess.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + 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'; diff --git a/app/Notifications/Server/DockerCleanupFailed.php b/app/Notifications/Server/DockerCleanupFailed.php index 53714925c..0291eed19 100644 --- a/app/Notifications/Server/DockerCleanupFailed.php +++ b/app/Notifications/Server/DockerCleanupFailed.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + 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( diff --git a/app/Notifications/Server/DockerCleanupSuccess.php b/app/Notifications/Server/DockerCleanupSuccess.php index 85a819da2..1a652d189 100644 --- a/app/Notifications/Server/DockerCleanupSuccess.php +++ b/app/Notifications/Server/DockerCleanupSuccess.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + 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( diff --git a/app/Notifications/Server/ForceDisabled.php b/app/Notifications/Server/ForceDisabled.php index e122849da..7a1f7bcbf 100644 --- a/app/Notifications/Server/ForceDisabled.php +++ b/app/Notifications/Server/ForceDisabled.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + 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.
    Please update your subscription to enable the server again [here](https://app.coolify.io/subscriptions).", + ); + } + public function toSlack(): SlackMessage { $title = 'Server disabled'; diff --git a/app/Notifications/Server/ForceEnabled.php b/app/Notifications/Server/ForceEnabled.php index a0e0a8b59..36dad3c60 100644 --- a/app/Notifications/Server/ForceEnabled.php +++ b/app/Notifications/Server/ForceEnabled.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + 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( diff --git a/app/Notifications/Server/HighDiskUsage.php b/app/Notifications/Server/HighDiskUsage.php index 9f4826689..aea9abd03 100644 --- a/app/Notifications/Server/HighDiskUsage.php +++ b/app/Notifications/Server/HighDiskUsage.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): array ]; } + public function toPushover(): PushoverMessage + { + return new PushoverMessage( + title: 'High disk usage detected', + level: 'warning', + message: "Server '{$this->server->name}' high disk usage detected!

    Disk usage: {$this->disk_usage}%.
    Threshold: {$this->server_disk_usage_notification_threshold}%.
    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"; diff --git a/app/Notifications/Server/Reachable.php b/app/Notifications/Server/Reachable.php index 4917e04f8..e03aef6b7 100644 --- a/app/Notifications/Server/Reachable.php +++ b/app/Notifications/Server/Reachable.php @@ -5,6 +5,7 @@ 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 @@ public function toDiscord(): DiscordMessage ); } + 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 [ diff --git a/app/Notifications/Server/Unreachable.php b/app/Notifications/Server/Unreachable.php index 43f176d49..fe90cc610 100644 --- a/app/Notifications/Server/Unreachable.php +++ b/app/Notifications/Server/Unreachable.php @@ -5,6 +5,7 @@ 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 @@ public function toTelegram(): ?array ]; } + public function toPushover(): PushoverMessage + { + return new PushoverMessage( + title: 'Server unreachable', + level: 'error', + message: "Your server '{$this->server->name}' is unreachable.
    All automations & integrations are turned off!

    IMPORTANT: 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"; diff --git a/app/Notifications/Test.php b/app/Notifications/Test.php index da9098500..65971a0ee 100644 --- a/app/Notifications/Test.php +++ b/app/Notifications/Test.php @@ -6,7 +6,9 @@ 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 @@ public function via(object $notifiable): array 'discord' => [DiscordChannel::class], 'telegram' => [TelegramChannel::class], 'slack' => [SlackChannel::class], + 'pushover' => [PushoverChannel::class], default => [], }; } else { @@ -85,6 +88,20 @@ public function toTelegram(): array ]; } + 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( diff --git a/app/Traits/HasNotificationSettings.php b/app/Traits/HasNotificationSettings.php index 82cbda6ad..ef858d0b6 100644 --- a/app/Traits/HasNotificationSettings.php +++ b/app/Traits/HasNotificationSettings.php @@ -6,6 +6,7 @@ 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 @@ public function getNotificationSettings(string $channel): ?Model 'discord' => $this->discordNotificationSettings, 'telegram' => $this->telegramNotificationSettings, 'slack' => $this->slackNotificationSettings, + 'pushover' => $this->pushoverNotificationSettings, default => null, }; } @@ -73,6 +75,7 @@ public function getEnabledChannels(string $event): array 'discord' => DiscordChannel::class, 'telegram' => TelegramChannel::class, 'slack' => SlackChannel::class, + 'pushover' => PushoverChannel::class, ]; if ($event === 'general') { diff --git a/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php b/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php new file mode 100644 index 000000000..907f7a052 --- /dev/null +++ b/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php @@ -0,0 +1,47 @@ +id(); + $table->foreignId('team_id')->constrained()->cascadeOnDelete(); + + $table->boolean('pushover_enabled')->default(false); + $table->text('pushover_user')->nullable(); + $table->text('pushover_token')->nullable(); + + $table->boolean('deployment_success_pushover_notifications')->default(false); + $table->boolean('deployment_failure_pushover_notifications')->default(true); + $table->boolean('status_change_pushover_notifications')->default(false); + $table->boolean('backup_success_pushover_notifications')->default(false); + $table->boolean('backup_failure_pushover_notifications')->default(true); + $table->boolean('scheduled_task_success_pushover_notifications')->default(false); + $table->boolean('scheduled_task_failure_pushover_notifications')->default(true); + $table->boolean('docker_cleanup_success_pushover_notifications')->default(false); + $table->boolean('docker_cleanup_failure_pushover_notifications')->default(true); + $table->boolean('server_disk_usage_pushover_notifications')->default(true); + $table->boolean('server_reachable_pushover_notifications')->default(false); + $table->boolean('server_unreachable_pushover_notifications')->default(true); + + $table->unique(['team_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('pushover_notification_settings'); + } +}; + diff --git a/resources/views/components/notification/navbar.blade.php b/resources/views/components/notification/navbar.blade.php index c4dbd25af..0193cf3cd 100644 --- a/resources/views/components/notification/navbar.blade.php +++ b/resources/views/components/notification/navbar.blade.php @@ -19,6 +19,10 @@ href="{{ route('notifications.slack') }}"> + + + - \ No newline at end of file + diff --git a/resources/views/livewire/notifications/pushover.blade.php b/resources/views/livewire/notifications/pushover.blade.php new file mode 100644 index 000000000..28a55516d --- /dev/null +++ b/resources/views/livewire/notifications/pushover.blade.php @@ -0,0 +1,84 @@ +
    + + Notifications | Coolify + + +
    +
    +

    Pushover

    + + Save + + @if ($pushoverEnabled) + + Send Test Notification + + @else + + Send Test Notification + + @endif +
    +
    + +
    + + + +

    Notification Settings

    +

    + Select events for which you would like to receive Pushover notifications. +

    +
    +
    +

    Deployments

    +
    + + + +
    +
    +
    +

    Backups

    +
    + + +
    +
    +
    +

    Scheduled Tasks

    +
    + + +
    +
    +
    +

    Server

    +
    + + + + + +
    +
    +
    +
    diff --git a/routes/web.php b/routes/web.php index 3570fe0ed..38ce7f15c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -14,6 +14,7 @@ use App\Livewire\Notifications\Email as NotificationEmail; use App\Livewire\Notifications\Slack as NotificationSlack; use App\Livewire\Notifications\Telegram as NotificationTelegram; +use App\Livewire\Notifications\Pushover as NotificationPushover; use App\Livewire\Profile\Index as ProfileIndex; use App\Livewire\Project\Application\Configuration as ApplicationConfiguration; use App\Livewire\Project\Application\Deployment\Index as DeploymentIndex; @@ -133,6 +134,7 @@ Route::get('/telegram', NotificationTelegram::class)->name('notifications.telegram'); Route::get('/discord', NotificationDiscord::class)->name('notifications.discord'); Route::get('/slack', NotificationSlack::class)->name('notifications.slack'); + Route::get('/pushover', NotificationPushover::class)->name('notifications.pushover'); }); Route::prefix('storages')->group(function () { From 9afe9299217b2c946d0ae55c0247a366f60aa7d5 Mon Sep 17 00:00:00 2001 From: Zao Soula Date: Wed, 11 Dec 2024 18:37:12 +0100 Subject: [PATCH 02/18] refactor: unify notification icon --- app/Notifications/Dto/PushoverMessage.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Notifications/Dto/PushoverMessage.php b/app/Notifications/Dto/PushoverMessage.php index 6022c2885..0efd1d526 100644 --- a/app/Notifications/Dto/PushoverMessage.php +++ b/app/Notifications/Dto/PushoverMessage.php @@ -17,8 +17,8 @@ public function getLevelIcon(): string { return match ($this->level) { 'info' => 'â„šī¸', - 'error' => '🚨', - 'success' => 'đŸŸĸ', + 'error' => '❌', + 'success' => '✅ ', 'warning' => 'âš ī¸', }; } From 9572c8498edb5831e44597d73b8aaf427f9e4624 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 18:42:55 +0100 Subject: [PATCH 03/18] chore: reorder navbar --- resources/views/components/notification/navbar.blade.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/views/components/notification/navbar.blade.php b/resources/views/components/notification/navbar.blade.php index 0193cf3cd..447a385c5 100644 --- a/resources/views/components/notification/navbar.blade.php +++ b/resources/views/components/notification/navbar.blade.php @@ -7,13 +7,13 @@ href="{{ route('notifications.email') }}"> - - - + + + From b48353c8a6ee644857f8b75cbd89f41a82614514 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 18:44:19 +0100 Subject: [PATCH 04/18] reorder more stuff --- app/Console/Commands/NotifyDemo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Console/Commands/NotifyDemo.php b/app/Console/Commands/NotifyDemo.php index b6e5015f8..990a03869 100644 --- a/app/Console/Commands/NotifyDemo.php +++ b/app/Console/Commands/NotifyDemo.php @@ -59,9 +59,9 @@ private function showHelp()
    Channels:
    • email
    • -
    • slack
    • discord
    • telegram
    • +
    • slack
    • pushover
    @@ -73,6 +73,6 @@ private function showHelp()
    In which manner you wish a coolified notification?
    - HTML, ['email', 'slack', 'discord', 'telegram', 'pushover']); + HTML, ['email', 'discord', 'telegram', 'slack', 'pushover']); } } From 1dade362534d0065ab3aff6aa50b39cbb0345e72 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:16:07 +0100 Subject: [PATCH 05/18] fix: slack helper --- resources/views/livewire/notifications/slack.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/notifications/slack.blade.php b/resources/views/livewire/notifications/slack.blade.php index 774f8e7e5..28bfe509f 100644 --- a/resources/views/livewire/notifications/slack.blade.php +++ b/resources/views/livewire/notifications/slack.blade.php @@ -24,7 +24,7 @@

    Notification Settings

    From 21ddaa317f247f38f5efda0b6caa1dca39a9e0cf Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:16:17 +0100 Subject: [PATCH 06/18] fix: telegram helper --- resources/views/livewire/notifications/telegram.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/notifications/telegram.blade.php b/resources/views/livewire/notifications/telegram.blade.php index 5dd859e9e..1e8bfcd92 100644 --- a/resources/views/livewire/notifications/telegram.blade.php +++ b/resources/views/livewire/notifications/telegram.blade.php @@ -26,8 +26,8 @@
    - +
    From 1568e55b050e47b2c75341412e13dd5499494d7f Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:16:28 +0100 Subject: [PATCH 07/18] fix: discord helper --- resources/views/livewire/notifications/discord.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/notifications/discord.blade.php b/resources/views/livewire/notifications/discord.blade.php index 1f83ed061..6caf31176 100644 --- a/resources/views/livewire/notifications/discord.blade.php +++ b/resources/views/livewire/notifications/discord.blade.php @@ -24,7 +24,7 @@

    Notification Settings

    From ebfc8a1094d5f114b5dc7af5262f682c925403a5 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:16:54 +0100 Subject: [PATCH 08/18] fix: telegram topic IDs --- app/Notifications/Channels/TelegramChannel.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/Notifications/Channels/TelegramChannel.php b/app/Notifications/Channels/TelegramChannel.php index 17d76181a..b5e7bf8b6 100644 --- a/app/Notifications/Channels/TelegramChannel.php +++ b/app/Notifications/Channels/TelegramChannel.php @@ -17,17 +17,24 @@ public function send($notifiable, $notification): void $chatId = $settings->telegram_chat_id; $topicId = match (get_class($notification)) { - \App\Notifications\Test::class => $settings->telegram_notifications_test_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\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\TaskSuccess::class => $settings->telegram_notifications_scheduled_task_success_topic_id, \App\Notifications\ScheduledTask\TaskFailed::class => $settings->telegram_notifications_scheduled_task_failure_topic_id, + + \App\Notifications\Server\DockerCleanupSuccess::class => $settings->telegram_notifications_docker_cleanup_success_topic_id, + \App\Notifications\Server\DockerCleanupFailed::class => $settings->telegram_notifications_docker_cleanup_failure_topic_id, + \App\Notifications\Server\HighDiskUsage::class => $settings->telegram_notifications_server_disk_usage_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, + default => null, }; From 92fec9582cfe21ae01df0cefe25960f14c876567 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:18:39 +0100 Subject: [PATCH 09/18] fix: make pushover settings more clear - Rename User to User Key - Rename Token to API Token - fix: helper and docs links --- app/Livewire/Notifications/Pushover.php | 23 +++++++++---------- app/Models/PushoverNotificationSettings.php | 10 ++++---- app/Models/Team.php | 12 +++++----- .../Channels/PushoverChannel.php | 18 +++++++-------- ...e_pushover_notification_settings_table.php | 5 ++-- .../livewire/notifications/pushover.blade.php | 10 ++++---- 6 files changed, 38 insertions(+), 40 deletions(-) diff --git a/app/Livewire/Notifications/Pushover.php b/app/Livewire/Notifications/Pushover.php index 7a3b294a2..2e8205f5e 100644 --- a/app/Livewire/Notifications/Pushover.php +++ b/app/Livewire/Notifications/Pushover.php @@ -18,10 +18,10 @@ class Pushover extends Component public bool $pushoverEnabled = false; #[Validate(['string', 'nullable'])] - public ?string $pushoverToken = null; - + public ?string $pushoverUserKey = null; + #[Validate(['string', 'nullable'])] - public ?string $pushoverUser = null; + public ?string $pushoverApiToken = null; #[Validate(['boolean'])] public bool $deploymentSuccessPushoverNotifications = false; @@ -59,7 +59,6 @@ class Pushover extends Component #[Validate(['boolean'])] public bool $serverUnreachablePushoverNotifications = true; - public function mount() { try { @@ -76,8 +75,8 @@ public function syncData(bool $toModel = false) if ($toModel) { $this->validate(); $this->settings->pushover_enabled = $this->pushoverEnabled; - $this->settings->pushover_user = $this->pushoverUser; - $this->settings->pushover_token = $this->pushoverToken; + $this->settings->pushover_user_key_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; @@ -96,8 +95,8 @@ public function syncData(bool $toModel = false) refreshSession(); } else { $this->pushoverEnabled = $this->settings->pushover_enabled; - $this->pushoverUser = $this->settings->pushover_user; - $this->pushoverToken = $this->settings->pushover_token; + $this->pushoverUserKey = $this->settings->pushover_user_key_key; + $this->pushoverApiToken = $this->settings->pushover_api_token; $this->deploymentSuccessPushoverNotifications = $this->settings->deployment_success_pushover_notifications; $this->deploymentFailurePushoverNotifications = $this->settings->deployment_failure_pushover_notifications; @@ -118,11 +117,11 @@ public function instantSavePushoverEnabled() { try { $this->validate([ - 'pushoverUser' => 'required', - 'pushoverToken' => 'required', + 'pushoverUserKey' => 'required', + 'pushoverApiToken' => 'required', ], [ - 'pushoverUser.required' => 'Pushover User is required.', - 'pushoverToken.required' => 'Pushover Token is required.', + 'pushoverUserKey.required' => 'Pushover User Key is required.', + 'pushoverApiToken.required' => 'Pushover API Token is required.', ]); $this->saveModel(); } catch (\Throwable $e) { diff --git a/app/Models/PushoverNotificationSettings.php b/app/Models/PushoverNotificationSettings.php index 7576a6040..7deeadedc 100644 --- a/app/Models/PushoverNotificationSettings.php +++ b/app/Models/PushoverNotificationSettings.php @@ -15,8 +15,8 @@ class PushoverNotificationSettings extends Model 'team_id', 'pushover_enabled', - 'pushover_user', - 'pushover_token', + 'pushover_user_key_key', + 'pushover_api_token', 'deployment_success_pushover_notifications', 'deployment_failure_pushover_notifications', @@ -29,12 +29,12 @@ class PushoverNotificationSettings extends Model 'server_disk_usage_pushover_notifications', 'server_reachable_pushover_notifications', 'server_unreachable_pushover_notifications', - ]; + ]; protected $casts = [ 'pushover_enabled' => 'boolean', - 'pushover_user' => 'encrypted', - 'pushover_token' => 'encrypted', + 'pushover_user_key_key' => 'encrypted', + 'pushover_api_token' => 'encrypted', 'deployment_success_pushover_notifications' => 'boolean', 'deployment_failure_pushover_notifications' => 'boolean', diff --git a/app/Models/Team.php b/app/Models/Team.php index fc10892a4..174137840 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -4,8 +4,8 @@ use App\Notifications\Channels\SendsDiscord; use App\Notifications\Channels\SendsEmail; -use App\Notifications\Channels\SendsSlack; use App\Notifications\Channels\SendsPushover; +use App\Notifications\Channels\SendsSlack; use App\Traits\HasNotificationSettings; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; @@ -33,7 +33,7 @@ ] )] -class Team extends Model implements SendsDiscord, SendsEmail, SendsSlack, SendsPushover +class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, SendsSlack { use HasNotificationSettings, Notifiable; @@ -156,12 +156,12 @@ public function routeNotificationForSlack() { return data_get($this, 'slack_webhook_url', null); } - + public function routeNotificationForPushover() { return [ - 'user' => data_get($this, 'pushover_user', null), - 'token' => data_get($this, 'pushover_token', null), + 'user' => data_get($this, 'pushover_user_key_key', null), + 'token' => data_get($this, 'pushover_api_token', null), ]; } @@ -287,7 +287,7 @@ public function slackNotificationSettings() { return $this->hasOne(SlackNotificationSettings::class); } - + public function pushoverNotificationSettings() { return $this->hasOne(PushoverNotificationSettings::class); diff --git a/app/Notifications/Channels/PushoverChannel.php b/app/Notifications/Channels/PushoverChannel.php index 56d3cb03d..3d3728d01 100644 --- a/app/Notifications/Channels/PushoverChannel.php +++ b/app/Notifications/Channels/PushoverChannel.php @@ -7,15 +7,15 @@ class PushoverChannel { - public function send(SendsPushover $notifiable, Notification $notification): void - { - $message = $notification->toPushover(); - $pushoverSettings = $notifiable->pushoverNotificationSettings; + public function send(SendsPushover $notifiable, Notification $notification): void + { + $message = $notification->toPushover(); + $pushoverSettings = $notifiable->pushoverNotificationSettings; - if (! $pushoverSettings || ! $pushoverSettings->isEnabled() || ! $pushoverSettings->pushover_user || ! $pushoverSettings->pushover_token) { - return; + if (! $pushoverSettings || ! $pushoverSettings->isEnabled() || ! $pushoverSettings->pushover_user_key || ! $pushoverSettings->pushover_api_token) { + return; + } + + SendMessageToPushoverJob::dispatch($message, $pushoverSettings->pushover_api_token, $pushoverSettings->pushover_user_key); } - - SendMessageToPushoverJob::dispatch($message, $pushoverSettings->pushover_token, $pushoverSettings->pushover_user); - } } diff --git a/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php b/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php index 907f7a052..8c317d997 100644 --- a/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php +++ b/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php @@ -16,8 +16,8 @@ public function up(): void $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('pushover_enabled')->default(false); - $table->text('pushover_user')->nullable(); - $table->text('pushover_token')->nullable(); + $table->text('pushover_user_key')->nullable(); + $table->text('pushover_api_token')->nullable(); $table->boolean('deployment_success_pushover_notifications')->default(false); $table->boolean('deployment_failure_pushover_notifications')->default(true); @@ -44,4 +44,3 @@ public function down(): void Schema::dropIfExists('pushover_notification_settings'); } }; - diff --git a/resources/views/livewire/notifications/pushover.blade.php b/resources/views/livewire/notifications/pushover.blade.php index 28a55516d..271af5367 100644 --- a/resources/views/livewire/notifications/pushover.blade.php +++ b/resources/views/livewire/notifications/pushover.blade.php @@ -23,12 +23,12 @@
    - + helper="Get your User Key in Pushover. You need to be logged in to Pushover to see your user key in the top right corner.
    Pushover Dashboard" required + id="pushoverUserKey" label="User Key" /> +

    Notification Settings

    From 866abfb1d41699e5860f7448b4270078f0f462c9 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:31:25 +0100 Subject: [PATCH 10/18] fix: typo in pushover user key --- app/Models/PushoverNotificationSettings.php | 4 ++-- app/Models/Team.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Models/PushoverNotificationSettings.php b/app/Models/PushoverNotificationSettings.php index 7deeadedc..e3191dcc3 100644 --- a/app/Models/PushoverNotificationSettings.php +++ b/app/Models/PushoverNotificationSettings.php @@ -15,7 +15,7 @@ class PushoverNotificationSettings extends Model 'team_id', 'pushover_enabled', - 'pushover_user_key_key', + 'pushover_user_key', 'pushover_api_token', 'deployment_success_pushover_notifications', @@ -33,7 +33,7 @@ class PushoverNotificationSettings extends Model protected $casts = [ 'pushover_enabled' => 'boolean', - 'pushover_user_key_key' => 'encrypted', + 'pushover_user_key' => 'encrypted', 'pushover_api_token' => 'encrypted', 'deployment_success_pushover_notifications' => 'boolean', diff --git a/app/Models/Team.php b/app/Models/Team.php index 174137840..e55cb0d19 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -160,7 +160,7 @@ public function routeNotificationForSlack() public function routeNotificationForPushover() { return [ - 'user' => data_get($this, 'pushover_user_key_key', null), + 'user' => data_get($this, 'pushover_user_key', null), 'token' => data_get($this, 'pushover_api_token', null), ]; } From 48ddc65435e1561e7ee442159dd46c9385524acb Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:34:44 +0100 Subject: [PATCH 11/18] fix: use Livewire refresh method and lock properties --- app/Livewire/Notifications/Email.php | 2 ++ app/Livewire/Notifications/Pushover.php | 17 +++++++++++++---- app/Livewire/Notifications/Slack.php | 9 +++++++++ app/Livewire/Notifications/Telegram.php | 10 +++++++++- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php index dc2a95e84..eac48cf77 100644 --- a/app/Livewire/Notifications/Email.php +++ b/app/Livewire/Notifications/Email.php @@ -14,8 +14,10 @@ class Email extends Component { protected $listeners = ['refresh' => '$refresh']; + #[Locked] public Team $team; + #[Locked] public EmailNotificationSettings $settings; #[Locked] diff --git a/app/Livewire/Notifications/Pushover.php b/app/Livewire/Notifications/Pushover.php index 2e8205f5e..f1e4c464d 100644 --- a/app/Livewire/Notifications/Pushover.php +++ b/app/Livewire/Notifications/Pushover.php @@ -5,22 +5,27 @@ 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(['string', 'nullable'])] + #[Validate(['nullable', 'string'])] public ?string $pushoverUserKey = null; - #[Validate(['string', 'nullable'])] + #[Validate(['nullable', 'string'])] public ?string $pushoverApiToken = null; #[Validate(['boolean'])] @@ -75,7 +80,7 @@ public function syncData(bool $toModel = false) if ($toModel) { $this->validate(); $this->settings->pushover_enabled = $this->pushoverEnabled; - $this->settings->pushover_user_key_key = $this->pushoverUserKey; + $this->settings->pushover_user_key = $this->pushoverUserKey; $this->settings->pushover_api_token = $this->pushoverApiToken; $this->settings->deployment_success_pushover_notifications = $this->deploymentSuccessPushoverNotifications; @@ -95,7 +100,7 @@ public function syncData(bool $toModel = false) refreshSession(); } else { $this->pushoverEnabled = $this->settings->pushover_enabled; - $this->pushoverUserKey = $this->settings->pushover_user_key_key; + $this->pushoverUserKey = $this->settings->pushover_user_key; $this->pushoverApiToken = $this->settings->pushover_api_token; $this->deploymentSuccessPushoverNotifications = $this->settings->deployment_success_pushover_notifications; @@ -128,6 +133,8 @@ public function instantSavePushoverEnabled() $this->pushoverEnabled = false; return handleError($e, $this); + } finally { + $this->dispatch('refresh'); } } @@ -137,6 +144,8 @@ public function instantSave() $this->syncData(true); } catch (\Throwable $e) { return handleError($e, $this); + } finally { + $this->dispatch('refresh'); } } diff --git a/app/Livewire/Notifications/Slack.php b/app/Livewire/Notifications/Slack.php index 97464fa1c..f47ad8a97 100644 --- a/app/Livewire/Notifications/Slack.php +++ b/app/Livewire/Notifications/Slack.php @@ -5,13 +5,18 @@ 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 @@ public function instantSaveSlackEnabled() $this->slackEnabled = false; return handleError($e, $this); + } finally { + $this->dispatch('refresh'); } } @@ -130,6 +137,8 @@ public function instantSave() $this->syncData(true); } catch (\Throwable $e) { return handleError($e, $this); + } finally { + $this->dispatch('refresh'); } } diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php index de2fa9cdc..85c16b277 100644 --- a/app/Livewire/Notifications/Telegram.php +++ b/app/Livewire/Notifications/Telegram.php @@ -5,13 +5,18 @@ 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'])] @@ -141,7 +146,6 @@ public function syncData(bool $toModel = false) $this->settings->telegram_notifications_server_unreachable_topic_id = $this->telegramNotificationsServerUnreachableTopicId; $this->settings->save(); - refreshSession(); } else { $this->telegramEnabled = $this->settings->telegram_enabled; $this->telegramToken = $this->settings->telegram_token; @@ -181,6 +185,8 @@ public function instantSave() $this->syncData(true); } catch (\Throwable $e) { return handleError($e, $this); + } finally { + $this->dispatch('refresh'); } } @@ -210,6 +216,8 @@ public function instantSaveTelegramEnabled() $this->telegramEnabled = false; return handleError($e, $this); + } finally { + $this->dispatch('refresh'); } } From a7330fe52b90bcc29475f1f8099a28ca805c062c Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:43:58 +0100 Subject: [PATCH 12/18] fix: create pushover settings for existing teams --- ...014_create_slack_notification_settings_table.php | 3 ++- ..._create_pushover_notification_settings_table.php | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php b/database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php index 790e0f667..8aee40d87 100644 --- a/database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php +++ b/database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php @@ -3,6 +3,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Schema; return new class extends Migration @@ -42,7 +43,7 @@ public function up(): void 'team_id' => $team->id, ]); } catch (\Throwable $e) { - \Log::error('Error migrating slack notification settings from teams table: '.$e->getMessage()); + Log::error('Error creating slack notification settings for existing teams: '.$e->getMessage()); } } } diff --git a/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php b/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php index 8c317d997..ad4215a07 100644 --- a/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php +++ b/database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php @@ -2,6 +2,8 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Schema; return new class extends Migration @@ -34,6 +36,17 @@ public function up(): void $table->unique(['team_id']); }); + $teams = DB::table('teams')->get(); + + foreach ($teams as $team) { + try { + DB::table('pushover_notification_settings')->insert([ + 'team_id' => $team->id, + ]); + } catch (\Throwable $e) { + Log::error('Error creating pushover notification settings for existing teams: '.$e->getMessage()); + } + } } /** From d2ff8c652170aeff36e9bda055503ffffb6c3ed9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 11 Dec 2024 21:31:12 +0100 Subject: [PATCH 13/18] feat: add seeder command and configuration for database seeding --- app/Console/Commands/Seeder.php | 24 +++++++++++++++++++ config/constants.php | 4 ++++ .../etc/s6-overlay/s6-rc.d/init-seeder/up | 5 +--- 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 app/Console/Commands/Seeder.php diff --git a/app/Console/Commands/Seeder.php b/app/Console/Commands/Seeder.php new file mode 100644 index 000000000..e37b6a9d2 --- /dev/null +++ b/app/Console/Commands/Seeder.php @@ -0,0 +1,24 @@ +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); + } + } +} diff --git a/config/constants.php b/config/constants.php index 3054df1f0..a02d6616a 100644 --- a/config/constants.php +++ b/config/constants.php @@ -37,6 +37,10 @@ 'is_migration_enabled' => env('MIGRATION_ENABLED', true), ], + 'seeder' => [ + 'is_seeder_enabled' => env('SEEDER_ENABLED', true), + ], + 'horizon' => [ 'is_horizon_enabled' => env('HORIZON_ENABLED', true), 'is_scheduler_enabled' => env('SCHEDULER_ENABLED', true), diff --git a/docker/production/etc/s6-overlay/s6-rc.d/init-seeder/up b/docker/production/etc/s6-overlay/s6-rc.d/init-seeder/up index 20d17c58b..007f4233e 100644 --- a/docker/production/etc/s6-overlay/s6-rc.d/init-seeder/up +++ b/docker/production/etc/s6-overlay/s6-rc.d/init-seeder/up @@ -6,10 +6,7 @@ cd /var/www/html foreground { php artisan - db:seed - --class - ProductionSeeder - --force + start:seeder } From 09746aa87774be069ce5fbda258f7f6181e4cd1d Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 11 Dec 2024 21:38:31 +0100 Subject: [PATCH 14/18] fix: update token permission check from 'write' to 'root' --- .../migrations/2024_10_30_074601_rename_token_permissions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2024_10_30_074601_rename_token_permissions.php b/database/migrations/2024_10_30_074601_rename_token_permissions.php index 2ca98d090..69d774d7f 100644 --- a/database/migrations/2024_10_30_074601_rename_token_permissions.php +++ b/database/migrations/2024_10_30_074601_rename_token_permissions.php @@ -40,7 +40,7 @@ public function down(): void $tokens = PersonalAccessToken::all(); foreach ($tokens as $token) { $abilities = collect(); - if (in_array('write', $token->abilities)) { + if (in_array('root', $token->abilities)) { $abilities->push('*'); } else { if (in_array('read', $token->abilities)) { From f88438edd3b531f3ff21b12695a7b296de4f7a2f Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 11 Dec 2024 23:13:13 +0100 Subject: [PATCH 15/18] chore: rename topicID to threadId like in the telegram API response --- app/Jobs/SendMessageToTelegramJob.php | 6 +- app/Livewire/Notifications/Telegram.php | 72 +++++++++---------- app/Models/TelegramNotificationSettings.php | 44 ++++++------ .../Channels/TelegramChannel.php | 28 ++++---- ...e_telegram_notification_settings_table.php | 24 +++---- ...notification_settings_from_teams_table.php | 27 +++---- .../livewire/notifications/telegram.blade.php | 48 ++++++------- 7 files changed, 125 insertions(+), 124 deletions(-) diff --git a/app/Jobs/SendMessageToTelegramJob.php b/app/Jobs/SendMessageToTelegramJob.php index 85f4fc934..6b0a64ae3 100644 --- a/app/Jobs/SendMessageToTelegramJob.php +++ b/app/Jobs/SendMessageToTelegramJob.php @@ -32,7 +32,7 @@ public function __construct( public array $buttons, public string $token, public string $chatId, - public ?string $topicId = null, + public ?string $threadId = null, ) { $this->onQueue('high'); } @@ -67,8 +67,8 @@ public function handle(): void '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()) { diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php index 85c16b277..01afb4ac6 100644 --- a/app/Livewire/Notifications/Telegram.php +++ b/app/Livewire/Notifications/Telegram.php @@ -65,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() { @@ -132,18 +132,18 @@ public function syncData(bool $toModel = false) $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(); } else { @@ -164,18 +164,18 @@ public function syncData(bool $toModel = false) $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; } } diff --git a/app/Models/TelegramNotificationSettings.php b/app/Models/TelegramNotificationSettings.php index 2edca14ff..78bd841bd 100644 --- a/app/Models/TelegramNotificationSettings.php +++ b/app/Models/TelegramNotificationSettings.php @@ -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() diff --git a/app/Notifications/Channels/TelegramChannel.php b/app/Notifications/Channels/TelegramChannel.php index b5e7bf8b6..ea4ab7171 100644 --- a/app/Notifications/Channels/TelegramChannel.php +++ b/app/Notifications/Channels/TelegramChannel.php @@ -16,24 +16,24 @@ public function send($notifiable, $notification): void $telegramToken = $settings->telegram_token; $chatId = $settings->telegram_chat_id; - $topicId = match (get_class($notification)) { - \App\Notifications\Application\DeploymentSuccess::class => $settings->telegram_notifications_deployment_success_topic_id, - \App\Notifications\Application\DeploymentFailed::class => $settings->telegram_notifications_deployment_failure_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\Container\ContainerStopped::class => $settings->telegram_notifications_status_change_thread_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\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_topic_id, - \App\Notifications\ScheduledTask\TaskFailed::class => $settings->telegram_notifications_scheduled_task_failure_topic_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_topic_id, - \App\Notifications\Server\DockerCleanupFailed::class => $settings->telegram_notifications_docker_cleanup_failure_topic_id, - \App\Notifications\Server\HighDiskUsage::class => $settings->telegram_notifications_server_disk_usage_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\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, }; @@ -42,6 +42,6 @@ public function send($notifiable, $notification): void return; } - SendMessageToTelegramJob::dispatch($message, $buttons, $telegramToken, $chatId, $topicId); + SendMessageToTelegramJob::dispatch($message, $buttons, $telegramToken, $chatId, $threadId); } } diff --git a/database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php b/database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php index 190d148fc..db4d998e3 100644 --- a/database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php +++ b/database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php @@ -32,18 +32,18 @@ public function up(): void $table->boolean('server_reachable_telegram_notifications')->default(false); $table->boolean('server_unreachable_telegram_notifications')->default(true); - $table->text('telegram_notifications_deployment_success_topic_id')->nullable(); - $table->text('telegram_notifications_deployment_failure_topic_id')->nullable(); - $table->text('telegram_notifications_status_change_topic_id')->nullable(); - $table->text('telegram_notifications_backup_success_topic_id')->nullable(); - $table->text('telegram_notifications_backup_failure_topic_id')->nullable(); - $table->text('telegram_notifications_scheduled_task_success_topic_id')->nullable(); - $table->text('telegram_notifications_scheduled_task_failure_topic_id')->nullable(); - $table->text('telegram_notifications_docker_cleanup_success_topic_id')->nullable(); - $table->text('telegram_notifications_docker_cleanup_failure_topic_id')->nullable(); - $table->text('telegram_notifications_server_disk_usage_topic_id')->nullable(); - $table->text('telegram_notifications_server_reachable_topic_id')->nullable(); - $table->text('telegram_notifications_server_unreachable_topic_id')->nullable(); + $table->text('telegram_notifications_deployment_success_thread_id')->nullable(); + $table->text('telegram_notifications_deployment_failure_thread_id')->nullable(); + $table->text('telegram_notifications_status_change_thread_id')->nullable(); + $table->text('telegram_notifications_backup_success_thread_id')->nullable(); + $table->text('telegram_notifications_backup_failure_thread_id')->nullable(); + $table->text('telegram_notifications_scheduled_task_success_thread_id')->nullable(); + $table->text('telegram_notifications_scheduled_task_failure_thread_id')->nullable(); + $table->text('telegram_notifications_docker_cleanup_success_thread_id')->nullable(); + $table->text('telegram_notifications_docker_cleanup_failure_thread_id')->nullable(); + $table->text('telegram_notifications_server_disk_usage_thread_id')->nullable(); + $table->text('telegram_notifications_server_reachable_thread_id')->nullable(); + $table->text('telegram_notifications_server_unreachable_thread_id')->nullable(); $table->unique(['team_id']); }); diff --git a/database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php b/database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php index 0c10646b9..df120e273 100644 --- a/database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php +++ b/database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php @@ -4,6 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Schema; return new class extends Migration @@ -30,17 +31,17 @@ public function up(): void 'status_change_telegram_notifications' => $team->telegram_notifications_status_changes ?? false, 'server_disk_usage_telegram_notifications' => $team->telegram_notifications_server_disk_usage ?? true, - 'telegram_notifications_deployment_success_topic_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null, - 'telegram_notifications_deployment_failure_topic_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null, - 'telegram_notifications_backup_success_topic_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null, - 'telegram_notifications_backup_failure_topic_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null, - 'telegram_notifications_scheduled_task_success_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null, - 'telegram_notifications_scheduled_task_failure_topic_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null, - 'telegram_notifications_status_change_topic_id' => $team->telegram_notifications_status_changes_message_thread_id ? Crypt::encryptString($team->telegram_notifications_status_changes_message_thread_id) : null, + 'telegram_notifications_deployment_success_thread_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null, + 'telegram_notifications_deployment_failure_thread_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null, + 'telegram_notifications_backup_success_thread_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null, + 'telegram_notifications_backup_failure_thread_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null, + 'telegram_notifications_scheduled_task_success_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null, + 'telegram_notifications_scheduled_task_failure_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null, + 'telegram_notifications_status_change_thread_id' => $team->telegram_notifications_status_changes_message_thread_id ? Crypt::encryptString($team->telegram_notifications_status_changes_message_thread_id) : null, ] ); } catch (Exception $e) { - \Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage()); + Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage()); } } @@ -101,13 +102,13 @@ public function down(): void 'telegram_notifications_scheduled_tasks' => $setting->scheduled_task_success_telegram_notifications || $setting->scheduled_task_failure_telegram_notifications, 'telegram_notifications_server_disk_usage' => $setting->server_disk_usage_telegram_notifications, - 'telegram_notifications_deployments_message_thread_id' => $setting->telegram_notifications_deployment_success_topic_id ? Crypt::decryptString($setting->telegram_notifications_deployment_success_topic_id) : null, - 'telegram_notifications_status_changes_message_thread_id' => $setting->telegram_notifications_status_change_topic_id ? Crypt::decryptString($setting->telegram_notifications_status_change_topic_id) : null, - 'telegram_notifications_database_backups_message_thread_id' => $setting->telegram_notifications_backup_success_topic_id ? Crypt::decryptString($setting->telegram_notifications_backup_success_topic_id) : null, - 'telegram_notifications_scheduled_tasks_thread_id' => $setting->telegram_notifications_scheduled_task_success_topic_id ? Crypt::decryptString($setting->telegram_notifications_scheduled_task_success_topic_id) : null, + 'telegram_notifications_deployments_message_thread_id' => $setting->telegram_notifications_deployment_success_thread_id ? Crypt::decryptString($setting->telegram_notifications_deployment_success_thread_id) : null, + 'telegram_notifications_status_changes_message_thread_id' => $setting->telegram_notifications_status_change_thread_id ? Crypt::decryptString($setting->telegram_notifications_status_change_thread_id) : null, + 'telegram_notifications_database_backups_message_thread_id' => $setting->telegram_notifications_backup_success_thread_id ? Crypt::decryptString($setting->telegram_notifications_backup_success_thread_id) : null, + 'telegram_notifications_scheduled_tasks_thread_id' => $setting->telegram_notifications_scheduled_task_success_thread_id ? Crypt::decryptString($setting->telegram_notifications_scheduled_task_success_thread_id) : null, ]); } catch (Exception $e) { - \Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage()); + Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage()); } } } diff --git a/resources/views/livewire/notifications/telegram.blade.php b/resources/views/livewire/notifications/telegram.blade.php index 1e8bfcd92..ecc9360fa 100644 --- a/resources/views/livewire/notifications/telegram.blade.php +++ b/resources/views/livewire/notifications/telegram.blade.php @@ -44,16 +44,16 @@ - +

    - +
    @@ -61,8 +61,8 @@ label="Container Status Changes" helper="Send a notification when a container status changes. It will send a notification for Stopped and Restarted events of a container." />
    - +
    @@ -74,8 +74,8 @@ - +
    @@ -83,8 +83,8 @@
    - + @@ -97,8 +97,8 @@ - +
    @@ -106,8 +106,8 @@
    - + @@ -120,8 +120,8 @@ - +
    @@ -129,8 +129,8 @@
    - +
    @@ -138,8 +138,8 @@
    - +
    @@ -147,8 +147,8 @@
    - + @@ -157,8 +157,8 @@ - + From e5f534b6ef655aebf92891d129e5f7917307e2ec Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 12 Dec 2024 08:40:34 +0100 Subject: [PATCH 16/18] fix: pushover --- .../livewire/notifications/pushover.blade.php | 140 +++++++++--------- routes/web.php | 2 +- 2 files changed, 72 insertions(+), 70 deletions(-) diff --git a/resources/views/livewire/notifications/pushover.blade.php b/resources/views/livewire/notifications/pushover.blade.php index 271af5367..c8dd777d8 100644 --- a/resources/views/livewire/notifications/pushover.blade.php +++ b/resources/views/livewire/notifications/pushover.blade.php @@ -1,84 +1,86 @@
    Notifications | Coolify - - -
    -
    -

    Pushover

    - - Save - - @if ($pushoverEnabled) + + + +
    +

    Pushover

    + + Save + + @if ($pushoverEnabled) Send Test Notification - @else + @else Send Test Notification - @endif -
    -
    - -
    + @endif +
    +
    + +
    +
    + helper="Get your User Key in Pushover. You need to be logged in to Pushover to see your user key in the top right corner.
    Pushover Dashboard" + required id="pushoverUserKey" label="User Key" /> - -

    Notification Settings

    -

    - Select events for which you would like to receive Pushover notifications. -

    -
    -
    -

    Deployments

    -
    - - - -
    -
    -
    -

    Backups

    -
    - - -
    -
    -
    -

    Scheduled Tasks

    -
    - - -
    -
    -
    -

    Server

    -
    - - - - - -
    + helper="Generate an API Token/Key in Pushover by creating a new application.
    Create Pushover Application" + required id="pushoverApiToken" label="API Token" /> +
    + +

    Notification Settings

    +

    + Select events for which you would like to receive Pushover notifications. +

    +
    +
    +

    Deployments

    +
    + + +
    +
    +

    Backups

    +
    + + +
    +
    +
    +

    Scheduled Tasks

    +
    + + +
    +
    +
    +

    Server

    +
    + + + + + +
    +
    +
    diff --git a/routes/web.php b/routes/web.php index 38ce7f15c..3d12b9b46 100644 --- a/routes/web.php +++ b/routes/web.php @@ -12,9 +12,9 @@ use App\Livewire\ForcePasswordReset; use App\Livewire\Notifications\Discord as NotificationDiscord; use App\Livewire\Notifications\Email as NotificationEmail; +use App\Livewire\Notifications\Pushover as NotificationPushover; use App\Livewire\Notifications\Slack as NotificationSlack; use App\Livewire\Notifications\Telegram as NotificationTelegram; -use App\Livewire\Notifications\Pushover as NotificationPushover; use App\Livewire\Profile\Index as ProfileIndex; use App\Livewire\Project\Application\Configuration as ApplicationConfiguration; use App\Livewire\Project\Application\Deployment\Index as DeploymentIndex; From f0812b754ceb5cefcdd1da240fa78f3c9a7adf02 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 12 Dec 2024 08:40:38 +0100 Subject: [PATCH 17/18] add new sponsors --- README.md | 7 ++++++- other/logos/internetgarden.ico | Bin 0 -> 15406 bytes 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 other/logos/internetgarden.ico diff --git a/README.md b/README.md index dac48d127..4d93a07cf 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,9 @@ ### Special Sponsors * [SupaGuide](https://supa.guide/?ref=coolify.io) - A comprehensive resource hub offering guides and tutorials for web development using Supabase. * [GoldenVM](https://billing.goldenvm.com/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes. * [Tigris](https://tigrisdata.com/?ref=coolify.io) - A fully managed serverless object storage service compatible with Amazon S3 API. Offers high performance, scalability, and built-in search capabilities for efficient data management. -* [Advin](https://coolify.ad.vin/?ref=coolify.io) - A digital advertising agency specializing in programmatic advertising and data-driven marketing strategies. +* [Cloudify.ro](https://cloudify.ro/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes. +* [Syntaxfm](https://syntax.fm/?ref=coolify.io) - Podcast for web developers. +* [PFGlabs](https://pfglabs.com/?ref=coolify.io) - Build real project with Golang. * [Treive](https://trieve.ai/?ref=coolify.io) - An AI-powered search and discovery platform for enhancing information retrieval in large datasets. * [Blacksmith](https://blacksmith.sh/?ref=coolify.io) - A cloud-native platform for automating infrastructure provisioning and management across multiple cloud providers. * [Brand Dev](https://brand.dev/?ref=coolify.io) - A web development agency specializing in creating custom digital experiences and brand identities. @@ -92,6 +94,9 @@ ## Github Sponsors ($40+) Michael Mazurczak Formbricks StartupFame +jyc.dev +BitLaunch +Internet Garden Jonas Jaeger JP Evercam diff --git a/other/logos/internetgarden.ico b/other/logos/internetgarden.ico new file mode 100644 index 0000000000000000000000000000000000000000..e555984be39b8a20ff9b2a3b8b13a87261cfa976 GIT binary patch literal 15406 zcmeHOd2k!m8CM`2EtGIm257^Sp=oEhI@1;kv?)g2ZRvfm3&Am%a-Is!&RUSLpTb<8HO{K;!9V^z)Q?RFo=`J8{TOTyC>ssgUdtuo&vxh8Rb{&fVoAV_=<@;@_^!})}3 z?0#XWfUi(ajFViK=*e*STvIu}us6r+6JB#j!V`9hUxTuD)pEO^Pl4_VR)#&mU#;>& z|1M4v?wlNTk9SC}yD8KKR~!X?0bw93M@Uw8xPDJEM(R7jN&G9&b=wV+`^Qus-5?+B z@@@P(h3JNzM^oAKp!+zx-!&f?-hiBMIH}d&G=G<@Y_4l;_vP(q_?I;H<@j@L(3+m2rPt;~Q9eB4O>J|| z*)5W83Jd4OgCS3{LrZIvZ*Jax#DW>Sj;XKd-AaMd+nePhjOfQwPV3A>gvkiBJ{^i5 z=4Kb>SMX5C)|1JJ?j!9!*DcT)fbO?2SNC#0ejnDt9atN-RQVgPFEtMIx^a%Em#YM*Q$fUMOI{5p_vtRAC3Ax1--+ib*s3r-ui^bv9`t3)~3_Z&aYY5 ztLo3j=oe94cdgWwrJ?m3>+#MKx=XeRWV~7<-E%T4yHwgC@fToR^_u8Dfc=Pv?5~u4 z$%C z0h-%{jislwR=@haD!~5%d;T^ZS?CM?1)5VTEya{a`KucG1kF1=y(+Jfe)YS<@4T3> zqhIp&kFr(>8*MU{<&odW{HAfT2ee%d$vJz9&-oMeyEazr2~TqBL+$MY4yV>6xX zx3D+8QcoUR#{VrYFPs}U)vwTdlk-^FR?=ZH`2wp;n=Y_pb;n?C9LNz*dW998EDicz z(&}XM83?9p_AHWbd(`7w_I$?bFiXpB`7oS&K4o>PY5&IT8Ad$^G~67MySM1A zL&`bPZ>GoW8^+DOs!lehv!AM4jh|noKL$eH^bKY@%)Zf?6nZnPZc6_H=SNkq8n1k? zcnpNZ3H@mmLo3ehs!le( zYkEu$GV1`Hxp8JZvXp!)-!Tp!QT4BSWI$IxVcEDMKL*hD4lA;)(9qr=@}_nYhDY!2 zdy%a-n_j-C{}ZCYIXN=cvxgQJY@R=&9X?r7+dlz1KVuDTH7pyL**xdXv3c);QSTNDsRFzf0NRNgx{ABIJa;?*D0Le^(UMuZc@&K62Av^ z*n>0F3cKX`tHUq+mW#TN{k}j}an$1M3ZKLxoOj;F8HmpJg9vGaVYEM;Su+R&I0Ju; z_$AQI;^eXIU#jl0#M1)82~{1=*}(M`a25LROXvSvB{{Fuo_WWD$0{$~SI}7;?dTn8 z+tFgr(!(EO4+zVu+l7f%b&r*9GVU3a{`U)?mC@#U^@Puee*^x@OMxwS_8%)wJ^tyz zy5rDZJjM%+XFV+Cm-+ZFIG<}u?e^wF;i@yG!7I9Qff+v^4+sVXbSP zW8!nv;#Tx1K3fZ8CcC%7H!TDmZG|?D9)3j^d~fKZ8^A;NJSFRaHbj334_m!&puGhB z=C{y3)HYpJKIilqp`}IsQA7MA4MumtRX*V!vhOVDqWSPhseYjEH0B`BY@Im>+iZKa zB;0sokLx7bi}m`j6n^5Ny>M!)6TW@;kbOdl`7I>j_r9yPxmI_7aMQjj35~$6v%X_Z z@$>y?@BhHQoPoQ7AL(Ic%dFsM>1VVpI2CjJKGfp_=t+*)eFgg=`XEm00Lw>dYD2s` zz&(q0UnT#(^Q|hsu)NCey57upua!Ak{3`!c+$Uk(n~6GX1fHGf8|`}aiNoLc8hW8gaxpbDmIl&QZ`~~$l>OgyE&SpXWW$bUty9f?`B=pG~jQdT%+yuJI>MY_V zUj&`qyTrt0z_uPCPJRm0;7#?yf4?TOC3A5^lqXpAXK;}v6S#nL3h*r^tW{FemAU$s zk)XSjus2f!tO2xb&JV?6@7@AGBi^L2WojC}m;~Oac*1z&5RFF1mjR({7P_Yb=2qw* zQt{};&aq#SNaarMuv}G>CUETi-FcggwdItmFT~WCK|1jpo){wa8kkldMO-zE` zw+(a`VWf9h_usKwHoXJTj3>+qjHg6bFes13?kwsGnyYA=6~KPbD*leA6EfXnxo(Zi z(kA^o1Or(a=(>aMDT;uUSwL-%`?@a-^cA%|(LIN|rv1d=q;gv9^JO5cZka{ zcNIT0-qX=NT=rd}{$8LbJJOQ6x(G;_1z77>>FF>kqx<^@>v!kwGZruCE4V{3;wvck zrmrg#ZV?;g@&&R@#tqSRJe`!;yC`}SNq2+RWu*5;+xLvn>5hx`_=-^>8d-RD2h<4sT=iX!Xi)x7ZPFm+3in zMSc;ne**A(^mOT!(Rg9opVCX5=I<$Ta=hvNbUzHcv|{T&*|?#Wp$6#Ko6}=32WXtr z8(uAb+6OGIK{42LS5&0o86mI{FNE#$WhwmZJ7R4eJZmiMV`B1UItMYTE0T;x=e_w^yEW2wvdQ1 z*^+LexBO)Tv&@LK6mM^UzmIJ{S~vC9eHK5Zb!{PU>bV#r1Yw>FHG{5PM9Lo#)cCJ-F${3;N*rU%6OvITcrs8N`JorAa?$_eg=JBp#Kh86X z-$FSr;;iDX;8`mN&_V+H*=&Ra>almjvi{5Kr^S1KcUX&=$q&>2OIp_rEuwm3pM{;4 zF7O3fP+Kt)dOw6cjs82;NplZ4uR(}2c(r>0eY-}2uLm~HH?T8rr+u+vfXWaQZ67#3 z)R8$$Wkvfo&adgs6xV^udYvj=k2iJxca2@e!p60=+mFCH$ Date: Thu, 12 Dec 2024 08:41:28 +0100 Subject: [PATCH 18/18] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d93a07cf..56edffd31 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,8 @@ # Donations ### Special Sponsors -![image](https://github.com/user-attachments/assets/726fb63e-c3b8-4260-b3ac-06780605ec5d) +![image](https://github.com/user-attachments/assets/6022bc9c-8435-4d14-9497-8be230ed8cb1) + * [CCCareers](https://cccareers.org/) - A career development platform connecting coding bootcamp graduates with job opportunities in the tech industry. * [Hetzner](http://htznr.li/CoolifyXHetzner) - A German web hosting company offering affordable dedicated servers, cloud services, and web hosting solutions.