The 1028-line handlers/commands.js bundled escalation logic + force-close
flow + /response tag CRUD + /panel + /signature + context-menu handlers +
several config-toggle slash commands. After the dispatch-table refactor it
was still a god module. Split into handlers/commands/ with one file per
topic; require('./commands') resolves to handlers/commands/index.js
(handlers/commands.js is removed).
Layout:
helpers.js — requireStaffRole, fetchLoggingChannel
(cross-submodule, kept here to avoid cycles with index.js)
escalation.js — runEscalation, runDeescalation, handleEscalate, handleDeescalate
(run* are still exported via index.js for handlers/buttons.js)
close.js — handleForceClose, handleCancelClose, handleCloseTimer
+ finalizeForceClose / postTranscript (timer callback)
response.js — handleResponse + send/create/edit/delete/list subcommands
+ handleAutocomplete (only /response autocompletes)
panel.js — handlePanel, buildPanelButtonRow, handleSignature
contextMenu.js — handleCreateTicketFromMessage, handleViewUserTickets
index.js — dispatch tables, handleCommand/handleContextMenu, plus the
short-and-not-thematic handlers (notifydm, add, remove,
transfer, move, topic, staffthread, pinmessages, gmailpoll,
help) and the public re-exports.
No behavior change — every imported name, every Discord call, every DB
write, every embed, every reply payload preserved verbatim. Public surface
of require('./commands') is still { handleCommand, handleContextMenu,
handleAutocomplete, runEscalation, runDeescalation }.
Largest single module is now index.js at 299 lines; others are 33–214.
34 lines
1.3 KiB
JavaScript
34 lines
1.3 KiB
JavaScript
/**
|
|
* Cross-submodule helpers for handlers/commands/*.
|
|
*
|
|
* Lives at this level (not in index.js) so escalation.js, close.js, etc. can
|
|
* import without creating circular dependencies with index.js.
|
|
*/
|
|
const { MessageFlags } = require('discord.js');
|
|
const { CONFIG } = require('../../config');
|
|
const { isStaff } = require('../../utils');
|
|
|
|
/**
|
|
* Reply ephemeral and return true if the interaction is in a guild and the
|
|
* user is not staff (so the caller should bail).
|
|
*/
|
|
async function requireStaffRole(interaction) {
|
|
if (!interaction.guild) return false;
|
|
if (!CONFIG.ROLE_ID_TO_PING && (!CONFIG.ADDITIONAL_STAFF_ROLES || CONFIG.ADDITIONAL_STAFF_ROLES.length === 0)) return false;
|
|
if (isStaff(interaction.member)) return false;
|
|
const roleMention = CONFIG.ROLE_ID_TO_PING ? `<@&${CONFIG.ROLE_ID_TO_PING}>` : 'support';
|
|
await interaction.reply({
|
|
content: `This command is only available to the support team (${roleMention}).`,
|
|
flags: MessageFlags.Ephemeral
|
|
});
|
|
return true;
|
|
}
|
|
|
|
/** Fetch the configured logging channel, or null if unset/missing. */
|
|
async function fetchLoggingChannel(client) {
|
|
if (!CONFIG.LOGGING_CHANNEL_ID) return null;
|
|
return client.channels.fetch(CONFIG.LOGGING_CHANNEL_ID).catch(() => null);
|
|
}
|
|
|
|
module.exports = { requireStaffRole, fetchLoggingChannel };
|