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
|
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) {
|
async function handleButton(interaction) {
|
||||||
const { customId } = interaction;
|
const { customId } = interaction;
|
||||||
|
|
||||||
@@ -757,13 +771,12 @@ async function handleButton(interaction) {
|
|||||||
const ticketHandler = TICKET_BUTTON_HANDLERS[customId];
|
const ticketHandler = TICKET_BUTTON_HANDLERS[customId];
|
||||||
if (!ticketHandler) return;
|
if (!ticketHandler) return;
|
||||||
|
|
||||||
// Every TICKET_BUTTON_HANDLERS entry mutates ticket state
|
// Claim / escalate / de-escalate mutate staff-owned ticket state and stay
|
||||||
// (claim/close/confirm_close*/cancel_close/escalate*/deescalate). The slash
|
// staff-only. Close-related buttons (close_ticket, confirm_close*,
|
||||||
// command dispatcher in handlers/commands/index.js gates these via
|
// cancel_close) are public so a ticket creator can close their own ticket;
|
||||||
// requireStaffRole; the button dispatcher must do the same — non-staff
|
// the 60s force-close countdown still applies, and the cancel button is
|
||||||
// members with view access to the ticket channel (creator, /add'd users)
|
// intentionally visible to anyone in the channel so any party can abort.
|
||||||
// could otherwise click Claim, Escalate, Close, etc.
|
if (!PUBLIC_TICKET_BUTTONS.has(customId) && (await requireStaffRole(interaction))) return;
|
||||||
if (await requireStaffRole(interaction)) return;
|
|
||||||
|
|
||||||
const ticket = await findTicketForChannel(
|
const ticket = await findTicketForChannel(
|
||||||
interaction,
|
interaction,
|
||||||
|
|||||||
Reference in New Issue
Block a user