Files
EpicNext-Cms/src/lib/notifications/preferences.ts
T
openhands 83f4585167
Local Build and Deploy / deploy (push) Successful in 1m5s
Feature: Plugin UI, event hooks, DB notifications, web push, webhook retry, games pages, rate limiting, tests
- Plugin admin UI: enable/disable per plugin with config forms
- Event hooks system: HookManager with on/off/emit for plugin events
- Database notifications: persistent via WebsiteNotification table + Redis pub/sub
- Notification preferences: per-user settings with API endpoints
- Web Push API: browser push notification subscription
- Webhook retry: 3 attempts with exponential backoff (1s/3s/9s) + delivery logs
- Webhook test button + paginated delivery log viewer
- Games: rank/challenge/reward admin pages
- Games: public frontend leaderboard
- Rate limiting: search API (30/min), notification stream dedup
- Unit tests: 28 new tests (registry, notifications, webhooks)
- Prisma migration 0017: website_notifications, website_notification_preferences, website_webhook_logs
2026-07-18 14:04:41 +02:00

81 lines
2.1 KiB
TypeScript

import "server-only";
import { prisma } from "@/lib/prisma";
export interface NotificationPreferences {
emailEnabled: boolean;
pushEnabled: boolean;
friendRequest: boolean;
messages: boolean;
guildInvite: boolean;
events: boolean;
alerts: boolean;
achievements: boolean;
radio: boolean;
}
const DEFAULTS: NotificationPreferences = {
emailEnabled: true,
pushEnabled: true,
friendRequest: true,
messages: true,
guildInvite: true,
events: true,
alerts: true,
achievements: true,
radio: true,
};
export async function getPreferences(
userId: number,
): Promise<NotificationPreferences> {
try {
const prefs = await prisma.websiteNotificationPreference.findUnique({
where: { userId: BigInt(userId) },
});
if (!prefs) return { ...DEFAULTS };
return {
emailEnabled: prefs.emailEnabled,
pushEnabled: prefs.pushEnabled,
friendRequest: prefs.friendRequest,
messages: prefs.messages,
guildInvite: prefs.guildInvite,
events: prefs.events,
alerts: prefs.alerts,
achievements: prefs.achievements,
radio: prefs.radio,
};
} catch {
return { ...DEFAULTS };
}
}
export async function updatePreferences(
userId: number,
prefs: Partial<NotificationPreferences>,
): Promise<void> {
try {
const existing = await prisma.websiteNotificationPreference.findUnique({
where: { userId: BigInt(userId) },
});
const data = {
emailEnabled: prefs.emailEnabled ?? existing?.emailEnabled ?? true,
pushEnabled: prefs.pushEnabled ?? existing?.pushEnabled ?? true,
friendRequest: prefs.friendRequest ?? existing?.friendRequest ?? true,
messages: prefs.messages ?? existing?.messages ?? true,
guildInvite: prefs.guildInvite ?? existing?.guildInvite ?? true,
events: prefs.events ?? existing?.events ?? true,
alerts: prefs.alerts ?? existing?.alerts ?? true,
achievements: prefs.achievements ?? existing?.achievements ?? true,
radio: prefs.radio ?? existing?.radio ?? true,
};
await prisma.websiteNotificationPreference.upsert({
where: { userId: BigInt(userId) },
update: data,
create: { userId: BigInt(userId), ...data },
});
} catch {}
}