Skip to content

Commit 318fa9e

Browse files
committed
Fix ticket close permission checks and error replies.
Import missing permission helpers, always surface permission failures to users, and log the actual user-facing message.
1 parent 5e13028 commit 318fa9e

4 files changed

Lines changed: 26 additions & 28 deletions

File tree

src/commands/Ticket/close.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { getColor } from '../../config/bot.js';
22
import { SlashCommandBuilder, PermissionFlagsBits, ChannelType, MessageFlags } from 'discord.js';
33
import { successEmbed } from '../../utils/embeds.js';
44
import { logger } from '../../utils/logger.js';
5-
import { handleInteractionError } from '../../utils/errorHandler.js';
5+
import { handleInteractionError, replyUserError, ErrorTypes } from '../../utils/errorHandler.js';
66
import { InteractionHelper } from '../../utils/interactionHelper.js';
77
import { getTicketPermissionContext } from '../../utils/ticketPermissions.js';
88
import { closeTicket } from '../../services/ticket.js';
@@ -49,7 +49,7 @@ export default {
4949
guildId: interaction.guildId,
5050
error: result.error
5151
});
52-
return await replyUserError(interaction, { type: ErrorTypes.UNKNOWN, message: 'result.error || "This command can only be used in a valid ticket channel."' });
52+
return await replyUserError(interaction, { type: ErrorTypes.UNKNOWN, message: result.error || 'This command can only be used in a valid ticket channel.' });
5353
}
5454

5555
await InteractionHelper.safeEditReply(interaction, {

src/handlers/ticketButtons.js

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { logger } from '../utils/logger.js';
77
import { InteractionHelper } from '../utils/interactionHelper.js';
88
import { checkRateLimit } from '../utils/rateLimiter.js';
99
import { replyUserError, ErrorTypes } from '../utils/errorHandler.js';
10+
import { getTicketPermissionContext } from '../utils/ticketPermissions.js';
1011

1112
function escapeHtml(text) {
1213
if (!text) return '';
@@ -30,6 +31,17 @@ async function ensureGuildContext(interaction) {
3031
return false;
3132
}
3233

34+
async function replyPermissionCheckFailure(interaction, permissionCheck) {
35+
let type = ErrorTypes.UNKNOWN;
36+
if (permissionCheck.error === 'Permission Denied') {
37+
type = ErrorTypes.PERMISSION;
38+
} else if (permissionCheck.error === 'Request Timeout') {
39+
type = ErrorTypes.RATE_LIMIT;
40+
}
41+
42+
await replyUserError(interaction, { type, message: permissionCheck.details });
43+
}
44+
3345
async function checkTicketPermissionWithTimeout(interaction, client, actionLabel, options = {}, timeoutMs = 2500) {
3446
const { allowTicketCreator = false } = options;
3547

@@ -185,9 +197,7 @@ const closeTicketHandler = {
185197
);
186198

187199
if (!permissionCheck.success) {
188-
if (!interaction.replied && !interaction.deferred) {
189-
await replyUserError(interaction, { type: ErrorTypes.PERMISSION, message: permissionCheck.details });
190-
}
200+
await replyPermissionCheckFailure(interaction, permissionCheck);
191201
return;
192202
}
193203

@@ -232,9 +242,7 @@ const closeTicketModalHandler = {
232242
);
233243

234244
if (!permissionCheck.success) {
235-
if (!interaction.replied && !interaction.deferred) {
236-
await replyUserError(interaction, { type: ErrorTypes.PERMISSION, message: permissionCheck.details });
237-
}
245+
await replyPermissionCheckFailure(interaction, permissionCheck);
238246
return;
239247
}
240248

@@ -280,9 +288,7 @@ const claimTicketHandler = {
280288
);
281289

282290
if (!permissionCheck.success) {
283-
if (!interaction.replied && !interaction.deferred) {
284-
await replyUserError(interaction, { type: ErrorTypes.PERMISSION, message: permissionCheck.details });
285-
}
291+
await replyPermissionCheckFailure(interaction, permissionCheck);
286292
return;
287293
}
288294

@@ -325,9 +331,7 @@ const priorityTicketHandler = {
325331
);
326332

327333
if (!permissionCheck.success) {
328-
if (!interaction.replied && !interaction.deferred) {
329-
await replyUserError(interaction, { type: ErrorTypes.PERMISSION, message: permissionCheck.details });
330-
}
334+
await replyPermissionCheckFailure(interaction, permissionCheck);
331335
return;
332336
}
333337

@@ -376,9 +380,7 @@ const pinTicketHandler = {
376380
);
377381

378382
if (!permissionCheck.success) {
379-
if (!interaction.replied && !interaction.deferred) {
380-
await replyUserError(interaction, { type: ErrorTypes.PERMISSION, message: permissionCheck.details });
381-
}
383+
await replyPermissionCheckFailure(interaction, permissionCheck);
382384
return;
383385
}
384386

@@ -485,9 +487,7 @@ const unclaimTicketHandler = {
485487
);
486488

487489
if (!permissionCheck.success) {
488-
if (!interaction.replied && !interaction.deferred) {
489-
await replyUserError(interaction, { type: ErrorTypes.PERMISSION, message: permissionCheck.details });
490-
}
490+
await replyPermissionCheckFailure(interaction, permissionCheck);
491491
return;
492492
}
493493

@@ -531,9 +531,7 @@ const reopenTicketHandler = {
531531
);
532532

533533
if (!permissionCheck.success) {
534-
if (!interaction.replied && !interaction.deferred) {
535-
await replyUserError(interaction, { type: ErrorTypes.PERMISSION, message: permissionCheck.details });
536-
}
534+
await replyPermissionCheckFailure(interaction, permissionCheck);
537535
return;
538536
}
539537

@@ -582,9 +580,7 @@ const deleteTicketHandler = {
582580
);
583581

584582
if (!permissionCheck.success) {
585-
if (!interaction.replied && !interaction.deferred) {
586-
await replyUserError(interaction, { type: ErrorTypes.PERMISSION, message: permissionCheck.details });
587-
}
583+
await replyPermissionCheckFailure(interaction, permissionCheck);
588584
return;
589585
}
590586

src/utils/errorHandler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ function logInteractionError(error, errorType, logData) {
193193

194194
if (isUserError || isExpectedError) {
195195
if (errorType !== ErrorTypes.RATE_LIMIT) {
196-
logger.debug(`User Error [${errorType.toUpperCase()}]: ${error.message}`, logData);
196+
logger.debug(`User Error [${errorType.toUpperCase()}]: ${error.userMessage || error.message}`, logData);
197197
}
198198
} else {
199199
logger.error(`System Error [${errorType.toUpperCase()}]`, {

src/utils/ticketPermissions.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ export async function getTicketPermissionContext({ client, interaction }) {
1616
const hasManageChannels = interaction.member.permissions.has(PermissionFlagsBits.ManageChannels);
1717
const staffRoleId = config.ticketStaffRoleId || null;
1818
const hasTicketStaffRole = Boolean(staffRoleId && interaction.member.roles?.cache?.has(staffRoleId));
19-
const isTicketCreator = Boolean(ticketData?.userId && ticketData.userId === interaction.user.id);
19+
const isTicketCreator = Boolean(
20+
ticketData?.userId && String(ticketData.userId) === String(interaction.user.id),
21+
);
2022

2123
return {
2224
config,

0 commit comments

Comments
 (0)