Enhance environment configuration and expand Prisma schema for bot management
- Added OWNER_USER_IDS to .env.example for specifying global bot owners. - Introduced new models in the Prisma schema: CommandOverride, OwnerTeamMember, GlobalUserBlacklist, GuildBlacklist, FeatureFlag, BotPresenceConfig, ChangelogEntry, and OwnerAuditLog to support advanced bot management features. - Updated env.ts to preprocess OWNER_USER_IDS for better handling of global bot owner IDs. - Modified ModulePlaceholderPage to ensure proper routing for remaining dashboard modules.
This commit is contained in:
@@ -12,7 +12,25 @@ const EnvSchema = z.object({
|
||||
WEBUI_URL: z.string().url().default('http://localhost:3000'),
|
||||
SESSION_SECRET: z.string().min(32, 'SESSION_SECRET must be at least 32 characters long'),
|
||||
SENTRY_DSN: z.string().optional(),
|
||||
DEFAULT_LOCALE: z.enum(['de', 'en']).default('de')
|
||||
DEFAULT_LOCALE: z.enum(['de', 'en']).default('de'),
|
||||
/**
|
||||
* Comma-separated Discord user IDs that are treated as global bot owners
|
||||
* for the (future) owner panel. Optional for now.
|
||||
*/
|
||||
OWNER_USER_IDS: z.preprocess(
|
||||
(value) => (typeof value === 'string' && value.trim() === '' ? undefined : value),
|
||||
z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((value) =>
|
||||
value
|
||||
? value
|
||||
.split(',')
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id.length > 0)
|
||||
: []
|
||||
)
|
||||
)
|
||||
});
|
||||
|
||||
export const env = EnvSchema.parse(process.env);
|
||||
|
||||
43
apps/webui/src/lib/module-configs/automod.ts
Normal file
43
apps/webui/src/lib/module-configs/automod.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { AutomodConfigDashboard, AutomodConfigDashboardPatch } from '@nexumi/shared';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
async function ensureAutoModConfig(guildId: string) {
|
||||
await prisma.guild.upsert({ where: { id: guildId }, update: {}, create: { id: guildId } });
|
||||
return prisma.autoModConfig.upsert({
|
||||
where: { guildId },
|
||||
update: {},
|
||||
create: { guildId }
|
||||
});
|
||||
}
|
||||
|
||||
function toDashboard(config: Awaited<ReturnType<typeof ensureAutoModConfig>>): AutomodConfigDashboard {
|
||||
return {
|
||||
enabled: config.enabled,
|
||||
antiRaidEnabled: config.antiRaidEnabled,
|
||||
antiRaidJoinThreshold: config.antiRaidJoinThreshold,
|
||||
antiRaidWindowSeconds: config.antiRaidWindowSeconds,
|
||||
antiRaidAction: 'LOCKDOWN',
|
||||
antiNukeEnabled: config.antiNukeEnabled,
|
||||
antiNukeBanThreshold: config.antiNukeBanThreshold,
|
||||
antiNukeChannelThreshold: config.antiNukeChannelThreshold,
|
||||
antiNukeWindowSeconds: config.antiNukeWindowSeconds,
|
||||
lockdownActive: config.lockdownActive
|
||||
};
|
||||
}
|
||||
|
||||
export async function getAutomodDashboard(guildId: string): Promise<AutomodConfigDashboard> {
|
||||
const config = await ensureAutoModConfig(guildId);
|
||||
return toDashboard(config);
|
||||
}
|
||||
|
||||
export async function updateAutomodDashboard(
|
||||
guildId: string,
|
||||
patch: AutomodConfigDashboardPatch
|
||||
): Promise<AutomodConfigDashboard> {
|
||||
await ensureAutoModConfig(guildId);
|
||||
const updated = await prisma.autoModConfig.update({
|
||||
where: { guildId },
|
||||
data: patch
|
||||
});
|
||||
return toDashboard(updated);
|
||||
}
|
||||
39
apps/webui/src/lib/module-configs/cases.ts
Normal file
39
apps/webui/src/lib/module-configs/cases.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { CaseDashboard, CaseListQuery } from '@nexumi/shared';
|
||||
import type { Prisma } from '@prisma/client';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
export async function listCases(guildId: string, query: CaseListQuery): Promise<CaseDashboard[]> {
|
||||
const where: Prisma.CaseWhereInput = {
|
||||
guildId,
|
||||
deletedAt: null
|
||||
};
|
||||
|
||||
if (query.action) {
|
||||
where.action = query.action;
|
||||
}
|
||||
|
||||
if (query.search) {
|
||||
where.OR = [
|
||||
{ targetUserId: { contains: query.search } },
|
||||
{ moderatorId: { contains: query.search } },
|
||||
{ reason: { contains: query.search, mode: 'insensitive' } }
|
||||
];
|
||||
}
|
||||
|
||||
const cases = await prisma.case.findMany({
|
||||
where,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: query.limit
|
||||
});
|
||||
|
||||
return cases.map((entry) => ({
|
||||
id: entry.id,
|
||||
caseNumber: entry.caseNumber,
|
||||
targetUserId: entry.targetUserId,
|
||||
moderatorId: entry.moderatorId,
|
||||
action: entry.action,
|
||||
reason: entry.reason,
|
||||
createdAt: entry.createdAt.toISOString(),
|
||||
deletedAt: entry.deletedAt ? entry.deletedAt.toISOString() : null
|
||||
}));
|
||||
}
|
||||
39
apps/webui/src/lib/module-configs/economy.ts
Normal file
39
apps/webui/src/lib/module-configs/economy.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { EconomyConfigDashboard, EconomyConfigDashboardPatch } from '@nexumi/shared';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
async function ensureEconomyConfig(guildId: string) {
|
||||
await prisma.guild.upsert({ where: { id: guildId }, update: {}, create: { id: guildId } });
|
||||
return prisma.economyConfig.upsert({
|
||||
where: { guildId },
|
||||
update: {},
|
||||
create: { guildId }
|
||||
});
|
||||
}
|
||||
|
||||
function toDashboard(config: Awaited<ReturnType<typeof ensureEconomyConfig>>): EconomyConfigDashboard {
|
||||
return {
|
||||
enabled: config.enabled,
|
||||
currencyName: config.currencyName,
|
||||
currencySymbol: config.currencySymbol,
|
||||
dailyAmount: config.dailyAmount,
|
||||
weeklyAmount: config.weeklyAmount,
|
||||
workMin: config.workMin,
|
||||
workMax: config.workMax,
|
||||
workCooldownSeconds: config.workCooldownSeconds,
|
||||
startingBalance: config.startingBalance
|
||||
};
|
||||
}
|
||||
|
||||
export async function getEconomyDashboard(guildId: string): Promise<EconomyConfigDashboard> {
|
||||
const config = await ensureEconomyConfig(guildId);
|
||||
return toDashboard(config);
|
||||
}
|
||||
|
||||
export async function updateEconomyDashboard(
|
||||
guildId: string,
|
||||
patch: EconomyConfigDashboardPatch
|
||||
): Promise<EconomyConfigDashboard> {
|
||||
await ensureEconomyConfig(guildId);
|
||||
const updated = await prisma.economyConfig.update({ where: { guildId }, data: patch });
|
||||
return toDashboard(updated);
|
||||
}
|
||||
29
apps/webui/src/lib/module-configs/fun.ts
Normal file
29
apps/webui/src/lib/module-configs/fun.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { FunConfigDashboard, FunConfigDashboardPatch } from '@nexumi/shared';
|
||||
import { redis } from '../redis';
|
||||
|
||||
function funConfigKey(guildId: string): string {
|
||||
return `fun:config:${guildId}`;
|
||||
}
|
||||
|
||||
export async function getFunDashboard(guildId: string): Promise<FunConfigDashboard> {
|
||||
const raw = await redis.get(funConfigKey(guildId));
|
||||
if (!raw) {
|
||||
return { enabled: true, mediaEnabled: true };
|
||||
}
|
||||
try {
|
||||
const parsed = JSON.parse(raw) as Partial<FunConfigDashboard>;
|
||||
return { enabled: parsed.enabled ?? true, mediaEnabled: parsed.mediaEnabled ?? true };
|
||||
} catch {
|
||||
return { enabled: true, mediaEnabled: true };
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateFunDashboard(
|
||||
guildId: string,
|
||||
patch: FunConfigDashboardPatch
|
||||
): Promise<FunConfigDashboard> {
|
||||
const current = await getFunDashboard(guildId);
|
||||
const next: FunConfigDashboard = { ...current, ...patch };
|
||||
await redis.set(funConfigKey(guildId), JSON.stringify(next));
|
||||
return next;
|
||||
}
|
||||
69
apps/webui/src/lib/module-configs/leveling.ts
Normal file
69
apps/webui/src/lib/module-configs/leveling.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { LevelingConfigDashboard, LevelingConfigDashboardPatch } from '@nexumi/shared';
|
||||
import type { Prisma } from '@prisma/client';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
async function ensureLevelingConfig(guildId: string) {
|
||||
await prisma.guild.upsert({ where: { id: guildId }, update: {}, create: { id: guildId } });
|
||||
return prisma.levelingConfig.upsert({
|
||||
where: { guildId },
|
||||
update: {},
|
||||
create: { guildId }
|
||||
});
|
||||
}
|
||||
|
||||
function toMultiplierMap(raw: unknown): Record<string, number> {
|
||||
if (!raw || typeof raw !== 'object') {
|
||||
return {};
|
||||
}
|
||||
const entries = Object.entries(raw as Record<string, unknown>).filter(
|
||||
(entry): entry is [string, number] => typeof entry[1] === 'number'
|
||||
);
|
||||
return Object.fromEntries(entries);
|
||||
}
|
||||
|
||||
function toDashboard(config: Awaited<ReturnType<typeof ensureLevelingConfig>>): LevelingConfigDashboard {
|
||||
return {
|
||||
enabled: config.enabled,
|
||||
textXpMin: config.textXpMin,
|
||||
textXpMax: config.textXpMax,
|
||||
textCooldownSeconds: config.textCooldownSeconds,
|
||||
voiceXpPerMinute: config.voiceXpPerMinute,
|
||||
noXpChannelIds: config.noXpChannelIds,
|
||||
noXpRoleIds: config.noXpRoleIds,
|
||||
roleMultipliers: toMultiplierMap(config.roleMultipliers),
|
||||
channelMultipliers: toMultiplierMap(config.channelMultipliers),
|
||||
levelUpMode: config.levelUpMode as LevelingConfigDashboard['levelUpMode'],
|
||||
levelUpChannelId: config.levelUpChannelId ?? '',
|
||||
levelUpMessage: config.levelUpMessage,
|
||||
stackRewards: config.stackRewards,
|
||||
cardAccentColor: config.cardAccentColor,
|
||||
cardBackgroundColor: config.cardBackgroundColor
|
||||
};
|
||||
}
|
||||
|
||||
export async function getLevelingDashboard(guildId: string): Promise<LevelingConfigDashboard> {
|
||||
const config = await ensureLevelingConfig(guildId);
|
||||
return toDashboard(config);
|
||||
}
|
||||
|
||||
export async function updateLevelingDashboard(
|
||||
guildId: string,
|
||||
patch: LevelingConfigDashboardPatch
|
||||
): Promise<LevelingConfigDashboard> {
|
||||
await ensureLevelingConfig(guildId);
|
||||
|
||||
const { levelUpChannelId, roleMultipliers, channelMultipliers, ...rest } = patch;
|
||||
const data: Prisma.LevelingConfigUpdateInput = { ...rest };
|
||||
if (levelUpChannelId !== undefined) {
|
||||
data.levelUpChannelId = levelUpChannelId === '' ? null : levelUpChannelId;
|
||||
}
|
||||
if (roleMultipliers !== undefined) {
|
||||
data.roleMultipliers = roleMultipliers as Prisma.InputJsonValue;
|
||||
}
|
||||
if (channelMultipliers !== undefined) {
|
||||
data.channelMultipliers = channelMultipliers as Prisma.InputJsonValue;
|
||||
}
|
||||
|
||||
const updated = await prisma.levelingConfig.update({ where: { guildId }, data });
|
||||
return toDashboard(updated);
|
||||
}
|
||||
55
apps/webui/src/lib/module-configs/logging.ts
Normal file
55
apps/webui/src/lib/module-configs/logging.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import type { LogEventTypeDashboard, LoggingConfigDashboard, LoggingConfigDashboardPatch } from '@nexumi/shared';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
async function ensureLoggingConfig(guildId: string) {
|
||||
await prisma.guild.upsert({ where: { id: guildId }, update: {}, create: { id: guildId } });
|
||||
return prisma.loggingConfig.upsert({
|
||||
where: { guildId },
|
||||
update: {},
|
||||
create: { guildId }
|
||||
});
|
||||
}
|
||||
|
||||
export async function getLoggingDashboard(guildId: string): Promise<LoggingConfigDashboard> {
|
||||
const [config, channels] = await Promise.all([
|
||||
ensureLoggingConfig(guildId),
|
||||
prisma.logChannel.findMany({ where: { guildId }, orderBy: { eventType: 'asc' } })
|
||||
]);
|
||||
|
||||
return {
|
||||
enabled: config.enabled,
|
||||
ignoreBots: config.ignoreBots,
|
||||
ignoredChannelIds: config.ignoredChannelIds,
|
||||
ignoredRoleIds: config.ignoredRoleIds,
|
||||
logChannels: channels.map((channel) => ({
|
||||
eventType: channel.eventType as LogEventTypeDashboard,
|
||||
channelId: channel.channelId
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
export async function updateLoggingDashboard(
|
||||
guildId: string,
|
||||
patch: LoggingConfigDashboardPatch
|
||||
): Promise<LoggingConfigDashboard> {
|
||||
await ensureLoggingConfig(guildId);
|
||||
|
||||
const { logChannels, ...configPatch } = patch;
|
||||
|
||||
if (Object.keys(configPatch).length > 0) {
|
||||
await prisma.loggingConfig.update({ where: { guildId }, data: configPatch });
|
||||
}
|
||||
|
||||
if (logChannels !== undefined) {
|
||||
await prisma.$transaction([
|
||||
prisma.logChannel.deleteMany({ where: { guildId } }),
|
||||
...logChannels.map((mapping) =>
|
||||
prisma.logChannel.create({
|
||||
data: { guildId, eventType: mapping.eventType, channelId: mapping.channelId }
|
||||
})
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
return getLoggingDashboard(guildId);
|
||||
}
|
||||
69
apps/webui/src/lib/module-configs/moderation.ts
Normal file
69
apps/webui/src/lib/module-configs/moderation.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { EscalationAction, ModerationDashboard, ModerationDashboardPatch } from '@nexumi/shared';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
async function ensureGuild(guildId: string): Promise<void> {
|
||||
await prisma.guild.upsert({ where: { id: guildId }, update: {}, create: { id: guildId } });
|
||||
}
|
||||
|
||||
async function ensureGuildSettings(guildId: string) {
|
||||
await ensureGuild(guildId);
|
||||
return prisma.guildSettings.upsert({
|
||||
where: { guildId },
|
||||
update: {},
|
||||
create: { guildId }
|
||||
});
|
||||
}
|
||||
|
||||
export async function getModerationDashboard(guildId: string): Promise<ModerationDashboard> {
|
||||
const [settings, rules] = await Promise.all([
|
||||
ensureGuildSettings(guildId),
|
||||
prisma.escalationRule.findMany({ where: { guildId }, orderBy: { warnCount: 'asc' } })
|
||||
]);
|
||||
|
||||
return {
|
||||
moderationEnabled: settings.moderationEnabled,
|
||||
escalations: rules.map((rule) => ({
|
||||
id: rule.id,
|
||||
warnCount: rule.warnCount,
|
||||
action: rule.action as EscalationAction,
|
||||
durationMs: rule.durationMs,
|
||||
reason: rule.reason,
|
||||
enabled: rule.enabled
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
export async function updateModerationDashboard(
|
||||
guildId: string,
|
||||
patch: ModerationDashboardPatch
|
||||
): Promise<ModerationDashboard> {
|
||||
await ensureGuild(guildId);
|
||||
|
||||
if (patch.moderationEnabled !== undefined) {
|
||||
await prisma.guildSettings.upsert({
|
||||
where: { guildId },
|
||||
update: { moderationEnabled: patch.moderationEnabled },
|
||||
create: { guildId, moderationEnabled: patch.moderationEnabled }
|
||||
});
|
||||
}
|
||||
|
||||
if (patch.escalations !== undefined) {
|
||||
await prisma.$transaction([
|
||||
prisma.escalationRule.deleteMany({ where: { guildId } }),
|
||||
...patch.escalations.map((rule) =>
|
||||
prisma.escalationRule.create({
|
||||
data: {
|
||||
guildId,
|
||||
warnCount: rule.warnCount,
|
||||
action: rule.action,
|
||||
durationMs: rule.durationMs ?? null,
|
||||
reason: rule.reason ?? null,
|
||||
enabled: rule.enabled
|
||||
}
|
||||
})
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
return getModerationDashboard(guildId);
|
||||
}
|
||||
51
apps/webui/src/lib/module-configs/verification.ts
Normal file
51
apps/webui/src/lib/module-configs/verification.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import type { VerificationConfigDashboard, VerificationConfigDashboardPatch } from '@nexumi/shared';
|
||||
import type { Prisma } from '@prisma/client';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
async function ensureVerificationConfig(guildId: string) {
|
||||
await prisma.guild.upsert({ where: { id: guildId }, update: {}, create: { id: guildId } });
|
||||
return prisma.verificationConfig.upsert({
|
||||
where: { guildId },
|
||||
update: {},
|
||||
create: { guildId }
|
||||
});
|
||||
}
|
||||
|
||||
function toDashboard(config: Awaited<ReturnType<typeof ensureVerificationConfig>>): VerificationConfigDashboard {
|
||||
return {
|
||||
enabled: config.enabled,
|
||||
channelId: config.channelId ?? '',
|
||||
verifiedRoleId: config.verifiedRoleId ?? '',
|
||||
unverifiedRoleId: config.unverifiedRoleId ?? '',
|
||||
mode: config.mode as VerificationConfigDashboard['mode'],
|
||||
minAccountAgeDays: config.minAccountAgeDays,
|
||||
failAction: config.failAction as VerificationConfigDashboard['failAction']
|
||||
};
|
||||
}
|
||||
|
||||
export async function getVerificationDashboard(guildId: string): Promise<VerificationConfigDashboard> {
|
||||
const config = await ensureVerificationConfig(guildId);
|
||||
return toDashboard(config);
|
||||
}
|
||||
|
||||
export async function updateVerificationDashboard(
|
||||
guildId: string,
|
||||
patch: VerificationConfigDashboardPatch
|
||||
): Promise<VerificationConfigDashboard> {
|
||||
await ensureVerificationConfig(guildId);
|
||||
|
||||
const { channelId, verifiedRoleId, unverifiedRoleId, ...rest } = patch;
|
||||
const data: Prisma.VerificationConfigUpdateInput = { ...rest };
|
||||
if (channelId !== undefined) {
|
||||
data.channelId = channelId === '' ? null : channelId;
|
||||
}
|
||||
if (verifiedRoleId !== undefined) {
|
||||
data.verifiedRoleId = verifiedRoleId === '' ? null : verifiedRoleId;
|
||||
}
|
||||
if (unverifiedRoleId !== undefined) {
|
||||
data.unverifiedRoleId = unverifiedRoleId === '' ? null : unverifiedRoleId;
|
||||
}
|
||||
|
||||
const updated = await prisma.verificationConfig.update({ where: { guildId }, data });
|
||||
return toDashboard(updated);
|
||||
}
|
||||
22
apps/webui/src/lib/module-configs/warnings.ts
Normal file
22
apps/webui/src/lib/module-configs/warnings.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { WarningDashboard, WarningListQuery } from '@nexumi/shared';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
export async function listWarnings(guildId: string, query: WarningListQuery): Promise<WarningDashboard[]> {
|
||||
const warnings = await prisma.warning.findMany({
|
||||
where: {
|
||||
guildId,
|
||||
...(query.userId ? { userId: query.userId } : {})
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 100
|
||||
});
|
||||
|
||||
return warnings.map((warning) => ({
|
||||
id: warning.id,
|
||||
userId: warning.userId,
|
||||
moderatorId: warning.moderatorId,
|
||||
reason: warning.reason,
|
||||
caseId: warning.caseId,
|
||||
createdAt: warning.createdAt.toISOString()
|
||||
}));
|
||||
}
|
||||
63
apps/webui/src/lib/module-configs/welcome.ts
Normal file
63
apps/webui/src/lib/module-configs/welcome.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import type { WelcomeConfigDashboard, WelcomeConfigDashboardPatch } from '@nexumi/shared';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
async function ensureWelcomeConfig(guildId: string) {
|
||||
await prisma.guild.upsert({ where: { id: guildId }, update: {}, create: { id: guildId } });
|
||||
return prisma.welcomeConfig.upsert({
|
||||
where: { guildId },
|
||||
update: {},
|
||||
create: { guildId }
|
||||
});
|
||||
}
|
||||
|
||||
function toDashboard(config: Awaited<ReturnType<typeof ensureWelcomeConfig>>): WelcomeConfigDashboard {
|
||||
return {
|
||||
welcomeEnabled: config.welcomeEnabled,
|
||||
leaveEnabled: config.leaveEnabled,
|
||||
welcomeChannelId: config.welcomeChannelId ?? '',
|
||||
leaveChannelId: config.leaveChannelId ?? '',
|
||||
welcomeType: config.welcomeType as WelcomeConfigDashboard['welcomeType'],
|
||||
welcomeContent: config.welcomeContent,
|
||||
welcomeEmbed: (config.welcomeEmbed as Record<string, unknown> | null) ?? null,
|
||||
leaveContent: config.leaveContent,
|
||||
leaveEmbed: (config.leaveEmbed as Record<string, unknown> | null) ?? null,
|
||||
welcomeDmEnabled: config.welcomeDmEnabled,
|
||||
welcomeDmContent: config.welcomeDmContent,
|
||||
userAutoroleIds: config.userAutoroleIds,
|
||||
botAutoroleIds: config.botAutoroleIds,
|
||||
imageTitle: config.imageTitle,
|
||||
imageSubtitle: config.imageSubtitle
|
||||
};
|
||||
}
|
||||
|
||||
export async function getWelcomeDashboard(guildId: string): Promise<WelcomeConfigDashboard> {
|
||||
const config = await ensureWelcomeConfig(guildId);
|
||||
return toDashboard(config);
|
||||
}
|
||||
|
||||
export async function updateWelcomeDashboard(
|
||||
guildId: string,
|
||||
patch: WelcomeConfigDashboardPatch
|
||||
): Promise<WelcomeConfigDashboard> {
|
||||
await ensureWelcomeConfig(guildId);
|
||||
|
||||
const { welcomeChannelId, leaveChannelId, welcomeEmbed, leaveEmbed, ...rest } = patch;
|
||||
|
||||
const data: Prisma.WelcomeConfigUpdateInput = { ...rest };
|
||||
if (welcomeChannelId !== undefined) {
|
||||
data.welcomeChannelId = welcomeChannelId === '' ? null : welcomeChannelId;
|
||||
}
|
||||
if (leaveChannelId !== undefined) {
|
||||
data.leaveChannelId = leaveChannelId === '' ? null : leaveChannelId;
|
||||
}
|
||||
if (welcomeEmbed !== undefined) {
|
||||
data.welcomeEmbed = welcomeEmbed === null ? Prisma.JsonNull : (welcomeEmbed as Prisma.InputJsonValue);
|
||||
}
|
||||
if (leaveEmbed !== undefined) {
|
||||
data.leaveEmbed = leaveEmbed === null ? Prisma.JsonNull : (leaveEmbed as Prisma.InputJsonValue);
|
||||
}
|
||||
|
||||
const updated = await prisma.welcomeConfig.update({ where: { guildId }, data });
|
||||
return toDashboard(updated);
|
||||
}
|
||||
Reference in New Issue
Block a user