From babccfd08a91dacf31551598a80bf12b5931c138 Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Thu, 12 Feb 2026 15:00:21 +0100 Subject: [PATCH] feat(config): add getGuildConfig() for database-backed guild settings Add function to fetch guild-specific config from database with: - 60-second cache TTL - Fallback to file-based config for migration period - Cache invalidation helper --- shared/lib/config.ts | 79 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/shared/lib/config.ts b/shared/lib/config.ts index 0d11def..cd54a9f 100644 --- a/shared/lib/config.ts +++ b/shared/lib/config.ts @@ -5,6 +5,85 @@ import { z } from 'zod'; const configPath = join(import.meta.dir, '..', 'config', 'config.json'); +export interface GuildConfig { + studentRole?: string; + visitorRole?: string; + colorRoles: string[]; + welcomeChannelId?: string; + welcomeMessage?: string; + feedbackChannelId?: string; + terminal?: { + channelId: string; + messageId: string; + }; + moderation: { + cases: { + dmOnWarn: boolean; + logChannelId?: string; + autoTimeoutThreshold?: number; + }; + }; +} + +const guildConfigCache = new Map(); +const CACHE_TTL_MS = 60000; + +export async function getGuildConfig(guildId: string): Promise { + const cached = guildConfigCache.get(guildId); + if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) { + return cached.config; + } + + try { + const { guildSettingsService } = await import('@shared/modules/guild-settings/guild-settings.service'); + const dbSettings = await guildSettingsService.getSettings(guildId); + + if (dbSettings) { + const config: GuildConfig = { + studentRole: dbSettings.studentRoleId, + visitorRole: dbSettings.visitorRoleId, + colorRoles: dbSettings.colorRoleIds ?? [], + welcomeChannelId: dbSettings.welcomeChannelId, + welcomeMessage: dbSettings.welcomeMessage, + feedbackChannelId: dbSettings.feedbackChannelId, + terminal: dbSettings.terminalChannelId ? { + channelId: dbSettings.terminalChannelId, + messageId: dbSettings.terminalMessageId ?? "", + } : undefined, + moderation: { + cases: { + dmOnWarn: dbSettings.moderationDmOnWarn ?? true, + logChannelId: dbSettings.moderationLogChannelId, + autoTimeoutThreshold: dbSettings.moderationAutoTimeoutThreshold, + }, + }, + }; + + guildConfigCache.set(guildId, { config, timestamp: Date.now() }); + return config; + } + } catch (error) { + console.error("Failed to load guild config from database:", error); + } + + const fileConfig: GuildConfig = { + studentRole: config.studentRole, + visitorRole: config.visitorRole, + colorRoles: config.colorRoles, + welcomeChannelId: config.welcomeChannelId, + welcomeMessage: config.welcomeMessage, + feedbackChannelId: config.feedbackChannelId, + terminal: config.terminal, + moderation: config.moderation, + }; + + return fileConfig; +} + +export function invalidateGuildConfigCache(guildId: string) { + guildConfigCache.delete(guildId); +} + export interface GameConfigType { leveling: { base: number;