audit week 1: creator ID tracking, channel-queue migration, deprecation cleanup
QUAL-006 store ticket.creatorId on creation; legacy split-pop returned the
message ID for discord-msg-* tickets, breaking transcript DM, close
log, and channel rename for context-menu-created tickets. Adds the
field to the Ticket schema and writes a one-shot backfill script
(scripts/backfill-creatorId.js, dry-run by default).
QUEUE-001 add enqueueOverwrite + enqueueTopic to services/channelQueue.js
(chain on renameChains alongside enqueueMove). Migrate handleAdd /
handleRemove / handleMove / handleTopic so permissionOverwrites,
setParent, and setTopic no longer race pending renames or sends.
handleMove now uses the existing enqueueMove. Initial overwrites in
handleTicketModal stay inline; channel doesn't exist yet so no race.
DISCORD-001 replace ephemeral: true with flags: MessageFlags.Ephemeral across
broccolini-discord.js, handlers/sharedHelpers.js, handlers/buttons.js,
handlers/commands.js. runDeferred opts now take { flags } directly.
SEC-003 /gmailpoll min interval is 30s. Drop the 5s/10s slash-command
choices and clamp Math.max(30000, ms) in handleGmailPoll for
defense in depth.
QUAL-001 upgrade silent .catch(() => {}) on the lastActivity updateOne in
handlers/messages.js to log via logError, so transient Mongo errors
surface in the debug channel instead of disappearing.
QUAL-002 drop await from logError/logWarn calls in services/staffThread.js
and services/pinMessage.js — fire-and-forget per CLAUDE.md hard rule.
QUAL-003 wrap stray setTimeouts (handleConfirmCloseRequest force-close timer,
runFinalClose channel-delete + overflow-cleanup, checkAutoClose
delete-after-email) in trackTimeout via lazy require so they clear
on shutdown.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
* Both handlers/commands.js and handlers/buttons.js use these to avoid
|
||||
* repeating the lookup-and-defer-and-try-catch pattern across 30+ branches.
|
||||
*/
|
||||
const { MessageFlags } = require('discord.js');
|
||||
const { mongoose } = require('../db-connection');
|
||||
const { logError } = require('../services/debugLog');
|
||||
|
||||
@@ -20,7 +21,7 @@ const Ticket = mongoose.model('Ticket');
|
||||
async function findTicketForChannel(interaction, missingMessage = 'This channel is not linked to a ticket.') {
|
||||
const ticket = await Ticket.findOne({ discordThreadId: interaction.channel.id }).lean();
|
||||
if (!ticket) {
|
||||
await interaction.reply({ content: missingMessage, ephemeral: true });
|
||||
await interaction.reply({ content: missingMessage, flags: MessageFlags.Ephemeral });
|
||||
return null;
|
||||
}
|
||||
return ticket;
|
||||
@@ -34,18 +35,18 @@ async function findTicketForChannel(interaction, missingMessage = 'This channel
|
||||
* @param {import('discord.js').Interaction} interaction
|
||||
* @param {string} verb
|
||||
* @param {() => Promise<void>} fn
|
||||
* @param {{ ephemeral?: boolean }} [opts]
|
||||
* @param {{ flags?: number }} [opts] - pass `MessageFlags.Ephemeral` for ephemeral defer
|
||||
*/
|
||||
async function runDeferred(interaction, verb, fn, { ephemeral = false } = {}) {
|
||||
async function runDeferred(interaction, verb, fn, { flags } = {}) {
|
||||
try {
|
||||
await interaction.deferReply({ ephemeral });
|
||||
await interaction.deferReply(flags ? { flags } : {});
|
||||
await fn();
|
||||
} catch (err) {
|
||||
console.error(`${verb} error:`, err);
|
||||
logError(verb, err, interaction).catch(() => {});
|
||||
const msg = `Failed to ${verb} this ticket.`;
|
||||
await interaction.editReply({ content: msg }).catch(() =>
|
||||
interaction.followUp({ content: msg, ephemeral: true }).catch(() => {})
|
||||
interaction.followUp({ content: msg, flags: MessageFlags.Ephemeral }).catch(() => {})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user