From e0249ed5fbf9298745e8755a7b724547b718058e Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 02:58:53 +0200 Subject: [PATCH 01/10] require justinkluever/discord-webhook-builder --- composer.json | 1 + composer.lock | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e0442783..64521b31 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,7 @@ "blade-ui-kit/blade-icons": "^1.9", "filament/filament": "^5.4", "flowframe/laravel-trend": "^0.5.0", + "justinkluever/discord-webhook-builder": "^0.1.0", "kirschbaum-development/commentions": "^0.7", "lara-zeus/spatie-translatable": "^2.0", "laravel/framework": "^13.3", diff --git a/composer.lock b/composer.lock index 49e83213..64d0bf8f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "209e86fabd21118bea34e29d0d1f24a8", + "content-hash": "1e8318672cb225a3760a0330d1320441", "packages": [ { "name": "blade-ui-kit/blade-heroicons", @@ -2159,6 +2159,70 @@ }, "time": "2025-03-19T14:43:43+00:00" }, + { + "name": "justinkluever/discord-webhook-builder", + "version": "v0.1.0", + "source": { + "type": "git", + "url": "https://github.com/justinkluever/discord-webhook-builder.git", + "reference": "e19ede6eaa3904db7c854843a0bdb7d9a1d696ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/justinkluever/discord-webhook-builder/zipball/e19ede6eaa3904db7c854843a0bdb7d9a1d696ac", + "reference": "e19ede6eaa3904db7c854843a0bdb7d9a1d696ac", + "shasum": "" + }, + "require": { + "php": "^8.3" + }, + "require-dev": { + "laravel/pint": "^v1.29.1", + "pestphp/pest": "^4.7.3", + "pestphp/pest-plugin-arch": "^4.0.2", + "pestphp/pest-plugin-type-coverage": "^4.0.4", + "phpstan/phpstan": "^2.2.2", + "rector/rector": "^2.4.5", + "symfony/var-dumper": "^7.0.0|^8.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "JustinKluever\\DiscordWebhookBuilder\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Klüver", + "email": "justin@kluever.info" + } + ], + "description": "a simple and fluent builder for discord webhook messages with embeds or components v2", + "homepage": "https://github.com/justinkluever/discord-webhook-builder", + "keywords": [ + "builder", + "component", + "components-v2", + "discord", + "discord-webhook", + "dto", + "embed", + "fluent", + "notification", + "payload", + "php", + "webhook" + ], + "support": { + "issues": "https://github.com/justinkluever/discord-webhook-builder/issues", + "source": "https://github.com/justinkluever/discord-webhook-builder" + }, + "time": "2026-06-13T11:22:39+00:00" + }, { "name": "kirschbaum-development/commentions", "version": "0.7.10", From 9249fa6215d9209abae0e6c1e635fc6ab9a1b607 Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 04:40:34 +0200 Subject: [PATCH 02/10] remove spatie/laravel-discord-alerts --- composer.json | 1 - composer.lock | 86 +-------------------------------------------------- 2 files changed, 1 insertion(+), 86 deletions(-) diff --git a/composer.json b/composer.json index 64521b31..907b768c 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,6 @@ "sentry/sentry-laravel": "^4.24", "socialiteproviders/twitch": "^5.4", "spatie/laravel-backup": "^10.2", - "spatie/laravel-discord-alerts": "^1.9", "spatie/laravel-translatable": "^6.13", "tales-from-a-dev/tailwind-merge-php": "^0.3.0", "ublabs/blade-simple-icons": "^0.203.0", diff --git a/composer.lock b/composer.lock index 64d0bf8f..dc224c0f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1e8318672cb225a3760a0330d1320441", + "content-hash": "bd97665457e0998da47805787c2d0a10", "packages": [ { "name": "blade-ui-kit/blade-heroicons", @@ -6843,90 +6843,6 @@ ], "time": "2026-06-01T22:44:58+00:00" }, - { - "name": "spatie/laravel-discord-alerts", - "version": "1.9.1", - "source": { - "type": "git", - "url": "https://github.com/spatie/laravel-discord-alerts.git", - "reference": "f199b6e03dcbcdb06f2a0b0978e37df2c2c397e7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-discord-alerts/zipball/f199b6e03dcbcdb06f2a0b0978e37df2c2c397e7", - "reference": "f199b6e03dcbcdb06f2a0b0978e37df2c2c397e7", - "shasum": "" - }, - "require": { - "illuminate/contracts": "^12.0|^13.0", - "php": "^8.3", - "spatie/laravel-package-tools": "^1.93.0" - }, - "require-dev": { - "larastan/larastan": "^3.0", - "nunomaduro/collision": "^8.0|^9.0", - "orchestra/testbench": "^10.0|^11.0", - "pestphp/pest": "^4.0", - "phpstan/extension-installer": "^1.3.1", - "spatie/laravel-ray": "^1.26" - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Discord": "DiscordAlert" - }, - "providers": [ - "Spatie\\DiscordAlerts\\DiscordAlertsServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Spatie\\DiscordAlerts\\": "src", - "Spatie\\DiscordAlerts\\Database\\Factories\\": "database/factories" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Rias Van der Veken", - "email": "rias@spatie.be", - "role": "Developer" - }, - { - "name": "Niels Vanpachtenbeke", - "email": "niels@spatie.be", - "role": "Developer" - }, - { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "role": "Developer" - } - ], - "description": "Send a message to Discord", - "homepage": "https://github.com/spatie/laravel-discord-alerts", - "keywords": [ - "laravel", - "laravel-discord-alerts", - "spatie" - ], - "support": { - "issues": "https://github.com/spatie/laravel-discord-alerts/issues", - "source": "https://github.com/spatie/laravel-discord-alerts/tree/1.9.1" - }, - "funding": [ - { - "url": "https://github.com/spatie", - "type": "github" - } - ], - "time": "2026-03-17T20:51:12+00:00" - }, { "name": "spatie/laravel-package-tools", "version": "1.93.1", From 3c733cd211b50031847d1ac335f0f8118a7dc940 Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 04:42:55 +0200 Subject: [PATCH 03/10] move discord alerts config to services config --- config/discord-alerts.php | 43 --------------------------------------- config/services.php | 7 +++++++ 2 files changed, 7 insertions(+), 43 deletions(-) delete mode 100644 config/discord-alerts.php diff --git a/config/discord-alerts.php b/config/discord-alerts.php deleted file mode 100644 index 9668fb94..00000000 --- a/config/discord-alerts.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'default' => env('DISCORD_ALERT_WEBHOOK'), - 'issues' => env('VHEART_IT_ISSUES_WEBHOOK'), - 'moderation' => env('VHEART_DISCORD_MODERATION_WEBHOOK'), - ], - - /* - * Default avatar is an empty string '' which means it will not be included in the payload. - * You can add multiple custom avatars and then specify directly with withAvatar() - */ - 'avatar_urls' => [ - 'default' => '', - ], - - /* - * This job will send the message to Discord. You can extend this - * job to set timeouts, retries, etc... - */ - 'job' => DiscordWebhookJob::class, - - /* - * The queue connection that should be used to send the alert. - * - * If not specified, we'll use the default queue connection. - */ - 'queue_connection' => env('DISCORD_ALERT_QUEUE_CONNECTION'), - - /* - * The queue name that should be used to send the alert. Only supported for drivers - * that allow multiple queues (e.g., redis, database, beanstalkd). Ignored for sync and null drivers. - */ - 'queue' => env('DISCORD_ALERT_QUEUE', 'default'), -]; diff --git a/config/services.php b/config/services.php index 469d2aa5..c29c2c16 100644 --- a/config/services.php +++ b/config/services.php @@ -42,4 +42,11 @@ 'redirect' => env('TWITCH_REDIRECT_URI'), ], + 'discord' => [ + 'webhooks' => [ + 'default' => env('DISCORD_ALERT_WEBHOOK'), + 'issues' => env('VHEART_IT_ISSUES_WEBHOOK'), + 'moderation' => env('VHEART_DISCORD_MODERATION_WEBHOOK'), + ], + ], ]; From 9c4beaf154b60baba84b4589337dbc01cf53b946 Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 04:47:51 +0200 Subject: [PATCH 04/10] refactor old discord webhook job to abstract base class for future jobs --- ...bhookJob.php => BaseDiscordWebhookJob.php} | 148 +++++++++++------- 1 file changed, 89 insertions(+), 59 deletions(-) rename app/Jobs/Discord/{DiscordWebhookJob.php => BaseDiscordWebhookJob.php} (54%) diff --git a/app/Jobs/Discord/DiscordWebhookJob.php b/app/Jobs/Discord/BaseDiscordWebhookJob.php similarity index 54% rename from app/Jobs/Discord/DiscordWebhookJob.php rename to app/Jobs/Discord/BaseDiscordWebhookJob.php index 52750d5b..a8150852 100644 --- a/app/Jobs/Discord/DiscordWebhookJob.php +++ b/app/Jobs/Discord/BaseDiscordWebhookJob.php @@ -5,41 +5,44 @@ namespace App\Jobs\Discord; use App\Events\Discord\DiscordWebhookDied; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeEncrypted; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Http\Client\ConnectionException; +use Illuminate\Http\Client\PendingRequest; use Illuminate\Http\Client\Response; use Illuminate\Queue\Attributes\MaxExceptions; use Illuminate\Queue\Attributes\Tries; +use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\RateLimited; use Illuminate\Queue\Middleware\Skip; use Illuminate\Queue\Middleware\WithoutOverlapping; +use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; use InvalidArgumentException; -use Spatie\DiscordAlerts\Jobs\SendToDiscordChannelJob; +use JustinKluever\DiscordWebhookBuilder\Webhook; #[Tries(254)] #[MaxExceptions(3)] -class DiscordWebhookJob extends SendToDiscordChannelJob implements ShouldBeEncrypted +abstract class BaseDiscordWebhookJob implements ShouldBeEncrypted, ShouldQueue { - private readonly string $webhookId; - - public function __construct( - string $text, - string $webhookUrl, - ?string $username = null, - bool $tts = false, - ?string $avatar_url = null, - ?array $embeds = null - ) { - if (! preg_match('/webhooks\/(\d+)\//', $webhookUrl, $match)) { - throw new InvalidArgumentException('Could not extract Webhook Id from provided webhook url, are you sure this is a discord webhook url?'); - } + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; - parent::__construct($text, $webhookUrl, $username, $tts, $avatar_url, $embeds); - $this->webhookId = $match[1]; - } + /** + * The Webhook Payload we should send to discord + */ + abstract protected function getPayload(): Webhook; + + /** + * The Webhook Url we send the Payload to + */ + abstract protected function getWebhook(): string; public function middleware(): array { @@ -52,12 +55,25 @@ public function middleware(): array public function handle(): void { + if ($this->shouldRun() === false) { + return; + } + if ($this->releaseIfCurrentlyRateLimited()) { return; } try { - $response = Http::timeout(5)->post($this->webhookUrl, $this->getPayload()); + Log::debug("Sending to Discord Webhook {$this->getWebhookId()}", [ + 'webhook_id' => $this->getWebhookId(), + 'payload' => $this->getPayload(), + ]); + + $response = $this->getRequest(); + + if ($response instanceof PendingRequest) { + $response = $response->post($this->getWebhook(), $this->getPayload()); + } } catch (ConnectionException) { $this->release(30); @@ -81,16 +97,57 @@ public function handle(): void } if ($response->failed()) { - $this->fail("Discord webhook $this->webhookId failed with status {$response->status()}: {$response->body()}"); + $this->fail("Discord webhook {$this->getWebhookId()} failed with status {$response->status()}: {$response->body()}"); + + return; + } + + $this->handleResponse($response); + } + + /** + * Allows us to override the entire request if needed + * + * @throws ConnectionException + */ + protected function getRequest(): PendingRequest|Response + { + return Http::timeout(5)->post($this->getWebhook(), $this->getPayload()); + } + + /** + * Allows us to do stuff with the response later + */ + protected function handleResponse(Response $response): void {} + + /** + * In case we need a way to easily stop a job at handle time + */ + protected function shouldRun(): bool + { + return true; + } + + protected function getWebhookId(): string + { + if (! preg_match('/webhooks\/(\d+)\//', $this->getWebhook(), $match)) { + throw new InvalidArgumentException('Could not extract Webhook Id from provided webhook url, are you sure this is a discord webhook url?'); } + + return $match[1]; } - private function isWebhookInvalid(): bool + protected function isWebhookInvalid(): bool { return Cache::has($this->cacheKey('invalid')); } - private function updateRateLimitStatus(Response $response): void + protected function cacheKey(string $suffix): string + { + return "discord:webhook:{$this->getWebhookId()}:$suffix"; + } + + protected function updateRateLimitStatus(Response $response): void { $rateLimitRemainingHeader = $response->header('X-RateLimit-Remaining'); $rateLimitResetAtHeader = $response->header('X-RateLimit-Reset'); @@ -105,34 +162,7 @@ private function updateRateLimitStatus(Response $response): void } } - private function getPayload(): array - { - $payload = [ - 'content' => $this->text, - 'tts' => $this->tts, - ]; - - if (filled($this->username)) { - $payload['username'] = $this->username; - } - - if (filled($this->avatar_url)) { - $payload['avatar_url'] = $this->avatar_url; - } - - if (filled($this->embeds)) { - $payload['embeds'] = $this->embeds; - } - - return $payload; - } - - private function cacheKey(string $suffix): string - { - return "discord:webhook:$this->webhookId:$suffix"; - } - - private function releaseIfRateLimitedAfter(Response $response): bool + protected function releaseIfRateLimitedAfter(Response $response): bool { if ($response->status() !== 429) { return false; @@ -142,8 +172,8 @@ private function releaseIfRateLimitedAfter(Response $response): bool $retryAfter = (int) ceil($body['retry_after'] ?? $response->header('Retry-After') ?? 60); $scope = $response->header('X-RateLimit-Scope') ?? 'unknown'; - Log::debug("Webhook '$this->webhookId' has triggered discord rate-limit in the '$scope' rate limit scope", [ - 'webhook_id' => $this->webhookId, + Log::debug("Webhook '{$this->getWebhookId()}' has triggered discord rate-limit in the '$scope' rate limit scope", [ + 'webhook_id' => $this->getWebhookId(), 'retry-after' => $retryAfter, 'scope' => $scope, ]); @@ -153,7 +183,7 @@ private function releaseIfRateLimitedAfter(Response $response): bool return true; } - private function releaseIfCurrentlyRateLimited(): bool + protected function releaseIfCurrentlyRateLimited(): bool { $rateLimitRemaining = Cache::get($this->cacheKey('rate-limit:remaining')); $rateLimitResetAt = Cache::get($this->cacheKey('rate-limit:reset')); @@ -167,7 +197,7 @@ private function releaseIfCurrentlyRateLimited(): bool $retryAfter = max($rateLimitResetAt - now()->timestamp, 1); Log::debug('Discord Webhook has been delayed', [ - 'webhook_id' => $this->webhookId, + 'webhook_id' => $this->getWebhookId(), 'retry_after' => $retryAfter, ]); @@ -179,20 +209,20 @@ private function releaseIfCurrentlyRateLimited(): bool return false; } - private function failIfWebhookNotFound(Response $response): bool + protected function failIfWebhookNotFound(Response $response): bool { if ($response->status() !== 404) { return false; } - Log::info("Discord Webhook '$this->webhookId' was not found on discord, discarding future attempts.", [ - 'webhook_id' => $this->webhookId, + Log::info("Discord Webhook '{$this->getWebhookId()}' was not found on discord, discarding future attempts.", [ + 'webhook_id' => $this->getWebhookId(), ]); Cache::put($this->cacheKey('invalid'), true, now()->addWeek()); - DiscordWebhookDied::dispatch($this->webhookId, $this->webhookUrl); + DiscordWebhookDied::dispatch($this->getWebhookId(), $this->getWebhook()); - $this->fail("Webhook '$this->webhookId' was not found (404)"); + $this->fail("Webhook '{$this->getWebhookId()}' was not found (404)"); return true; } From adbd2fbec92284b4bbb98b0737a472423cfebbc4 Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 04:48:27 +0200 Subject: [PATCH 05/10] implement job to send current report status for us --- app/Jobs/Discord/ReportWebhookJob.php | 90 +++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 app/Jobs/Discord/ReportWebhookJob.php diff --git a/app/Jobs/Discord/ReportWebhookJob.php b/app/Jobs/Discord/ReportWebhookJob.php new file mode 100644 index 00000000..1c9f22fc --- /dev/null +++ b/app/Jobs/Discord/ReportWebhookJob.php @@ -0,0 +1,90 @@ +report->status->name; + + if ($this->report->resolver instanceof User) { + $currentStatus = 'Resolved by '.$this->report->resolver->name." ({$this->getDiscordTimestamp($this->report->resolved_at)})"; + } elseif ($this->report->claimer instanceof User) { + $currentStatus = 'Claimed by '.$this->report->claimer->name." ({$this->getDiscordTimestamp($this->report->claimed_at)})"; + } + + return Webhook::make() + ->flag(MessageFlag::IS_COMPONENTS_V2) + ->allowedMentions(AllowedMentions::none()->roles('1494691682422226996')) + ->component( + Container::make( + TextDisplay::make("### Report of type `{$this->report->reason->name}`"), + TextDisplay::make($this->report->description ?? 'No Details'), + Separator::make(), + TextDisplay::make("-# $currentStatus • Created {$this->getDiscordTimestamp($this->report->created_at)} • <@&1494691682422226996>") + ) + ->accentColor(Color::fromHex('#e71d73')), + ActionRow::make( + Button::make() + ->label('View Report') + ->style(ButtonStyle::Link) + ->url(Filament::getPanel('admin')->getResourceUrl($this->report, 'view')), + Button::make() + ->label('View '.Str::title($this->report->reportable_type)) + ->style(ButtonStyle::Link) + ->url(Filament::getPanel('admin')->getResourceUrl($this->report->reportable, 'view')), + Button::make() + ->label('View All Reports') + ->style(ButtonStyle::Link) + ->url(Filament::getPanel('admin')->getResourceUrl($this->report)) + ) + ); + } + + protected function handleResponse(Response $response): void + { + $messageId = $response->json('id'); + + Log::debug('Discord webhook response for report', [ + 'report_id' => $this->report->id, + 'message_id' => $messageId, + ]); + } + + protected function getWebhook(): string + { + return config('services.discord.webhooks.moderation').'?with_components=true&wait=true'; + } + + private function getDiscordTimestamp(CarbonInterface $dateTime): string + { + return "timestamp:R>"; + } +} From b5f71b08bfd699d04b7e0a67b06af4a6049f0b24 Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 04:48:50 +0200 Subject: [PATCH 06/10] refctor NotifyAboutReportsJob to use new job --- app/Jobs/Reports/NotifyAboutReportsJob.php | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/app/Jobs/Reports/NotifyAboutReportsJob.php b/app/Jobs/Reports/NotifyAboutReportsJob.php index f3d69695..a3c6c037 100644 --- a/app/Jobs/Reports/NotifyAboutReportsJob.php +++ b/app/Jobs/Reports/NotifyAboutReportsJob.php @@ -4,14 +4,12 @@ namespace App\Jobs\Reports; +use App\Jobs\Discord\ReportWebhookJob; use App\Models\Report; -use Exception; -use Filament\Facades\Filament; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Queue\Queueable; use Illuminate\Queue\Attributes\DebounceFor; use Illuminate\Support\Facades\Cache; -use Spatie\DiscordAlerts\Facades\DiscordAlert; /** * Notify moderation team about new reports @@ -38,20 +36,7 @@ public function handle(): void Cache::put(self::NOTIFICATION_CACHE_KEY_PREFIX.$report->id, true, now()->addWeek()); - $this->notifyDiscord($report); + ReportWebhookJob::dispatchSync($report); }); } - - private function notifyDiscord(Report $report): void - { - try { - DiscordAlert::to('moderation')->message('<@&1494691682422226996>', [[ - 'title' => 'New Report ('.$report->reason->name.')', - 'url' => Filament::getPanel('admin')->getResourceUrl($report, 'view'), - 'color' => '#e71d73', - ]]); - } catch (Exception $exception) { - report($exception); - } - } } From ae3dc9ea74355556d097b0b0839d2d8458be4c21 Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 05:00:34 +0200 Subject: [PATCH 07/10] actually dont use dispatchSync oops --- app/Jobs/Reports/NotifyAboutReportsJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Jobs/Reports/NotifyAboutReportsJob.php b/app/Jobs/Reports/NotifyAboutReportsJob.php index a3c6c037..86e3f1bb 100644 --- a/app/Jobs/Reports/NotifyAboutReportsJob.php +++ b/app/Jobs/Reports/NotifyAboutReportsJob.php @@ -36,7 +36,7 @@ public function handle(): void Cache::put(self::NOTIFICATION_CACHE_KEY_PREFIX.$report->id, true, now()->addWeek()); - ReportWebhookJob::dispatchSync($report); + ReportWebhookJob::dispatch($report); }); } } From b89089103f0751b5059be72ce345efe3749826c1 Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 05:01:03 +0200 Subject: [PATCH 08/10] always put discord webhooks on the discord-webhooks queue by default --- app/Jobs/Discord/BaseDiscordWebhookJob.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Jobs/Discord/BaseDiscordWebhookJob.php b/app/Jobs/Discord/BaseDiscordWebhookJob.php index a8150852..b13dd37a 100644 --- a/app/Jobs/Discord/BaseDiscordWebhookJob.php +++ b/app/Jobs/Discord/BaseDiscordWebhookJob.php @@ -13,6 +13,7 @@ use Illuminate\Http\Client\PendingRequest; use Illuminate\Http\Client\Response; use Illuminate\Queue\Attributes\MaxExceptions; +use Illuminate\Queue\Attributes\Queue; use Illuminate\Queue\Attributes\Tries; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\RateLimited; @@ -27,6 +28,7 @@ #[Tries(254)] #[MaxExceptions(3)] +#[Queue('discord-webhooks')] abstract class BaseDiscordWebhookJob implements ShouldBeEncrypted, ShouldQueue { use Dispatchable; From 0637db32a1cc1996d3c3850294e62acc76fa44be Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 05:01:35 +0200 Subject: [PATCH 09/10] put report webhook job on the moderation queue for higher priority --- app/Jobs/Discord/ReportWebhookJob.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Jobs/Discord/ReportWebhookJob.php b/app/Jobs/Discord/ReportWebhookJob.php index 1c9f22fc..b80c1b18 100644 --- a/app/Jobs/Discord/ReportWebhookJob.php +++ b/app/Jobs/Discord/ReportWebhookJob.php @@ -10,6 +10,7 @@ use Filament\Facades\Filament; use Illuminate\Http\Client\Response; use Illuminate\Queue\Attributes\DeleteWhenMissingModels; +use Illuminate\Queue\Attributes\Queue; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; use JustinKluever\DiscordWebhookBuilder\Components\ActionRow; @@ -24,6 +25,7 @@ use JustinKluever\DiscordWebhookBuilder\Webhook; #[DeleteWhenMissingModels] +#[Queue('moderation')] class ReportWebhookJob extends BaseDiscordWebhookJob { public function __construct( From 8134e42e1bfdaf5c5e854a972b5b8193fa6038c4 Mon Sep 17 00:00:00 2001 From: "Justin K." Date: Sun, 14 Jun 2026 05:03:48 +0200 Subject: [PATCH 10/10] update queue worker entrypoint to also work on moderation and discord-webhooks queue --- docker/release/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/release/entrypoint.sh b/docker/release/entrypoint.sh index 62f12511..6b56d9b7 100644 --- a/docker/release/entrypoint.sh +++ b/docker/release/entrypoint.sh @@ -60,7 +60,7 @@ elif [ "$INSTANCE" = "worker" ]; then echo "[Entrypoint] Starting Laravel Worker..." exec /app/artisan queue:work \ --name=queue-worker \ - --queue=default \ + --queue=moderation,default,discord-webhooks \ --sleep=3 \ --tries=3 \ --max-time=3600 \