Refactor embed handling and enhance user experience across components

- Integrated the new `buildEmbedFromPayload` function in Scheduler, Tags, and Welcome components to streamline embed creation and management.
- Updated validation schemas to require embed content checks, ensuring robust data integrity for embeds.
- Enhanced localization files to include new placeholder descriptions and improve user guidance for embed fields.
- Refactored embed parsing logic to utilize the `WelcomeEmbedSchema`, improving consistency and validation across the application.
This commit is contained in:
TheOnlyMace
2026-07-22 22:30:46 +02:00
parent e7a3162494
commit 95eed45ec4
19 changed files with 500 additions and 146 deletions

View File

@@ -1,4 +1,9 @@
import type { ScheduledMessageDashboard, ScheduledMessageDashboardCreate, WelcomeEmbed } from '@nexumi/shared';
import {
WelcomeEmbedSchema,
type ScheduledMessageDashboard,
type ScheduledMessageDashboardCreate,
type WelcomeEmbed
} from '@nexumi/shared';
import { Prisma, type ScheduledMessage } from '@prisma/client';
import { prisma } from '../prisma';
import { getScheduleQueue } from '../queues';
@@ -10,17 +15,8 @@ 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 };
const parsed = WelcomeEmbedSchema.safeParse(raw);
return parsed.success ? parsed.data : null;
}
function toDashboard(schedule: ScheduledMessage): ScheduledMessageDashboard {

View File

@@ -1,4 +1,10 @@
import type { TagDashboard, TagDashboardCreate, TagDashboardUpdate, WelcomeEmbed } from '@nexumi/shared';
import {
WelcomeEmbedSchema,
type TagDashboard,
type TagDashboardCreate,
type TagDashboardUpdate,
type WelcomeEmbed
} from '@nexumi/shared';
import { Prisma, type Tag } from '@prisma/client';
import { prisma } from '../prisma';
import { assertPremiumLimit, PremiumLimitError } from '../premium';
@@ -16,17 +22,8 @@ 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 };
const parsed = WelcomeEmbedSchema.safeParse(raw);
return parsed.success ? parsed.data : null;
}
function toDashboard(tag: Tag): TagDashboard {

View File

@@ -1,4 +1,9 @@
import type { WelcomeConfigDashboard, WelcomeConfigDashboardPatch, WelcomeEmbed } from '@nexumi/shared';
import {
WelcomeEmbedSchema,
type WelcomeConfigDashboard,
type WelcomeConfigDashboardPatch,
type WelcomeEmbed
} from '@nexumi/shared';
import { Prisma } from '@prisma/client';
import { prisma } from '../prisma';
@@ -12,17 +17,8 @@ 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 };
const parsed = WelcomeEmbedSchema.safeParse(raw);
return parsed.success ? parsed.data : null;
}
function toDashboard(config: Awaited<ReturnType<typeof ensureWelcomeConfig>>): WelcomeConfigDashboard {

View File

@@ -33,7 +33,9 @@ const USER_SERVER: PlaceholderDefinition[] = [
{ token: '{user.name}', descriptionKey: 'placeholders.desc.userName' },
{ token: '{user.tag}', descriptionKey: 'placeholders.desc.userTag' },
{ token: '{user.id}', descriptionKey: 'placeholders.desc.userId' },
{ token: '{user.avatar}', descriptionKey: 'placeholders.desc.userAvatar' },
{ token: '{server}', descriptionKey: 'placeholders.desc.server' },
{ token: '{server.icon}', descriptionKey: 'placeholders.desc.serverIcon' },
{ token: '{memberCount}', descriptionKey: 'placeholders.desc.memberCount' }
];
@@ -49,7 +51,9 @@ export const PLACEHOLDER_PRESETS: Record<PlaceholderPresetId, PlaceholderDefinit
{ token: '{user.name}', descriptionKey: 'placeholders.desc.userName' },
{ token: '{user.tag}', descriptionKey: 'placeholders.desc.userTag' },
{ token: '{user.id}', descriptionKey: 'placeholders.desc.userId' },
{ token: '{user.avatar}', descriptionKey: 'placeholders.desc.userAvatar' },
{ token: '{server}', descriptionKey: 'placeholders.desc.server' },
{ token: '{server.icon}', descriptionKey: 'placeholders.desc.serverIcon' },
{ token: '{args}', descriptionKey: 'placeholders.desc.args' },
{ token: '{random:a|b|c}', descriptionKey: 'placeholders.desc.random' },
...CHANNEL_MENTIONS