Implement ticket panel synchronization and configuration updates

- Added `panelChannelId` and `panelMessageId` fields to the `TicketConfig` model for managing ticket panel settings.
- Introduced `syncTicketPanel` function to handle posting and updating the ticket panel in Discord channels via BullMQ.
- Enhanced error handling for ticket panel synchronization, including specific error messages for missing categories and posting failures.
- Updated WebUI components to support panel channel selection and improved error messaging for synchronization issues.
- Added localization entries for new error messages related to ticket panel synchronization in both English and German.
- Refactored ticket category management to trigger panel synchronization upon category creation, update, or deletion.
This commit is contained in:
TheOnlyMace
2026-07-25 16:06:17 +02:00
parent dba7bb3cdc
commit 1eec10ba80
19 changed files with 476 additions and 47 deletions

View File

@@ -385,6 +385,7 @@ export const TicketConfigDashboardSchema = z.object({
mode: TicketModeSchema,
categoryId: OptionalSnowflakeSchema,
logChannelId: OptionalSnowflakeSchema,
panelChannelId: OptionalSnowflakeSchema,
transcriptDm: z.boolean(),
inactivityHours: z.number().int().positive(),
ratingEnabled: z.boolean()
@@ -398,7 +399,7 @@ export const TicketCategoryDashboardSchema = z.object({
id: z.string().optional(),
name: z.string().min(1).max(100),
description: z.string().max(500).nullable().optional(),
emoji: z.string().max(32).nullable().optional(),
emoji: z.string().max(80).nullable().optional(),
supportRoleIds: z.array(z.string())
});
export type TicketCategoryDashboard = z.infer<typeof TicketCategoryDashboardSchema>;

View File

@@ -415,6 +415,7 @@ const de: Dictionary = {
'giveaway.error.invalid_duration': 'Ungültige Dauer. Nutze z. B. 1h, 2d.',
'giveaway.error.duration_too_short': 'Die Dauer muss mindestens 1 Minute betragen.',
'giveaway.error.invalid_channel': 'Ungültiger Kanal.',
'ticket.panel.defaultTitle': 'Support-Tickets',
'ticket.panel.defaultDescription': 'Wähle eine Kategorie, um ein Ticket zu öffnen.',
'ticket.panel.created': 'Ticket-Panel erstellt.',
'ticket.category.created': 'Kategorie **{name}** erstellt.',
@@ -458,6 +459,8 @@ const de: Dictionary = {
'ticket.error.no_channel': 'Ticket-Kanal nicht gefunden.',
'ticket.error.invalid_name': 'Ungültiger Name.',
'ticket.error.invalid_channel': 'Ungültiger Kanal.',
'ticket.error.missing_permission':
'Mir fehlen Berechtigungen, um das Ticket-Panel in diesem Kanal zu posten (Kanal sehen, Nachrichten senden, Embeds).',
'ticket.error.no_parent_channel': 'Kein Elternkanal für Thread-Tickets konfiguriert.',
'ticket.error.invalid_parent_channel': 'Der konfigurierte Elternkanal ist ungültig.',
'ticket.error.not_found': 'Ticket nicht gefunden.',
@@ -1010,6 +1013,7 @@ const en: Dictionary = {
'giveaway.error.invalid_duration': 'Invalid duration. Use e.g. 1h, 2d.',
'giveaway.error.duration_too_short': 'Duration must be at least 1 minute.',
'giveaway.error.invalid_channel': 'Invalid channel.',
'ticket.panel.defaultTitle': 'Support Tickets',
'ticket.panel.defaultDescription': 'Select a category to open a ticket.',
'ticket.panel.created': 'Ticket panel created.',
'ticket.category.created': 'Category **{name}** created.',
@@ -1053,6 +1057,8 @@ const en: Dictionary = {
'ticket.error.no_channel': 'Ticket channel not found.',
'ticket.error.invalid_name': 'Invalid name.',
'ticket.error.invalid_channel': 'Invalid channel.',
'ticket.error.missing_permission':
'I am missing permissions to post the ticket panel in this channel (View Channel, Send Messages, Embed Links).',
'ticket.error.no_parent_channel': 'No parent channel configured for thread tickets.',
'ticket.error.invalid_parent_channel': 'The configured parent channel is invalid.',
'ticket.error.not_found': 'Ticket not found.',