Dynamic overflow categories
This commit is contained in:
@@ -13,7 +13,7 @@ const {
|
||||
const { mongoose } = require('../db-connection');
|
||||
const { CONFIG, TICKET_TAGS } = require('../config');
|
||||
const { getPriorityEmoji, getPriorityColor, replaceVariables, escapeRegex } = require('../utils');
|
||||
const { canRename, makeTicketName, pickTicketCategoryId, createDiscordTicketAsThread, checkTicketCreationRateLimit } = require('../services/tickets');
|
||||
const { canRename, makeTicketName, getOrCreateTicketCategory, createDiscordTicketAsThread, checkTicketCreationRateLimit } = require('../services/tickets');
|
||||
const { sendTicketNotificationEmail } = require('../services/gmail');
|
||||
const { getTicketActionRow } = require('../utils/ticketComponents');
|
||||
const { getEmailRouting } = require('../services/guildSettings');
|
||||
@@ -118,7 +118,7 @@ async function runEscalation(interaction, ticket, nextTier, reason) {
|
||||
const pendingEmbed = new EmbedBuilder()
|
||||
.setDescription('Ticket will be escalated in a few seconds.')
|
||||
.setColor(CONFIG.EMBED_COLOR_INFO);
|
||||
await interaction.reply({ content: null, embeds: [pendingEmbed] });
|
||||
await interaction.editReply({ embeds: [pendingEmbed] });
|
||||
|
||||
const creatorId = isDiscordTicket
|
||||
? (ticket.gmailThreadId.split('-').pop() || '').trim()
|
||||
@@ -228,10 +228,7 @@ async function runDeescalation(interaction, ticket) {
|
||||
.setColor(0x00BFFF)
|
||||
.setTitle(`✅ De-escalated to ${tierLabel} Support`)
|
||||
.setFooter({ text: interaction.member?.displayName || interaction.user.username });
|
||||
await interaction.reply({
|
||||
embeds: [deescalateEmbed],
|
||||
ephemeral: true
|
||||
});
|
||||
await interaction.editReply({ embeds: [deescalateEmbed] });
|
||||
|
||||
const logChan = await interaction.client.channels.fetch(CONFIG.LOG_CHAN).catch(() => null);
|
||||
if (logChan) {
|
||||
@@ -316,6 +313,7 @@ async function handleCommand(interaction) {
|
||||
}
|
||||
|
||||
try {
|
||||
await interaction.deferReply();
|
||||
await runEscalation(interaction, ticket, nextTier, reason);
|
||||
if (action === 'unclaim') {
|
||||
await Ticket.updateOne(
|
||||
@@ -325,7 +323,9 @@ async function handleCommand(interaction) {
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Escalate error:', err);
|
||||
await interaction.reply({ content: 'Failed to escalate this ticket.', ephemeral: true });
|
||||
await interaction.editReply({ content: 'Failed to escalate this ticket.' }).catch(() =>
|
||||
interaction.followUp({ content: 'Failed to escalate this ticket.', ephemeral: true }).catch(() => {})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,10 +357,13 @@ async function handleCommand(interaction) {
|
||||
}
|
||||
|
||||
try {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
await runDeescalation(interaction, ticket);
|
||||
} catch (err) {
|
||||
console.error('Deescalate error:', err);
|
||||
await interaction.reply({ content: 'Failed to deescalate this ticket.', ephemeral: true });
|
||||
await interaction.editReply({ content: 'Failed to deescalate this ticket.' }).catch(() =>
|
||||
interaction.followUp({ content: 'Failed to deescalate this ticket.', ephemeral: true }).catch(() => {})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1044,35 +1047,49 @@ async function handleContextMenu(interaction) {
|
||||
const ticketNumber = (lastTicket?.ticketNumber || 0) + 1;
|
||||
|
||||
let channel;
|
||||
let parentCategoryIdForTicket = null;
|
||||
if (CONFIG.DISCORD_THREAD_CHANNEL_ID) {
|
||||
try {
|
||||
channel = await createDiscordTicketAsThread(guild, ticketNumber, message.author.id);
|
||||
parentCategoryIdForTicket = channel.parent?.parentId ?? null;
|
||||
} catch (err) {
|
||||
console.error('Discord ticket thread create (from message) failed:', err.message);
|
||||
return interaction.editReply('❌ Could not create ticket thread. Check DISCORD_THREAD_CHANNEL_ID.');
|
||||
}
|
||||
} else {
|
||||
const categoryIds = [CONFIG.DISCORD_TICKET_CATEGORY_ID, ...(CONFIG.DISCORD_TICKET_OVERFLOW_CATEGORY_IDS || [])];
|
||||
const parentId = pickTicketCategoryId(guild, categoryIds);
|
||||
if (!parentId) {
|
||||
return interaction.editReply('❌ Discord ticket category not found or all categories full (50 channels max). Contact an administrator.');
|
||||
let parentId;
|
||||
try {
|
||||
parentId = await getOrCreateTicketCategory(
|
||||
guild,
|
||||
CONFIG.DISCORD_TICKET_CATEGORY_ID,
|
||||
CONFIG.TICKET_CATEGORY_NAME
|
||||
);
|
||||
} catch (err) {
|
||||
console.error('getOrCreateTicketCategory (context menu ticket):', err);
|
||||
return interaction.editReply('❌ Discord ticket category could not be resolved. Contact an administrator.');
|
||||
}
|
||||
parentCategoryIdForTicket = parentId;
|
||||
try {
|
||||
channel = await guild.channels.create({
|
||||
name: `ticket-${ticketNumber}`,
|
||||
type: ChannelType.GuildText,
|
||||
parent: parentId,
|
||||
permissionOverwrites: [
|
||||
{ id: guild.id, deny: [PermissionFlagsBits.ViewChannel] },
|
||||
{
|
||||
id: message.author.id,
|
||||
allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages, PermissionFlagsBits.ReadMessageHistory]
|
||||
},
|
||||
{
|
||||
id: CONFIG.ROLE_ID_TO_PING,
|
||||
allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages, PermissionFlagsBits.ReadMessageHistory]
|
||||
}
|
||||
]
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('guild.channels.create (context menu ticket):', err);
|
||||
return interaction.editReply('❌ Failed to create ticket channel. Contact an administrator.');
|
||||
}
|
||||
channel = await guild.channels.create({
|
||||
name: `ticket-${ticketNumber}`,
|
||||
type: ChannelType.GuildText,
|
||||
parent: parentId,
|
||||
permissionOverwrites: [
|
||||
{ id: guild.id, deny: [PermissionFlagsBits.ViewChannel] },
|
||||
{
|
||||
id: message.author.id,
|
||||
allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages, PermissionFlagsBits.ReadMessageHistory]
|
||||
},
|
||||
{
|
||||
id: CONFIG.ROLE_ID_TO_PING,
|
||||
allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages, PermissionFlagsBits.ReadMessageHistory]
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
const gmailThreadId = `discord-msg-${Date.now()}-${message.id}`;
|
||||
@@ -1086,7 +1103,8 @@ async function handleContextMenu(interaction) {
|
||||
status: 'open',
|
||||
ticketNumber,
|
||||
priority: 'normal',
|
||||
lastActivity: now
|
||||
lastActivity: now,
|
||||
parentCategoryId: parentCategoryIdForTicket
|
||||
});
|
||||
|
||||
const welcomeEmbed = new EmbedBuilder()
|
||||
|
||||
Reference in New Issue
Block a user