Add events module with dashboard UI, scheduling, signups, and settings updates; extend env/readme.
This commit is contained in:
@@ -1,8 +1,225 @@
|
||||
import { prisma } from '../database';
|
||||
|
||||
export interface GuildSettings {
|
||||
welcomeChannelId?: string;
|
||||
logChannelId?: string;
|
||||
automodEnabled?: boolean;
|
||||
automodConfig?: any;
|
||||
statuspageEnabled?: boolean;
|
||||
statuspageConfig?: any;
|
||||
welcomeConfig?: {
|
||||
enabled?: boolean;
|
||||
channelId?: string;
|
||||
embedTitle?: string;
|
||||
embedDescription?: string;
|
||||
embedColor?: string;
|
||||
embedFooter?: string;
|
||||
embedThumbnail?: string;
|
||||
embedImage?: string;
|
||||
embedThumbnailData?: string;
|
||||
embedImageData?: string;
|
||||
};
|
||||
loggingConfig?: {
|
||||
logChannelId?: string;
|
||||
categories?: {
|
||||
joinLeave?: boolean;
|
||||
messageEdit?: boolean;
|
||||
messageDelete?: boolean;
|
||||
automodActions?: boolean;
|
||||
ticketActions?: boolean;
|
||||
musicEvents?: boolean;
|
||||
};
|
||||
};
|
||||
levelingEnabled?: boolean;
|
||||
ticketsEnabled?: boolean;
|
||||
musicEnabled?: boolean;
|
||||
dynamicVoiceEnabled?: boolean;
|
||||
dynamicVoiceConfig?: {
|
||||
lobbyChannelId?: string;
|
||||
categoryId?: string;
|
||||
userLimit?: number;
|
||||
bitrate?: number;
|
||||
template?: string;
|
||||
};
|
||||
eventsEnabled?: boolean;
|
||||
supportLoginConfig?: {
|
||||
panelChannelId?: string;
|
||||
panelMessageId?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
loginLabel?: string;
|
||||
logoutLabel?: string;
|
||||
autoRefresh?: boolean;
|
||||
};
|
||||
birthdayEnabled?: boolean;
|
||||
birthdayConfig?: {
|
||||
enabled?: boolean;
|
||||
channelId?: string;
|
||||
sendHour?: number;
|
||||
messageTemplate?: string;
|
||||
};
|
||||
reactionRolesEnabled?: boolean;
|
||||
reactionRolesConfig?: any;
|
||||
supportRoleId?: string;
|
||||
welcomeEnabled?: boolean;
|
||||
}
|
||||
|
||||
export const settings = new Map<string, GuildSettings>();
|
||||
class SettingsStore {
|
||||
private cache = new Map<string, GuildSettings>();
|
||||
|
||||
private applyModuleDefaults(cfg: GuildSettings): GuildSettings {
|
||||
const normalized: GuildSettings = { ...cfg };
|
||||
(
|
||||
[
|
||||
'ticketsEnabled',
|
||||
'automodEnabled',
|
||||
'welcomeEnabled',
|
||||
'levelingEnabled',
|
||||
'musicEnabled',
|
||||
'dynamicVoiceEnabled',
|
||||
'statuspageEnabled',
|
||||
'birthdayEnabled',
|
||||
'reactionRolesEnabled',
|
||||
'eventsEnabled'
|
||||
] as const
|
||||
).forEach((key) => {
|
||||
if (normalized[key] === undefined) normalized[key] = true;
|
||||
});
|
||||
// keep welcomeConfig flag in sync when present
|
||||
if (normalized.welcomeConfig && normalized.welcomeConfig.enabled === undefined && normalized.welcomeEnabled !== undefined) {
|
||||
normalized.welcomeConfig = { ...normalized.welcomeConfig, enabled: normalized.welcomeEnabled };
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
public async init() {
|
||||
const rows = await prisma.guildSettings.findMany();
|
||||
rows.forEach((row) => {
|
||||
const cfg = {
|
||||
welcomeChannelId: row.welcomeChannelId ?? undefined,
|
||||
logChannelId: row.logChannelId ?? undefined,
|
||||
automodEnabled: row.automodEnabled ?? undefined,
|
||||
automodConfig: (row as any).automodConfig ?? undefined,
|
||||
statuspageEnabled: (row as any).statuspageEnabled ?? (row as any).automodConfig?.statuspageEnabled ?? undefined,
|
||||
statuspageConfig: (row as any).statuspageConfig ?? (row as any).automodConfig?.statuspageConfig ?? undefined,
|
||||
welcomeEnabled: (row as any).welcomeEnabled ?? undefined,
|
||||
welcomeConfig: (row as any).automodConfig?.welcomeConfig ?? undefined,
|
||||
loggingConfig: (row as any).automodConfig?.loggingConfig ?? undefined,
|
||||
levelingEnabled: row.levelingEnabled ?? undefined,
|
||||
ticketsEnabled: row.ticketsEnabled ?? undefined,
|
||||
musicEnabled: (row as any).musicEnabled ?? undefined,
|
||||
dynamicVoiceEnabled: (row as any).dynamicVoiceEnabled ?? undefined,
|
||||
dynamicVoiceConfig: (row as any).dynamicVoiceConfig ?? undefined,
|
||||
eventsEnabled: (row as any).eventsEnabled ?? undefined,
|
||||
supportLoginConfig: (row as any).supportLoginConfig ?? undefined,
|
||||
birthdayEnabled: (row as any).birthdayEnabled ?? undefined,
|
||||
birthdayConfig: (row as any).birthdayConfig ?? undefined,
|
||||
reactionRolesEnabled: (row as any).reactionRolesEnabled ?? undefined,
|
||||
reactionRolesConfig: (row as any).reactionRolesConfig ?? undefined,
|
||||
supportRoleId: row.supportRoleId ?? undefined
|
||||
} satisfies GuildSettings;
|
||||
this.cache.set(row.guildId, this.applyModuleDefaults(cfg));
|
||||
});
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
public get(guildId: string) {
|
||||
const cached = this.cache.get(guildId);
|
||||
return cached ? this.applyModuleDefaults(cached) : undefined;
|
||||
}
|
||||
|
||||
public all() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
public async set(guildId: string, partial: GuildSettings) {
|
||||
if ((partial as any).welcomeEnabled !== undefined) {
|
||||
partial.welcomeConfig = { ...(partial.welcomeConfig ?? {}), enabled: (partial as any).welcomeEnabled };
|
||||
delete (partial as any).welcomeEnabled;
|
||||
}
|
||||
if (partial.birthdayEnabled !== undefined) {
|
||||
partial.birthdayConfig = { ...(partial.birthdayConfig ?? {}), enabled: partial.birthdayEnabled };
|
||||
} else if (partial.birthdayConfig?.enabled !== undefined) {
|
||||
partial.birthdayEnabled = partial.birthdayConfig.enabled;
|
||||
}
|
||||
if (partial.reactionRolesEnabled !== undefined) {
|
||||
partial.reactionRolesConfig = { ...(partial.reactionRolesConfig ?? {}), enabled: partial.reactionRolesEnabled };
|
||||
} else if (partial.reactionRolesConfig?.enabled !== undefined) {
|
||||
partial.reactionRolesEnabled = partial.reactionRolesConfig.enabled;
|
||||
}
|
||||
const merged: GuildSettings = this.applyModuleDefaults({ ...(this.cache.get(guildId) ?? {}), ...partial });
|
||||
const mergedAutomod = {
|
||||
...(merged.automodConfig ?? {}),
|
||||
...(partial.automodConfig ?? {}),
|
||||
loggingConfig: partial.loggingConfig ?? merged.loggingConfig ?? merged.automodConfig?.loggingConfig,
|
||||
welcomeConfig: partial.welcomeConfig ?? merged.welcomeConfig ?? merged.automodConfig?.welcomeConfig,
|
||||
statuspageEnabled: merged.statuspageEnabled,
|
||||
statuspageConfig: partial.statuspageConfig ?? merged.statuspageConfig ?? merged.automodConfig?.statuspageConfig
|
||||
};
|
||||
if (partial.dynamicVoiceConfig) {
|
||||
merged.dynamicVoiceConfig = { ...(merged.dynamicVoiceConfig ?? {}), ...partial.dynamicVoiceConfig };
|
||||
}
|
||||
if (partial.supportLoginConfig) {
|
||||
merged.supportLoginConfig = { ...(merged.supportLoginConfig ?? {}), ...partial.supportLoginConfig };
|
||||
}
|
||||
if (partial.birthdayConfig) {
|
||||
merged.birthdayConfig = { ...(merged.birthdayConfig ?? {}), ...partial.birthdayConfig };
|
||||
}
|
||||
if (partial.reactionRolesConfig) {
|
||||
merged.reactionRolesConfig = { ...(merged.reactionRolesConfig ?? {}), ...partial.reactionRolesConfig };
|
||||
}
|
||||
merged.automodConfig = { ...mergedAutomod, supportLoginConfig: merged.supportLoginConfig ?? mergedAutomod['supportLoginConfig'] };
|
||||
merged.statuspageEnabled = mergedAutomod.statuspageEnabled;
|
||||
merged.statuspageConfig = mergedAutomod.statuspageConfig;
|
||||
merged.loggingConfig = mergedAutomod.loggingConfig;
|
||||
merged.welcomeConfig = mergedAutomod.welcomeConfig;
|
||||
this.cache.set(guildId, merged);
|
||||
await prisma.guildSettings.upsert({
|
||||
where: { guildId },
|
||||
update: {
|
||||
welcomeChannelId: merged.welcomeChannelId ?? null,
|
||||
logChannelId: merged.logChannelId ?? null,
|
||||
automodEnabled: merged.automodEnabled ?? null,
|
||||
automodConfig: merged.automodConfig ?? null,
|
||||
levelingEnabled: merged.levelingEnabled ?? null,
|
||||
ticketsEnabled: merged.ticketsEnabled ?? null,
|
||||
musicEnabled: merged.musicEnabled ?? null,
|
||||
statuspageEnabled: merged.statuspageEnabled ?? null,
|
||||
statuspageConfig: merged.statuspageConfig ?? null,
|
||||
dynamicVoiceEnabled: merged.dynamicVoiceEnabled ?? null,
|
||||
dynamicVoiceConfig: merged.dynamicVoiceConfig ?? null,
|
||||
eventsEnabled: (merged as any).eventsEnabled ?? null,
|
||||
birthdayEnabled: merged.birthdayEnabled ?? null,
|
||||
birthdayConfig: merged.birthdayConfig ?? null,
|
||||
reactionRolesEnabled: merged.reactionRolesEnabled ?? null,
|
||||
reactionRolesConfig: merged.reactionRolesConfig ?? null,
|
||||
supportRoleId: merged.supportRoleId ?? null
|
||||
},
|
||||
create: {
|
||||
guildId,
|
||||
welcomeChannelId: merged.welcomeChannelId ?? null,
|
||||
logChannelId: merged.logChannelId ?? null,
|
||||
automodEnabled: merged.automodEnabled ?? null,
|
||||
automodConfig: merged.automodConfig ?? null,
|
||||
levelingEnabled: merged.levelingEnabled ?? null,
|
||||
ticketsEnabled: merged.ticketsEnabled ?? null,
|
||||
musicEnabled: merged.musicEnabled ?? null,
|
||||
statuspageEnabled: merged.statuspageEnabled ?? null,
|
||||
statuspageConfig: merged.statuspageConfig ?? null,
|
||||
dynamicVoiceEnabled: merged.dynamicVoiceEnabled ?? null,
|
||||
dynamicVoiceConfig: merged.dynamicVoiceConfig ?? null,
|
||||
eventsEnabled: (merged as any).eventsEnabled ?? null,
|
||||
birthdayEnabled: merged.birthdayEnabled ?? null,
|
||||
birthdayConfig: merged.birthdayConfig ?? null,
|
||||
reactionRolesEnabled: merged.reactionRolesEnabled ?? null,
|
||||
reactionRolesConfig: merged.reactionRolesConfig ?? null,
|
||||
supportRoleId: merged.supportRoleId ?? null
|
||||
}
|
||||
});
|
||||
return merged;
|
||||
}
|
||||
}
|
||||
|
||||
export const settingsStore = new SettingsStore();
|
||||
// Backwards compatibility for existing imports (read-only)
|
||||
export const settings = settingsStore.all();
|
||||
|
||||
Reference in New Issue
Block a user