feat: add opt-out toggle for prestige bot announcements
CI / Lint, Build & Test (pull_request) Failing after 1m2s
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m9s

Adds enablePrestigeAnnouncements to ProfileSettings (defaults to true).
The prestige route now checks this setting before posting the Discord
webhook, and the edit profile modal exposes a toggle in the Sounds &
Notifications section so players can opt out.

Closes #169
This commit is contained in:
2026-03-31 13:20:01 -07:00
committed by Naomi Carrigan
parent 19f5f5e54f
commit 87686a310f
5 changed files with 65 additions and 11 deletions
+22 -9
View File
@@ -147,17 +147,30 @@ prestigeRouter.post("/", async(context) => {
const prestigeCount = prestigeData.count;
void logger.metric("prestige", 1, { discordId, prestigeCount });
void postMilestoneWebhook(discordId, "prestige", {
// eslint-disable-next-line capitalized-comments -- v8 ignore
/* v8 ignore next -- @preserve */
apotheosis: prestigeState.apotheosis?.count ?? 0,
prestige: prestigeData.count,
// eslint-disable-next-line capitalized-comments -- v8 ignore
/* v8 ignore next 2 -- @preserve */
transcendence: prestigeState.transcendence?.count ?? 0,
const playerRecord = await prisma.player.findUnique({
select: { profileSettings: true },
where: { discordId },
});
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Runtime shape check for JSON field */
const playerSettings = playerRecord?.profileSettings as
Record<string, unknown> | null | undefined;
const announcementsEnabled
= playerSettings?.enablePrestigeAnnouncements !== false;
if (announcementsEnabled) {
void postMilestoneWebhook(discordId, "prestige", {
// eslint-disable-next-line capitalized-comments -- v8 ignore
/* v8 ignore next -- @preserve */
apotheosis: prestigeState.apotheosis?.count ?? 0,
prestige: prestigeData.count,
// eslint-disable-next-line capitalized-comments -- v8 ignore
/* v8 ignore next 2 -- @preserve */
transcendence: prestigeState.transcendence?.count ?? 0,
});
}
return context.json({
milestoneRunestones: milestoneRunestones,
+2
View File
@@ -47,6 +47,7 @@ const parseProfileSettings = (raw: unknown): ProfileSettings => {
: "suffix";
return {
enableNotifications: rawObject.enableNotifications === true,
enablePrestigeAnnouncements: rawObject.enablePrestigeAnnouncements !== false,
enableSounds: rawObject.enableSounds === true,
numberFormat: numberFormat,
showAchievementsUnlocked: rawObject.showAchievementsUnlocked !== false,
@@ -222,6 +223,7 @@ profileRouter.put("/", authMiddleware, async(context) => {
: "suffix";
const profileSettings: ProfileSettings = {
enableNotifications: body.profileSettings.enableNotifications ?? false,
enablePrestigeAnnouncements: body.profileSettings.enablePrestigeAnnouncements ?? true,
enableSounds: body.profileSettings.enableSounds ?? false,
numberFormat: numberFormat,
showAchievementsUnlocked: body.profileSettings.showAchievementsUnlocked ?? true,