diff --git a/apps/api/src/services/webhook.ts b/apps/api/src/services/webhook.ts index 72ddf1f..b7ef8cd 100644 --- a/apps/api/src/services/webhook.ts +++ b/apps/api/src/services/webhook.ts @@ -9,6 +9,12 @@ import { logger } from "./logger.js"; const discordApi = "https://discord.com/api/v10"; +/** + * Discord MessageFlags.SUPPRESS_NOTIFICATIONS — messages are delivered without + * triggering desktop or mobile push notifications. + */ +const suppressNotifications = 4096; + /** * Grants the apotheosis Discord role to the given player if configured. * Fails silently so role grant errors do not affect the game action. @@ -85,7 +91,10 @@ const postMilestoneWebhook = async( try { await fetch(webhookUrl, { - body: JSON.stringify({ content }), + body: JSON.stringify({ + content: content, + flags: suppressNotifications, + }), headers: { "Content-Type": "application/json" }, method: "POST", }); diff --git a/apps/api/test/services/webhook.spec.ts b/apps/api/test/services/webhook.spec.ts index 28680b0..a68a90a 100644 --- a/apps/api/test/services/webhook.spec.ts +++ b/apps/api/test/services/webhook.spec.ts @@ -97,9 +97,10 @@ describe("webhook service", () => { await postMilestoneWebhook("user123", "prestige", counts); const [url, options] = mockFetch.mock.calls[0] as [string, RequestInit]; expect(url).toBe("https://discord.com/webhook/abc"); - const body = JSON.parse(options.body as string) as { content: string }; + const body = JSON.parse(options.body as string) as { content: string; flags: number }; expect(body.content).toContain("<@user123>"); expect(body.content).toContain("prestiged"); + expect(body.flags).toBe(4096); }); it("posts transcendence message correctly", async () => {