buttons: allow non-staff to close tickets (countdown still applies)
After the previous TICKET_BUTTON_HANDLERS gate, ticket creators and /add'd members were locked out of every ticket button — including close_ticket on their own ticket. Add a PUBLIC_TICKET_BUTTONS set so the close flow (close_ticket / confirm_close / confirm_close_with_email / confirm_close_no_email / cancel_close) skips the staff check. Claim, escalate, and de-escalate remain staff-only. The 60s FORCE_CLOSE_TIMER countdown, the transcript archive, and the optional customer-closure email all continue to fire on the existing runFinalClose path — nothing about the close behavior changes, only who is allowed to click the button. cancel_close is intentionally public too: anyone in the channel can abort a pending close, including the original setter, staff, or the creator. The pendingCloses entry stores who set it, but the abort path doesn't gate on that — kept permissive to match the rest of the close flow.
This commit is contained in:
@@ -732,6 +732,20 @@ const TICKET_BUTTON_HANDLERS = {
|
||||
deescalate_ticket: handleDeescalateButton
|
||||
};
|
||||
|
||||
/**
|
||||
* TICKET_BUTTON_HANDLERS entries that any user with channel access may
|
||||
* invoke — not just staff. Ticket creators and /add'd users get to close
|
||||
* their own ticket (with the 60s countdown still in place) and cancel a
|
||||
* pending close. Claim/escalate/de-escalate stay staff-only.
|
||||
*/
|
||||
const PUBLIC_TICKET_BUTTONS = new Set([
|
||||
'close_ticket',
|
||||
'confirm_close',
|
||||
'confirm_close_with_email',
|
||||
'confirm_close_no_email',
|
||||
'cancel_close'
|
||||
]);
|
||||
|
||||
async function handleButton(interaction) {
|
||||
const { customId } = interaction;
|
||||
|
||||
@@ -757,13 +771,12 @@ async function handleButton(interaction) {
|
||||
const ticketHandler = TICKET_BUTTON_HANDLERS[customId];
|
||||
if (!ticketHandler) return;
|
||||
|
||||
// Every TICKET_BUTTON_HANDLERS entry mutates ticket state
|
||||
// (claim/close/confirm_close*/cancel_close/escalate*/deescalate). The slash
|
||||
// command dispatcher in handlers/commands/index.js gates these via
|
||||
// requireStaffRole; the button dispatcher must do the same — non-staff
|
||||
// members with view access to the ticket channel (creator, /add'd users)
|
||||
// could otherwise click Claim, Escalate, Close, etc.
|
||||
if (await requireStaffRole(interaction)) return;
|
||||
// Claim / escalate / de-escalate mutate staff-owned ticket state and stay
|
||||
// staff-only. Close-related buttons (close_ticket, confirm_close*,
|
||||
// cancel_close) are public so a ticket creator can close their own ticket;
|
||||
// the 60s force-close countdown still applies, and the cancel button is
|
||||
// intentionally visible to anyone in the channel so any party can abort.
|
||||
if (!PUBLIC_TICKET_BUTTONS.has(customId) && (await requireStaffRole(interaction))) return;
|
||||
|
||||
const ticket = await findTicketForChannel(
|
||||
interaction,
|
||||
|
||||
Reference in New Issue
Block a user