import { eq } from "drizzle-orm"; import { gameSettings } from "@db/schema"; import { DrizzleClient } from "@shared/db/DrizzleClient"; import type { LevelingConfig, EconomyConfig, InventoryConfig, LootdropConfig, TriviaConfig, ModerationConfig, } from "@db/schema/game-settings"; export type GameSettingsData = { leveling: LevelingConfig; economy: EconomyConfig; inventory: InventoryConfig; lootdrop: LootdropConfig; trivia: TriviaConfig; moderation: ModerationConfig; commands: Record; system: Record; }; let cachedSettings: GameSettingsData | null = null; let cacheTimestamp = 0; const CACHE_TTL_MS = 30000; export const gameSettingsService = { getSettings: async (useCache = true): Promise => { if (useCache && cachedSettings && Date.now() - cacheTimestamp < CACHE_TTL_MS) { return cachedSettings; } const settings = await DrizzleClient.query.gameSettings.findFirst({ where: eq(gameSettings.id, "default"), }); if (!settings) return null; cachedSettings = { leveling: settings.leveling, economy: settings.economy, inventory: settings.inventory, lootdrop: settings.lootdrop, trivia: settings.trivia, moderation: settings.moderation, commands: settings.commands ?? {}, system: settings.system ?? {}, }; cacheTimestamp = Date.now(); return cachedSettings; }, upsertSettings: async (data: Partial) => { const existing = await gameSettingsService.getSettings(false); const values: typeof gameSettings.$inferInsert = { id: "default", leveling: data.leveling ?? existing?.leveling ?? gameSettingsService.getDefaultLeveling(), economy: data.economy ?? existing?.economy ?? gameSettingsService.getDefaultEconomy(), inventory: data.inventory ?? existing?.inventory ?? gameSettingsService.getDefaultInventory(), lootdrop: data.lootdrop ?? existing?.lootdrop ?? gameSettingsService.getDefaultLootdrop(), trivia: data.trivia ?? existing?.trivia ?? gameSettingsService.getDefaultTrivia(), moderation: data.moderation ?? existing?.moderation ?? gameSettingsService.getDefaultModeration(), commands: data.commands ?? existing?.commands ?? {}, system: data.system ?? existing?.system ?? {}, updatedAt: new Date(), }; const [result] = await DrizzleClient.insert(gameSettings) .values(values) .onConflictDoUpdate({ target: gameSettings.id, set: values, }) .returning(); gameSettingsService.invalidateCache(); return result; }, updateSection: async ( section: K, value: GameSettingsData[K] ) => { const existing = await gameSettingsService.getSettings(false); if (!existing) { throw new Error("Game settings not found. Initialize settings first."); } const updates: Partial = { [section]: value }; await gameSettingsService.upsertSettings(updates); gameSettingsService.invalidateCache(); }, toggleCommand: async (commandName: string, enabled: boolean) => { const settings = await gameSettingsService.getSettings(false); if (!settings) { throw new Error("Game settings not found. Initialize settings first."); } const commands = { ...settings.commands, [commandName]: enabled, }; await gameSettingsService.updateSection("commands", commands); }, invalidateCache: () => { cachedSettings = null; cacheTimestamp = 0; }, getDefaultLeveling: (): LevelingConfig => ({ base: 100, exponent: 1.5, chat: { cooldownMs: 60000, minXp: 5, maxXp: 15, }, }), getDefaultEconomy: (): EconomyConfig => ({ daily: { amount: "100", streakBonus: "10", weeklyBonus: "50", cooldownMs: 86400000, }, transfers: { allowSelfTransfer: false, minAmount: "1", }, exam: { multMin: 1.0, multMax: 2.0, }, }), getDefaultInventory: (): InventoryConfig => ({ maxStackSize: "99", maxSlots: 20, }), getDefaultLootdrop: (): LootdropConfig => ({ activityWindowMs: 300000, minMessages: 5, spawnChance: 0.1, cooldownMs: 60000, reward: { min: 10, max: 50, currency: "AU", }, }), getDefaultTrivia: (): TriviaConfig => ({ entryFee: "50", rewardMultiplier: 1.8, timeoutSeconds: 30, cooldownMs: 60000, categories: [], difficulty: "random", }), getDefaultModeration: (): ModerationConfig => ({ prune: { maxAmount: 100, confirmThreshold: 50, batchSize: 100, batchDelayMs: 1000, }, }), getDefaults: (): GameSettingsData => ({ leveling: gameSettingsService.getDefaultLeveling(), economy: gameSettingsService.getDefaultEconomy(), inventory: gameSettingsService.getDefaultInventory(), lootdrop: gameSettingsService.getDefaultLootdrop(), trivia: gameSettingsService.getDefaultTrivia(), moderation: gameSettingsService.getDefaultModeration(), commands: {}, system: {}, }), };