feat(tickets): retry sending messages if they fail
vi v@vt3e.cat
Mon, 02 Mar 2026 22:09:23 +0000
1 files changed,
86 insertions(+),
48 deletions(-)
M
src/interactions/commands/tickets/actions.ts
→
src/interactions/commands/tickets/actions.ts
@@ -216,65 +216,103 @@
const publicMessage = await getTicketContainer(ticket, "closed", true); const staffMessage = await getTicketContainer(ticket, "closed", false); - // send message to the author - try { - const thankYou = new ActionRowBuilder<ButtonBuilder>().addComponents( - new ButtonBuilder() - .setCustomId(`ticket:thank:${ticket.id}`) - .setLabel("Thank your moderator") - .setEmoji("💖") - .setStyle(ButtonStyle.Primary), - ); + const retry = async (fn: () => Promise<void>, label: string) => { + const maxRetries = 5; + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + await fn(); + return; + } catch (error) { + logger.error( + error, + `Attempt ${attempt}/${maxRetries} failed for ${label}`, + ); + if (attempt === maxRetries) { + throw error; + } + } + } + }; - publicMessage.container.addActionRowComponents(thankYou); + const messageAuthor = async () => { + try { + const thankYou = new ActionRowBuilder<ButtonBuilder>().addComponents( + new ButtonBuilder() + .setCustomId(`ticket:thank:${ticket.id}`) + .setLabel("Thank your moderator") + .setEmoji("💖") + .setStyle(ButtonStyle.Primary), + ); - await author.send({ - components: [publicMessage.container], - flags: ["IsComponentsV2"], - files: publicMessage.files, - allowedMentions: { - users: [], - }, - }); - } catch (error) { - logger.error( - error, - `Could not send DM to user ${ticket.authorId} for closed ticket ${ticket.id}`, - ); - } + publicMessage.container.addActionRowComponents(thankYou); - // send message to transcript channel - try { - if (!transcriptChannelId) { - logger.warn( - `No transcript channel configured for guild ${interaction.guildId}, skipping transcript post`, + await author.send({ + components: [publicMessage.container], + flags: ["IsComponentsV2"], + files: publicMessage.files, + allowedMentions: { + users: [], + }, + }); + } catch (error) { + logger.error( + error, + `Could not send DM to user ${ticket.authorId} for closed ticket ${ticket.id}`, ); - return; } - const transcriptChannel = await client.channels.fetch(transcriptChannelId); - if (!transcriptChannel || !("send" in transcriptChannel)) { - logger.warn( - `Transcript channel with ID ${transcriptChannelId} not found or is not a text channel`, + }; + + const sendToStaff = async () => { + try { + if (!transcriptChannelId) { + logger.warn( + `No transcript channel configured for guild ${interaction.guildId}, skipping transcript post`, + ); + return; + } + const transcriptChannel = + await client.channels.fetch(transcriptChannelId); + if (!transcriptChannel || !("send" in transcriptChannel)) { + logger.warn( + `Transcript channel with ID ${transcriptChannelId} not found or is not a text channel`, + ); + return; + } + + await transcriptChannel.send({ + components: [staffMessage.container], + flags: ["IsComponentsV2"], + files: staffMessage.files, + allowedMentions: { + users: [], + }, + }); + } catch (error) { + logger.error( + error, + `Could not send ticket transcript to transcript channel ${transcriptChannelId} for ticket ${ticket.id}`, ); - return; + await interaction.followUp({ + content: + "⚠️ Ticket closed but failed to send transcript to transcript channel.", + }); } + }; - await transcriptChannel.send({ - components: [staffMessage.container], - flags: ["IsComponentsV2"], - files: staffMessage.files, - allowedMentions: { - users: [], - }, - }); - } catch (error) { - logger.error( - error, - `Could not send ticket transcript to transcript channel ${transcriptChannelId} for ticket ${ticket.id}`, + try { + await retry( + messageAuthor, + `DM user ${ticket.authorId} for ticket ${ticket.id}`, + ); + await retry( + sendToStaff, + `send transcript to channel ${transcriptChannelId} for ticket ${ticket.id}`, ); + } catch (error) { + logger.error(error, `Failed after all retries for ticket ${ticket.id}`); await interaction.followUp({ content: - "⚠️ Ticket closed but failed to send transcript to transcript channel.", + "⚠️ Ticket closed but failed to send transcript/notification after multiple attempts.", }); } }