Local Build and Deploy / deploy (push) Successful in 1m5s
- 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
81 lines
2.1 KiB
TypeScript
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 {}
|
|
}
|