Enhance embed functionality across scheduler and welcome components
- Updated SchedulerManager and WelcomeForm to integrate DiscordEmbedBuilder for managing embeds, replacing JSON text areas with a more user-friendly interface. - Modified data handling in the scheduler and welcome configurations to support embed structures, ensuring proper parsing and validation. - Updated localization files to reflect changes in embed handling, improving user guidance and clarity in both English and German. - Enhanced validation schemas to require embed titles or descriptions where necessary, ensuring robust data integrity.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { ScheduledMessageDashboard, ScheduledMessageDashboardCreate } from '@nexumi/shared';
|
||||
import type { ScheduledMessage } from '@prisma/client';
|
||||
import type { ScheduledMessageDashboard, ScheduledMessageDashboardCreate, WelcomeEmbed } from '@nexumi/shared';
|
||||
import { Prisma, type ScheduledMessage } from '@prisma/client';
|
||||
import { prisma } from '../prisma';
|
||||
import { getScheduleQueue } from '../queues';
|
||||
|
||||
@@ -9,12 +9,27 @@ export class SchedulerValidationError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
function parseEmbed(raw: unknown): WelcomeEmbed | null {
|
||||
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
||||
return null;
|
||||
}
|
||||
const record = raw as Record<string, unknown>;
|
||||
const title = typeof record.title === 'string' ? record.title : undefined;
|
||||
const description = typeof record.description === 'string' ? record.description : undefined;
|
||||
const color = typeof record.color === 'number' ? record.color : undefined;
|
||||
if (!title && !description && color === undefined) {
|
||||
return null;
|
||||
}
|
||||
return { title, description, color };
|
||||
}
|
||||
|
||||
function toDashboard(schedule: ScheduledMessage): ScheduledMessageDashboard {
|
||||
return {
|
||||
id: schedule.id,
|
||||
channelId: schedule.channelId,
|
||||
creatorId: schedule.creatorId,
|
||||
content: schedule.content,
|
||||
embed: parseEmbed(schedule.embed),
|
||||
rolePingId: schedule.rolePingId,
|
||||
cron: schedule.cron,
|
||||
runAt: schedule.runAt?.toISOString() ?? null,
|
||||
@@ -69,6 +84,10 @@ export async function createScheduledMessageDashboard(
|
||||
channelId: input.channelId,
|
||||
creatorId,
|
||||
content: input.content?.trim() || null,
|
||||
embed:
|
||||
input.embed === undefined || input.embed === null
|
||||
? Prisma.JsonNull
|
||||
: (input.embed as Prisma.InputJsonValue),
|
||||
rolePingId: input.rolePingId || null,
|
||||
cron,
|
||||
runAt
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { TagDashboard, TagDashboardCreate, TagDashboardUpdate } from '@nexumi/shared';
|
||||
import type { Tag } from '@prisma/client';
|
||||
import type { TagDashboard, TagDashboardCreate, TagDashboardUpdate, WelcomeEmbed } from '@nexumi/shared';
|
||||
import { Prisma, type Tag } from '@prisma/client';
|
||||
import { prisma } from '../prisma';
|
||||
import { assertPremiumLimit, PremiumLimitError } from '../premium';
|
||||
|
||||
@@ -15,11 +15,26 @@ export class TagPremiumError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
function parseEmbed(raw: unknown): WelcomeEmbed | null {
|
||||
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
||||
return null;
|
||||
}
|
||||
const record = raw as Record<string, unknown>;
|
||||
const title = typeof record.title === 'string' ? record.title : undefined;
|
||||
const description = typeof record.description === 'string' ? record.description : undefined;
|
||||
const color = typeof record.color === 'number' ? record.color : undefined;
|
||||
if (!title && !description && color === undefined) {
|
||||
return null;
|
||||
}
|
||||
return { title, description, color };
|
||||
}
|
||||
|
||||
function toDashboard(tag: Tag): TagDashboard {
|
||||
return {
|
||||
id: tag.id,
|
||||
name: tag.name,
|
||||
content: tag.content,
|
||||
embed: parseEmbed(tag.embed),
|
||||
responseType: tag.responseType as TagDashboard['responseType'],
|
||||
triggerWord: tag.triggerWord,
|
||||
allowedRoleIds: tag.allowedRoleIds,
|
||||
@@ -53,6 +68,10 @@ export async function createTag(
|
||||
guildId,
|
||||
name: input.name,
|
||||
content: input.content ?? null,
|
||||
embed:
|
||||
input.embed === undefined || input.embed === null
|
||||
? Prisma.JsonNull
|
||||
: (input.embed as Prisma.InputJsonValue),
|
||||
responseType: input.responseType,
|
||||
triggerWord: input.triggerWord ?? null,
|
||||
allowedRoleIds: input.allowedRoleIds,
|
||||
@@ -85,6 +104,9 @@ export async function updateTag(
|
||||
data: {
|
||||
...(patch.name !== undefined ? { name: patch.name } : {}),
|
||||
...(patch.content !== undefined ? { content: patch.content } : {}),
|
||||
...(patch.embed !== undefined
|
||||
? { embed: patch.embed === null ? Prisma.JsonNull : (patch.embed as Prisma.InputJsonValue) }
|
||||
: {}),
|
||||
...(patch.responseType !== undefined ? { responseType: patch.responseType } : {}),
|
||||
...(patch.triggerWord !== undefined ? { triggerWord: patch.triggerWord } : {}),
|
||||
...(patch.allowedRoleIds !== undefined ? { allowedRoleIds: patch.allowedRoleIds } : {}),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { WelcomeConfigDashboard, WelcomeConfigDashboardPatch } from '@nexumi/shared';
|
||||
import type { WelcomeConfigDashboard, WelcomeConfigDashboardPatch, WelcomeEmbed } from '@nexumi/shared';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { prisma } from '../prisma';
|
||||
|
||||
@@ -11,6 +11,20 @@ async function ensureWelcomeConfig(guildId: string) {
|
||||
});
|
||||
}
|
||||
|
||||
function parseEmbed(raw: unknown): WelcomeEmbed | null {
|
||||
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
||||
return null;
|
||||
}
|
||||
const record = raw as Record<string, unknown>;
|
||||
const title = typeof record.title === 'string' ? record.title : undefined;
|
||||
const description = typeof record.description === 'string' ? record.description : undefined;
|
||||
const color = typeof record.color === 'number' ? record.color : undefined;
|
||||
if (!title && !description && color === undefined) {
|
||||
return null;
|
||||
}
|
||||
return { title, description, color };
|
||||
}
|
||||
|
||||
function toDashboard(config: Awaited<ReturnType<typeof ensureWelcomeConfig>>): WelcomeConfigDashboard {
|
||||
return {
|
||||
welcomeEnabled: config.welcomeEnabled,
|
||||
@@ -19,9 +33,9 @@ function toDashboard(config: Awaited<ReturnType<typeof ensureWelcomeConfig>>): W
|
||||
leaveChannelId: config.leaveChannelId ?? '',
|
||||
welcomeType: config.welcomeType as WelcomeConfigDashboard['welcomeType'],
|
||||
welcomeContent: config.welcomeContent,
|
||||
welcomeEmbed: (config.welcomeEmbed as Record<string, unknown> | null) ?? null,
|
||||
welcomeEmbed: parseEmbed(config.welcomeEmbed),
|
||||
leaveContent: config.leaveContent,
|
||||
leaveEmbed: (config.leaveEmbed as Record<string, unknown> | null) ?? null,
|
||||
leaveEmbed: parseEmbed(config.leaveEmbed),
|
||||
welcomeDmEnabled: config.welcomeDmEnabled,
|
||||
welcomeDmContent: config.welcomeDmContent,
|
||||
userAutoroleIds: config.userAutoroleIds,
|
||||
|
||||
Reference in New Issue
Block a user