2021-10-24 22:48:25 +01:00
|
|
|
|
const Discord = require("discord.js");
|
2022-08-12 01:35:36 +01:00
|
|
|
|
|
2026-05-16 15:10:27 +01:00
|
|
|
|
const supportbot = require("../Structures/ConfigStore").supportbot;
|
|
|
|
|
|
const cmdconfig = require("../Structures/ConfigStore").commands;
|
|
|
|
|
|
const msgconfig = require("../Structures/ConfigStore").messages;
|
2021-10-24 22:48:25 +01:00
|
|
|
|
|
|
|
|
|
|
const Event = require("../Structures/Event.js");
|
2025-09-20 23:09:22 +01:00
|
|
|
|
const db = require("../Structures/Database.js");
|
2024-06-13 17:36:44 +01:00
|
|
|
|
|
2021-11-10 21:41:12 -06:00
|
|
|
|
module.exports = new Event("interactionCreate", async (client, interaction) => {
|
2024-07-09 22:49:49 +01:00
|
|
|
|
if (interaction.type === Discord.InteractionType.ApplicationCommand) {
|
2021-10-24 22:48:25 +01:00
|
|
|
|
const command = client.commands.find(
|
2026-03-10 20:02:43 +00:00
|
|
|
|
(cmd) => cmd.name.toLowerCase() === interaction.commandName,
|
2021-10-24 22:48:25 +01:00
|
|
|
|
);
|
|
|
|
|
|
|
2021-11-23 18:08:45 -06:00
|
|
|
|
if (interaction.user.bot || !interaction.guild) return;
|
2021-10-24 22:48:25 +01:00
|
|
|
|
|
2022-07-22 13:19:05 +01:00
|
|
|
|
const NotValid = new Discord.EmbedBuilder()
|
2024-07-09 22:49:49 +01:00
|
|
|
|
.setDescription(`:x: \`Invalid Command\``)
|
2022-08-12 01:35:36 +01:00
|
|
|
|
.setColor(supportbot.Embed.Colours.Error);
|
2021-10-24 22:48:25 +01:00
|
|
|
|
|
|
|
|
|
|
if (!command)
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
embeds: [NotValid],
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2021-10-24 22:48:25 +01:00
|
|
|
|
});
|
|
|
|
|
|
|
2022-02-04 17:49:02 -06:00
|
|
|
|
const permission = interaction.member.permissions.has(command.permissions);
|
2021-10-24 22:48:25 +01:00
|
|
|
|
|
2022-07-22 13:19:05 +01:00
|
|
|
|
const ValidPerms = new Discord.EmbedBuilder()
|
2021-10-24 22:48:25 +01:00
|
|
|
|
.setDescription(
|
2026-03-10 20:02:43 +00:00
|
|
|
|
"> :x: `Invalid Permissions` Do you have the correct permissions to execute this command?",
|
2021-10-24 22:48:25 +01:00
|
|
|
|
)
|
2022-08-12 01:35:36 +01:00
|
|
|
|
.setColor(supportbot.Embed.Colours.Error);
|
2021-10-24 22:48:25 +01:00
|
|
|
|
|
|
|
|
|
|
if (!permission)
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
embeds: [ValidPerms],
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2024-07-09 22:49:49 +01:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
if (
|
|
|
|
|
|
command.name === cmdconfig.OpenTicket.Command &&
|
|
|
|
|
|
supportbot.Ticket.TicketReason
|
|
|
|
|
|
) {
|
2024-07-09 22:49:49 +01:00
|
|
|
|
const modal = new Discord.ModalBuilder()
|
|
|
|
|
|
.setCustomId("ticketReasonModal")
|
|
|
|
|
|
.setTitle("Ticket Reason")
|
|
|
|
|
|
.addComponents(
|
|
|
|
|
|
new Discord.ActionRowBuilder().addComponents(
|
|
|
|
|
|
new Discord.TextInputBuilder()
|
|
|
|
|
|
.setCustomId("reasonInput")
|
|
|
|
|
|
.setLabel("Reason")
|
|
|
|
|
|
.setStyle(Discord.TextInputStyle.Paragraph)
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setRequired(true),
|
|
|
|
|
|
),
|
2024-07-09 22:49:49 +01:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
await interaction.showModal(modal);
|
|
|
|
|
|
} else {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
console.log(
|
|
|
|
|
|
"\u001b[32m",
|
|
|
|
|
|
"[Executed]",
|
|
|
|
|
|
"\u001b[37;1m",
|
|
|
|
|
|
`${interaction.user.username} has executed ${command.name}`,
|
|
|
|
|
|
);
|
2026-05-26 20:11:22 +01:00
|
|
|
|
|
2024-07-09 22:49:49 +01:00
|
|
|
|
await command.run(interaction);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("Error executing command:", error);
|
|
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
content: "An error occurred while executing the command.",
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2021-10-24 22:48:25 +01:00
|
|
|
|
});
|
2024-07-09 22:49:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (interaction.isModalSubmit()) {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
if (interaction.customId.startsWith("ticketReasonModal")) {
|
2024-07-09 22:49:49 +01:00
|
|
|
|
const reason = interaction.fields.getTextInputValue("reasonInput");
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const department = interaction.customId.includes(":")
|
|
|
|
|
|
? interaction.customId.split(":")[1]
|
|
|
|
|
|
: supportbot.Ticket.DepartmentSystem?.DefaultDepartment || "general";
|
|
|
|
|
|
|
2024-07-09 22:49:49 +01:00
|
|
|
|
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
|
2026-03-10 20:02:43 +00:00
|
|
|
|
if (!cmd) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "Open ticket command not found.",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
2024-07-09 22:49:49 +01:00
|
|
|
|
}
|
2026-03-10 20:02:43 +00:00
|
|
|
|
|
|
|
|
|
|
interaction.reason = reason;
|
|
|
|
|
|
interaction.department = department;
|
|
|
|
|
|
interaction.priority =
|
|
|
|
|
|
supportbot.Ticket.DepartmentSystem?.Departments?.[department]
|
|
|
|
|
|
?.DefaultPriority ||
|
|
|
|
|
|
supportbot.Ticket.PrioritySystem?.DefaultPriority ||
|
|
|
|
|
|
"medium";
|
|
|
|
|
|
|
|
|
|
|
|
return await cmd.run(interaction);
|
2024-07-09 22:49:49 +01:00
|
|
|
|
}
|
2021-10-24 22:48:25 +01:00
|
|
|
|
}
|
2024-06-12 12:54:31 +01:00
|
|
|
|
|
2024-10-10 19:14:45 +01:00
|
|
|
|
if (interaction.customId === "renameTicketModal") {
|
|
|
|
|
|
const newTicketName = interaction.fields.getTextInputValue("renameTicket");
|
|
|
|
|
|
const ticketChannelId = interaction.channel.id;
|
|
|
|
|
|
let ticketChannel;
|
|
|
|
|
|
if (supportbot.Ticket.TicketType === "threads") {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
ticketChannel = interaction.guild.channels.cache.get(ticketChannelId);
|
2024-10-10 19:14:45 +01:00
|
|
|
|
} else if (supportbot.Ticket.TicketType === "channels") {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
ticketChannel = interaction.guild.channels.cache.get(ticketChannelId);
|
2024-10-10 19:14:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
if (!ticketChannel) {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "Ticket channel not found.",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
2024-10-10 19:14:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
try {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
await ticketChannel.setName(newTicketName);
|
|
|
|
|
|
const renamedsuccess = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(msgconfig.Ticket.RenamedSuccess)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
embeds: [renamedsuccess],
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
2024-10-10 19:14:45 +01:00
|
|
|
|
} catch (error) {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
console.error("Error renaming the ticket:", error);
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "There was an error renaming the ticket.",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (interaction.isStringSelectMenu()) {
|
|
|
|
|
|
if (interaction.customId === "ticketdepartmentselect") {
|
|
|
|
|
|
const selectedDepartment = interaction.values[0];
|
2026-08-10 20:15:00 +01:00
|
|
|
|
const deptConfig = supportbot.Ticket?.DepartmentSystem?.Departments?.[selectedDepartment];
|
|
|
|
|
|
if (deptConfig && deptConfig.Enabled === false) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "Ticket creation for this department is currently disabled.",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-03-10 20:02:43 +00:00
|
|
|
|
|
|
|
|
|
|
if (supportbot.Ticket.TicketReason) {
|
|
|
|
|
|
const modal = new Discord.ModalBuilder()
|
|
|
|
|
|
.setCustomId(`ticketReasonModal:${selectedDepartment}`)
|
|
|
|
|
|
.setTitle("Ticket Reason")
|
|
|
|
|
|
.addComponents(
|
|
|
|
|
|
new Discord.ActionRowBuilder().addComponents(
|
|
|
|
|
|
new Discord.TextInputBuilder()
|
|
|
|
|
|
.setCustomId("reasonInput")
|
|
|
|
|
|
.setLabel("Reason")
|
|
|
|
|
|
.setStyle(Discord.TextInputStyle.Paragraph)
|
|
|
|
|
|
.setRequired(true),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
return await interaction.showModal(modal);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
|
|
|
|
|
|
if (!cmd) {
|
2024-10-10 19:14:45 +01:00
|
|
|
|
return interaction.reply({
|
2026-03-10 20:02:43 +00:00
|
|
|
|
content: "Open ticket command not found.",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2024-10-10 19:14:45 +01:00
|
|
|
|
});
|
2026-03-10 20:02:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interaction.department = selectedDepartment;
|
|
|
|
|
|
interaction.priority =
|
|
|
|
|
|
supportbot.Ticket.DepartmentSystem?.Departments?.[selectedDepartment]
|
|
|
|
|
|
?.DefaultPriority ||
|
|
|
|
|
|
supportbot.Ticket.PrioritySystem?.DefaultPriority ||
|
|
|
|
|
|
"medium";
|
|
|
|
|
|
|
|
|
|
|
|
return await cmd.run(interaction);
|
2024-10-10 19:14:45 +01:00
|
|
|
|
}
|
2025-09-22 18:36:04 +01:00
|
|
|
|
|
2024-06-12 12:54:31 +01:00
|
|
|
|
if (interaction.customId === "ticketcontrolpanel") {
|
|
|
|
|
|
const selectedOption = interaction.values[0];
|
|
|
|
|
|
const { getRole, getChannel } = interaction.client;
|
|
|
|
|
|
switch (selectedOption) {
|
|
|
|
|
|
case "ticketclose":
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const closeCommand = client.commands.get(
|
|
|
|
|
|
cmdconfig.CloseTicket.Command,
|
|
|
|
|
|
);
|
2024-06-12 12:54:31 +01:00
|
|
|
|
if (closeCommand) {
|
2024-07-09 22:49:49 +01:00
|
|
|
|
await closeCommand.run(interaction);
|
2024-06-12 12:54:31 +01:00
|
|
|
|
} else {
|
|
|
|
|
|
console.error("[X] Close Command Not Found");
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
case "supportvc":
|
|
|
|
|
|
const ticketInfo = db.getTicket(interaction.channel.id);
|
|
|
|
|
|
if (!ticketInfo) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "⚠️ This channel isn’t a valid ticket.",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2024-11-09 00:37:51 +00:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const user =
|
|
|
|
|
|
interaction.guild.members.cache.get(ticketInfo.user_id) ||
|
|
|
|
|
|
ticketInfo.user_id;
|
|
|
|
|
|
const username = user?.user?.username || "Unknown User";
|
2025-09-20 23:09:22 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const VCcategory = interaction.guild.channels.cache.find(
|
|
|
|
|
|
(c) =>
|
|
|
|
|
|
c.name === supportbot.VoiceTickets.Category ||
|
|
|
|
|
|
c.id === supportbot.VoiceTickets.Category,
|
|
|
|
|
|
);
|
2025-09-20 23:09:22 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
if (!VCcategory) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "⚠️ The Support VC category does not exist!",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2025-09-20 23:09:22 +01:00
|
|
|
|
});
|
2026-03-10 20:02:43 +00:00
|
|
|
|
}
|
2025-09-20 23:09:22 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const SupportVoice = await interaction.guild.channels.create({
|
|
|
|
|
|
name: supportbot.VoiceTickets.Name.replace(/%username%/g, username),
|
|
|
|
|
|
type: Discord.ChannelType.GuildVoice,
|
|
|
|
|
|
parent: VCcategory,
|
|
|
|
|
|
permissionOverwrites: [
|
|
|
|
|
|
{
|
|
|
|
|
|
id: interaction.guild.id,
|
|
|
|
|
|
deny: [Discord.PermissionsBitField.Flags.Connect],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: user.id || user, // works if user is a Member or just ID
|
|
|
|
|
|
allow: [
|
|
|
|
|
|
Discord.PermissionsBitField.Flags.Connect,
|
|
|
|
|
|
Discord.PermissionsBitField.Flags.Speak,
|
|
|
|
|
|
Discord.PermissionsBitField.Flags.ViewChannel,
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
});
|
2025-09-20 23:09:22 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
db.updateTicketVoice(ticketInfo.ticket_id, SupportVoice.id);
|
2025-09-20 23:09:22 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const vcmadeembed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(`> **Support VC Created:** <#${SupportVoice.id}>`)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
2025-09-20 23:09:22 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const VCDeleteButton = new Discord.ButtonBuilder()
|
|
|
|
|
|
.setCustomId("deleteSupportVC")
|
|
|
|
|
|
.setLabel(supportbot.Buttons.Voice.TicketDeleteText)
|
|
|
|
|
|
.setEmoji(supportbot.Buttons.General.Delete)
|
|
|
|
|
|
.setStyle(supportbot.Buttons.General.DeleteStyle);
|
2025-09-20 23:09:22 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const VCDeleteRow = new Discord.ActionRowBuilder().addComponents(
|
|
|
|
|
|
VCDeleteButton,
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
embeds: [vcmadeembed],
|
|
|
|
|
|
components: [VCDeleteRow],
|
|
|
|
|
|
});
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case "archiveticket":
|
|
|
|
|
|
const arcembed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(msgconfig.Ticket.TicketArchived)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
const CloseButton = new Discord.ButtonBuilder()
|
|
|
|
|
|
.setCustomId("confirmCloseTicket")
|
|
|
|
|
|
.setLabel(supportbot.Ticket.Close.Confirmation_Button)
|
|
|
|
|
|
.setEmoji(supportbot.Ticket.Close.Confirmation_Emoji)
|
|
|
|
|
|
.setStyle(supportbot.Ticket.Close.Confirmation_Style);
|
|
|
|
|
|
const unarchiveButton = new Discord.ButtonBuilder()
|
|
|
|
|
|
.setCustomId("unarchiveTicket")
|
|
|
|
|
|
.setLabel(supportbot.Buttons.Tickets.Unarchive)
|
|
|
|
|
|
.setEmoji(supportbot.Buttons.Tickets.Unarchive_Emoji)
|
|
|
|
|
|
.setStyle(supportbot.Buttons.Tickets.Unarchive_Style);
|
|
|
|
|
|
const ArchivedOptions = new Discord.ActionRowBuilder().addComponents(
|
|
|
|
|
|
CloseButton,
|
|
|
|
|
|
unarchiveButton,
|
|
|
|
|
|
);
|
|
|
|
|
|
await interaction.channel.send({
|
|
|
|
|
|
embeds: [arcembed],
|
|
|
|
|
|
components: [ArchivedOptions],
|
|
|
|
|
|
});
|
|
|
|
|
|
if (supportbot.Ticket.TicketType === "threads") {
|
|
|
|
|
|
await interaction.channel.setArchived(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (supportbot.Ticket.TicketType === "channels") {
|
|
|
|
|
|
const { getRole, getChannel } = interaction.client;
|
|
|
|
|
|
await interaction.channel.setParent(
|
|
|
|
|
|
supportbot.Ticket.TicketArchiveCategory,
|
|
|
|
|
|
);
|
|
|
|
|
|
const tickets = db.getAllTickets();
|
|
|
|
|
|
const ticketInfo = tickets.find(
|
|
|
|
|
|
(t) => t.ticket_id === interaction.channel.id,
|
|
|
|
|
|
);
|
|
|
|
|
|
if (ticketInfo) {
|
|
|
|
|
|
const user =
|
|
|
|
|
|
interaction.guild.members.cache.get(ticketInfo.user_id) ||
|
|
|
|
|
|
ticketInfo.user_id;
|
|
|
|
|
|
const claimedBy =
|
|
|
|
|
|
interaction.guild.members.cache.get(ticketInfo.claimed_by) ||
|
|
|
|
|
|
ticketInfo.claimed_by;
|
|
|
|
|
|
const Admin = await interaction.guild.roles.fetch(
|
|
|
|
|
|
supportbot.Roles.StaffMember.Admin,
|
|
|
|
|
|
);
|
|
|
|
|
|
const Staff = await interaction.guild.roles.fetch(
|
|
|
|
|
|
supportbot.Roles.StaffMember.Staff,
|
|
|
|
|
|
);
|
|
|
|
|
|
if (user && user.id) {
|
|
|
|
|
|
await interaction.channel.permissionOverwrites.edit(user.id, {
|
|
|
|
|
|
ViewChannel: false,
|
|
|
|
|
|
SendMessages: false,
|
2024-07-30 17:45:35 +01:00
|
|
|
|
});
|
2026-03-10 20:02:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (supportbot.ClaimTickets === true) {
|
|
|
|
|
|
if (claimedBy && claimedBy.id) {
|
|
|
|
|
|
await interaction.channel.permissionOverwrites.edit(
|
|
|
|
|
|
claimedBy.id,
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewChannel: true,
|
|
|
|
|
|
SendMessages: true,
|
|
|
|
|
|
ReadMessageHistory: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
2024-10-10 19:14:45 +01:00
|
|
|
|
}
|
2026-03-10 20:02:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (supportbot.ClaimTickets === false) {
|
|
|
|
|
|
if (Staff && Staff.id) {
|
|
|
|
|
|
await interaction.channel.permissionOverwrites.edit(
|
|
|
|
|
|
claimedBy.id,
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewChannel: true,
|
|
|
|
|
|
SendMessages: true,
|
|
|
|
|
|
ReadMessageHistory: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
2024-10-10 19:14:45 +01:00
|
|
|
|
}
|
2026-03-10 20:02:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (Admin && Admin.id) {
|
|
|
|
|
|
await interaction.channel.permissionOverwrites.edit(Admin.id, {
|
|
|
|
|
|
ViewChannel: true,
|
|
|
|
|
|
SendMessages: true,
|
|
|
|
|
|
ReadMessageHistory: true,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
await interaction.channel.permissionOverwrites.edit(
|
|
|
|
|
|
interaction.guild.roles.everyone.id,
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewChannel: false,
|
|
|
|
|
|
SendMessages: false,
|
|
|
|
|
|
ReadMessageHistory: false,
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case "lockticket":
|
|
|
|
|
|
const lockembed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(msgconfig.Ticket.TicketLocked)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
const unlockButton = new Discord.ButtonBuilder()
|
|
|
|
|
|
.setCustomId("unlockTicket")
|
|
|
|
|
|
.setLabel(supportbot.Buttons.Tickets.Unlock)
|
|
|
|
|
|
.setEmoji(supportbot.Buttons.Tickets.Unlock_Emoji)
|
|
|
|
|
|
.setStyle(supportbot.Buttons.Tickets.Unlock_Style);
|
|
|
|
|
|
const LockedOptions = new Discord.ActionRowBuilder().addComponents(
|
|
|
|
|
|
unlockButton,
|
|
|
|
|
|
);
|
|
|
|
|
|
await interaction.channel.send({
|
|
|
|
|
|
embeds: [lockembed],
|
|
|
|
|
|
components: [LockedOptions],
|
|
|
|
|
|
ephemeral: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
if (supportbot.Ticket.TicketType === "threads") {
|
|
|
|
|
|
await interaction.channel.setLocked(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case "unlockTicket":
|
|
|
|
|
|
const unlockEmbed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(msgconfig.Ticket.TicketUnlocked)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
await interaction.channel.send({
|
|
|
|
|
|
embeds: [unlockEmbed],
|
|
|
|
|
|
ephemeral: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
if (supportbot.Ticket.TicketType === "threads") {
|
|
|
|
|
|
await interaction.channel.setLocked(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
2024-06-12 12:54:31 +01:00
|
|
|
|
case "enableinvites":
|
|
|
|
|
|
await handleInvites(interaction, true);
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case "disableinvites":
|
|
|
|
|
|
await handleInvites(interaction, false);
|
|
|
|
|
|
break;
|
2024-10-10 19:14:45 +01:00
|
|
|
|
|
|
|
|
|
|
case "renameticket":
|
|
|
|
|
|
const modal = new Discord.ModalBuilder()
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setCustomId("renameTicketModal")
|
|
|
|
|
|
.setTitle("Rename Channel")
|
|
|
|
|
|
.addComponents(
|
|
|
|
|
|
new Discord.ActionRowBuilder().addComponents(
|
2024-10-10 19:14:45 +01:00
|
|
|
|
new Discord.TextInputBuilder()
|
|
|
|
|
|
.setCustomId("renameTicket")
|
|
|
|
|
|
.setLabel("New Channel Name")
|
|
|
|
|
|
.setStyle(Discord.TextInputStyle.Short)
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setRequired(true),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
await interaction.showModal(modal);
|
|
|
|
|
|
break;
|
2024-06-12 12:54:31 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
if (interaction.customId === "deleteSupportVC") {
|
2025-09-20 23:09:22 +01:00
|
|
|
|
const ticketData = db.getAllTickets();
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const ticketInfo = ticketData.find(
|
|
|
|
|
|
(t) => t.ticket_id === interaction.channel.id,
|
|
|
|
|
|
);
|
2024-11-09 00:37:51 +00:00
|
|
|
|
if (ticketInfo && ticketInfo.voiceChannelId) {
|
|
|
|
|
|
try {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const voiceChannel = await interaction.guild.channels
|
|
|
|
|
|
.fetch(ticketInfo.voiceChannelId)
|
|
|
|
|
|
.catch(() => null);
|
2024-11-09 00:37:51 +00:00
|
|
|
|
if (voiceChannel) {
|
|
|
|
|
|
await voiceChannel.delete();
|
|
|
|
|
|
const successEmbed = new Discord.EmbedBuilder()
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setDescription(
|
|
|
|
|
|
"✅ Support voice channel has been successfully deleted!",
|
|
|
|
|
|
)
|
2024-11-09 00:37:51 +00:00
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
embeds: [successEmbed],
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2024-11-09 00:37:51 +00:00
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const errorEmbed = new Discord.EmbedBuilder()
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setDescription(
|
|
|
|
|
|
"❌ The associated voice channel could not be found.",
|
|
|
|
|
|
)
|
2024-11-09 00:37:51 +00:00
|
|
|
|
.setColor(supportbot.Embed.Colours.Error);
|
|
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
embeds: [errorEmbed],
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2024-11-09 00:37:51 +00:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
console.error("Error deleting the Voice Channel:", error);
|
2024-11-09 00:37:51 +00:00
|
|
|
|
const errorEmbed = new Discord.EmbedBuilder()
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setDescription(
|
|
|
|
|
|
"❌ **There was an error trying to delete this voice channel. Please try again later.**",
|
|
|
|
|
|
)
|
2024-11-09 00:37:51 +00:00
|
|
|
|
.setColor(supportbot.Embed.Colours.Error);
|
|
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
embeds: [errorEmbed],
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2024-11-09 00:37:51 +00:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const errorEmbed = new Discord.EmbedBuilder()
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setDescription(
|
|
|
|
|
|
"⚠️ This button is not linked to a valid voice channel.",
|
|
|
|
|
|
)
|
2024-11-09 00:37:51 +00:00
|
|
|
|
.setColor(supportbot.Embed.Colours.Warn);
|
|
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
embeds: [errorEmbed],
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2024-11-09 00:37:51 +00:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-10-24 22:48:25 +01:00
|
|
|
|
if (interaction.isButton()) {
|
2026-03-11 18:58:15 +00:00
|
|
|
|
if (interaction.customId.startsWith("ticket_ai_enable:")) {
|
|
|
|
|
|
const ticketId = interaction.customId.split(":")[1];
|
|
|
|
|
|
const ticket = db.getTicket(ticketId);
|
|
|
|
|
|
|
|
|
|
|
|
if (!ticket) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: msgconfig.Ticket.AIMode.TicketNotFound,
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const usingThreads = supportbot.Ticket.TicketType === "threads";
|
|
|
|
|
|
|
|
|
|
|
|
if (usingThreads) {
|
|
|
|
|
|
db.setTicketAIState(ticketId, {
|
|
|
|
|
|
enabled: true,
|
|
|
|
|
|
aiChannelId: interaction.channel.id,
|
|
|
|
|
|
aiType: "thread",
|
|
|
|
|
|
enabledBy: interaction.user.id,
|
|
|
|
|
|
enabledAt: new Date().toISOString(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const embed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(msgconfig.Ticket.AIMode.EnabledMessage)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
embeds: [embed],
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let aiChannelId = ticket.aiChannelId;
|
|
|
|
|
|
|
|
|
|
|
|
if (!aiChannelId) {
|
|
|
|
|
|
const threadName =
|
|
|
|
|
|
supportbot.Ticket.AIMode?.ThreadName || "Chat with SupportBot AI";
|
|
|
|
|
|
|
|
|
|
|
|
const aiThread = await interaction.channel.threads.create({
|
|
|
|
|
|
name: threadName,
|
|
|
|
|
|
autoArchiveDuration: 60,
|
|
|
|
|
|
reason: "ticket ai mode thread",
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await aiThread.members.add(interaction.user.id).catch(() => {});
|
|
|
|
|
|
|
|
|
|
|
|
aiChannelId = aiThread.id;
|
|
|
|
|
|
|
|
|
|
|
|
const welcomeEmbed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setTitle(msgconfig.Ticket.AIMode.ThreadWelcomeTitle)
|
|
|
|
|
|
.setDescription(msgconfig.Ticket.AIMode.ThreadWelcomeMessage)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.General);
|
|
|
|
|
|
|
|
|
|
|
|
await aiThread.send({ embeds: [welcomeEmbed] });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
db.setTicketAIState(ticketId, {
|
|
|
|
|
|
enabled: true,
|
|
|
|
|
|
aiChannelId,
|
|
|
|
|
|
aiType: "thread",
|
|
|
|
|
|
enabledBy: interaction.user.id,
|
|
|
|
|
|
enabledAt: new Date().toISOString(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const embed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(msgconfig.Ticket.AIMode.EnabledMessage)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
embeds: [embed],
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("Error enabling ticket AI:", error);
|
|
|
|
|
|
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: msgconfig.Ticket.AIMode.EnableError,
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (interaction.customId.startsWith("ticket_ai_disable:")) {
|
|
|
|
|
|
const ticketId = interaction.customId.split(":")[1];
|
|
|
|
|
|
const ticket = db.getTicket(ticketId);
|
|
|
|
|
|
|
|
|
|
|
|
if (!ticket) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: msgconfig.Ticket.AIMode.TicketNotFound,
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
db.setTicketAIState(ticketId, {
|
|
|
|
|
|
enabled: false,
|
|
|
|
|
|
aiChannelId: null,
|
|
|
|
|
|
aiType: null,
|
|
|
|
|
|
enabledBy: interaction.user.id,
|
|
|
|
|
|
enabledAt: null,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const embed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(msgconfig.Ticket.AIMode.DisabledMessage)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
embeds: [embed],
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("Error disabling ticket AI:", error);
|
|
|
|
|
|
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: msgconfig.Ticket.AIMode.DisableError,
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-30 17:45:35 +01:00
|
|
|
|
if (interaction.customId === "unarchiveTicket") {
|
2024-10-10 19:14:45 +01:00
|
|
|
|
if (supportbot.Ticket.TicketType === "threads") {
|
|
|
|
|
|
await interaction.channel.setArchived(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (supportbot.Ticket.TicketType === "channels") {
|
|
|
|
|
|
const { getRole, getChannel } = interaction.client;
|
2026-03-10 20:02:43 +00:00
|
|
|
|
await interaction.channel.setParent(
|
|
|
|
|
|
supportbot.Ticket.TicketChannelsCategory,
|
|
|
|
|
|
);
|
2025-09-20 23:09:22 +01:00
|
|
|
|
const ticketData = db.getAllTickets();
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const ticketInfo = ticketData.find(
|
|
|
|
|
|
(t) => t.ticket_id === interaction.channel.id,
|
|
|
|
|
|
);
|
2024-10-10 19:14:45 +01:00
|
|
|
|
if (ticketInfo) {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const user =
|
|
|
|
|
|
interaction.guild.members.cache.get(ticketInfo.user_id) ||
|
|
|
|
|
|
ticketInfo.user_id;
|
|
|
|
|
|
const claimedBy =
|
|
|
|
|
|
interaction.guild.members.cache.get(ticketInfo.claimed_by) ||
|
|
|
|
|
|
ticketInfo.claimed_by;
|
|
|
|
|
|
const Admin = await interaction.guild.roles.fetch(
|
|
|
|
|
|
supportbot.Roles.StaffMember.Admin,
|
|
|
|
|
|
);
|
|
|
|
|
|
const Staff = await interaction.guild.roles.fetch(
|
|
|
|
|
|
supportbot.Roles.StaffMember.Staff,
|
|
|
|
|
|
);
|
2024-10-10 19:14:45 +01:00
|
|
|
|
if (user && user.id) {
|
|
|
|
|
|
await interaction.channel.permissionOverwrites.edit(user.id, {
|
|
|
|
|
|
ViewChannel: true,
|
|
|
|
|
|
SendMessages: true,
|
|
|
|
|
|
ReadMessageHistory: true,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if (supportbot.ClaimTickets === true) {
|
|
|
|
|
|
if (claimedBy && claimedBy.id) {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
await interaction.channel.permissionOverwrites.edit(
|
|
|
|
|
|
claimedBy.id,
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewChannel: true,
|
|
|
|
|
|
SendMessages: true,
|
|
|
|
|
|
ReadMessageHistory: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2024-10-10 19:14:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
if (supportbot.ClaimTickets === false) {
|
|
|
|
|
|
if (Staff && Staff.id) {
|
2026-03-10 20:02:43 +00:00
|
|
|
|
await interaction.channel.permissionOverwrites.edit(
|
|
|
|
|
|
claimedBy.id,
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewChannel: true,
|
|
|
|
|
|
SendMessages: true,
|
|
|
|
|
|
ReadMessageHistory: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2024-10-10 19:14:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
if (Admin && Admin.id) {
|
|
|
|
|
|
await interaction.channel.permissionOverwrites.edit(Admin.id, {
|
|
|
|
|
|
ViewChannel: true,
|
|
|
|
|
|
SendMessages: true,
|
|
|
|
|
|
ReadMessageHistory: true,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-03-10 20:02:43 +00:00
|
|
|
|
await interaction.channel.permissionOverwrites.edit(
|
|
|
|
|
|
interaction.guild.roles.everyone.id,
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewChannel: false,
|
|
|
|
|
|
SendMessages: false,
|
|
|
|
|
|
ReadMessageHistory: false,
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
2024-10-10 19:14:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
const unrcembed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(msgconfig.Ticket.TicketUnarchived)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
2024-07-30 17:45:35 +01:00
|
|
|
|
await interaction.update({
|
|
|
|
|
|
embeds: [unrcembed],
|
|
|
|
|
|
components: [],
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-10 20:15:00 +01:00
|
|
|
|
if (interaction.customId === "createticket" || interaction.customId === "openticket") {
|
|
|
|
|
|
const panelDisabled = panelconfig.Panel === false || supportbot.Ticket?.Enabled === false;
|
|
|
|
|
|
if (panelDisabled) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "Ticket creation is currently disabled.",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-09 22:49:49 +01:00
|
|
|
|
if (supportbot.Ticket.TicketReason) {
|
|
|
|
|
|
const modal = new Discord.ModalBuilder()
|
|
|
|
|
|
.setCustomId("ticketReasonModal")
|
|
|
|
|
|
.setTitle("Ticket Reason")
|
|
|
|
|
|
.addComponents(
|
|
|
|
|
|
new Discord.ActionRowBuilder().addComponents(
|
|
|
|
|
|
new Discord.TextInputBuilder()
|
|
|
|
|
|
.setCustomId("reasonInput")
|
|
|
|
|
|
.setLabel("Reason")
|
|
|
|
|
|
.setStyle(Discord.TextInputStyle.Paragraph)
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setRequired(true),
|
|
|
|
|
|
),
|
2024-07-09 22:49:49 +01:00
|
|
|
|
);
|
|
|
|
|
|
await interaction.showModal(modal);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
|
|
|
|
|
|
if (!cmd) return;
|
|
|
|
|
|
await cmd.run(interaction);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("Error executing the ticket command:", error);
|
|
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
content: "An error occurred while creating the ticket.",
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2024-07-09 22:49:49 +01:00
|
|
|
|
});
|
|
|
|
|
|
}
|
2021-10-24 22:48:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-12 12:54:31 +01:00
|
|
|
|
if (interaction.customId === "openticket") {
|
2024-07-09 22:49:49 +01:00
|
|
|
|
if (supportbot.Ticket.TicketReason) {
|
|
|
|
|
|
const modal = new Discord.ModalBuilder()
|
|
|
|
|
|
.setCustomId("ticketReasonModal")
|
|
|
|
|
|
.setTitle("Ticket Reason")
|
|
|
|
|
|
.addComponents(
|
|
|
|
|
|
new Discord.ActionRowBuilder().addComponents(
|
|
|
|
|
|
new Discord.TextInputBuilder()
|
|
|
|
|
|
.setCustomId("reasonInput")
|
|
|
|
|
|
.setLabel("Reason")
|
|
|
|
|
|
.setStyle(Discord.TextInputStyle.Paragraph)
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setRequired(true),
|
|
|
|
|
|
),
|
2024-07-09 22:49:49 +01:00
|
|
|
|
);
|
|
|
|
|
|
await interaction.showModal(modal);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
|
|
|
|
|
|
if (!cmd) return;
|
|
|
|
|
|
await cmd.run(interaction);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(error);
|
|
|
|
|
|
}
|
2021-10-24 22:48:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-12 12:54:31 +01:00
|
|
|
|
|
2024-07-09 22:49:49 +01:00
|
|
|
|
if (interaction.customId.startsWith("claimticket-")) {
|
|
|
|
|
|
const ticketChannelId = interaction.customId.split("-")[1];
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const ticketChannel =
|
|
|
|
|
|
interaction.guild.channels.cache.get(ticketChannelId);
|
2024-06-12 12:54:31 +01:00
|
|
|
|
if (!ticketChannel) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "Ticket channel not found.",
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2021-10-24 22:48:25 +01:00
|
|
|
|
});
|
2024-06-12 12:54:31 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-20 23:09:22 +01:00
|
|
|
|
const { getRole } = interaction.client;
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const Staff = await getRole(
|
|
|
|
|
|
supportbot.Roles.StaffMember.Staff,
|
|
|
|
|
|
interaction.guild,
|
|
|
|
|
|
);
|
|
|
|
|
|
const Admin = await getRole(
|
|
|
|
|
|
supportbot.Roles.StaffMember.Admin,
|
|
|
|
|
|
interaction.guild,
|
|
|
|
|
|
);
|
2024-06-12 12:54:31 +01:00
|
|
|
|
|
|
|
|
|
|
const RolePerms = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setTitle("Invalid Permissions!")
|
|
|
|
|
|
.setDescription(
|
2026-03-10 20:02:43 +00:00
|
|
|
|
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``,
|
2024-06-12 12:54:31 +01:00
|
|
|
|
)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Warn);
|
|
|
|
|
|
|
|
|
|
|
|
if (!Staff || !Admin) {
|
2025-09-20 23:09:22 +01:00
|
|
|
|
return interaction.reply({ embeds: [RolePerms], ephemeral: true });
|
2024-06-12 12:54:31 +01:00
|
|
|
|
}
|
2021-10-24 22:48:25 +01:00
|
|
|
|
|
2024-06-12 12:54:31 +01:00
|
|
|
|
const NoPermsClaim = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setTitle(msgconfig.Ticket.ClaimTickets.NoPermsToClaimTitle)
|
|
|
|
|
|
.setDescription(
|
2026-03-10 20:02:43 +00:00
|
|
|
|
msgconfig.Ticket.ClaimTickets.NoPermsToClaim.replace(
|
|
|
|
|
|
"%channel%",
|
|
|
|
|
|
ticketChannel.name,
|
|
|
|
|
|
),
|
2024-06-12 12:54:31 +01:00
|
|
|
|
)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Error);
|
|
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
if (
|
|
|
|
|
|
!interaction.member.roles.cache.has(Staff.id) &&
|
|
|
|
|
|
!interaction.member.roles.cache.has(Admin.id)
|
|
|
|
|
|
) {
|
2025-09-20 23:09:22 +01:00
|
|
|
|
return interaction.reply({ embeds: [NoPermsClaim], ephemeral: true });
|
2024-06-12 12:54:31 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-10 19:14:45 +01:00
|
|
|
|
if (supportbot.Ticket.TicketType === "threads") {
|
2025-09-20 23:09:22 +01:00
|
|
|
|
await ticketChannel.members.add(interaction.user.id);
|
|
|
|
|
|
} else {
|
2024-10-10 19:14:45 +01:00
|
|
|
|
await ticketChannel.permissionOverwrites.create(interaction.user.id, {
|
2025-09-20 23:09:22 +01:00
|
|
|
|
ViewChannel: true,
|
|
|
|
|
|
SendMessages: true,
|
|
|
|
|
|
ReadMessageHistory: true,
|
|
|
|
|
|
});
|
2024-10-10 19:14:45 +01:00
|
|
|
|
await ticketChannel.permissionOverwrites.create(Admin, {
|
2025-09-20 23:09:22 +01:00
|
|
|
|
ViewChannel: true,
|
|
|
|
|
|
SendMessages: true,
|
|
|
|
|
|
ReadMessageHistory: true,
|
|
|
|
|
|
});
|
2026-03-10 20:02:43 +00:00
|
|
|
|
await ticketChannel.permissionOverwrites.create(
|
|
|
|
|
|
interaction.guild.roles.everyone,
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewChannel: false,
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
2025-09-20 23:09:22 +01:00
|
|
|
|
}
|
2024-06-12 12:54:31 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const pingclaimedstaff = await ticketChannel.send(
|
|
|
|
|
|
`<@${interaction.user.id}>`,
|
|
|
|
|
|
);
|
2025-09-20 23:09:22 +01:00
|
|
|
|
setTimeout(() => pingclaimedstaff.delete(), 2000);
|
2024-06-12 12:54:31 +01:00
|
|
|
|
|
2025-09-20 23:09:22 +01:00
|
|
|
|
const ticketInfo = db.getTicket(ticketChannelId);
|
|
|
|
|
|
if (ticketInfo) {
|
|
|
|
|
|
db.updateTicketStatus(ticketChannelId, ticketInfo.status);
|
|
|
|
|
|
ticketInfo.claimed_by = interaction.user.id;
|
2021-10-24 22:48:25 +01:00
|
|
|
|
}
|
2024-06-12 12:54:31 +01:00
|
|
|
|
|
|
|
|
|
|
const claimMessage = await interaction.message.fetch();
|
|
|
|
|
|
const claimedEmbed = new Discord.EmbedBuilder(claimMessage.embeds[0].data)
|
|
|
|
|
|
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimedTitle)
|
|
|
|
|
|
.setDescription(
|
2026-03-10 20:02:43 +00:00
|
|
|
|
msgconfig.Ticket.ClaimTickets.ClaimMessage_Edit.replace(
|
|
|
|
|
|
"%user%",
|
|
|
|
|
|
`${interaction.user.id}`,
|
|
|
|
|
|
).replace("%channel%", `${ticketChannel.id}`),
|
2024-06-12 12:54:31 +01:00
|
|
|
|
)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
|
|
|
|
|
|
const successfullyClaimed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimedTitle)
|
2026-03-10 20:02:43 +00:00
|
|
|
|
.setDescription(
|
|
|
|
|
|
msgconfig.Ticket.ClaimTickets.Claimed.replace(
|
|
|
|
|
|
"%channel%",
|
|
|
|
|
|
`${ticketChannel.id}`,
|
|
|
|
|
|
),
|
2025-09-20 23:09:22 +01:00
|
|
|
|
)
|
2024-06-12 12:54:31 +01:00
|
|
|
|
.setColor(supportbot.Embed.Colours.Success);
|
|
|
|
|
|
|
|
|
|
|
|
await claimMessage.edit({ embeds: [claimedEmbed], components: [] });
|
2026-03-10 20:02:43 +00:00
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
embeds: [successfullyClaimed],
|
|
|
|
|
|
ephemeral: true,
|
|
|
|
|
|
});
|
2021-10-24 22:48:25 +01:00
|
|
|
|
}
|
2024-06-13 17:36:44 +01:00
|
|
|
|
|
|
|
|
|
|
// SUGGESTION INTERACTIONS [START]
|
2024-07-09 22:49:49 +01:00
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
interaction.customId === "upvote" ||
|
|
|
|
|
|
interaction.customId === "downvote" ||
|
|
|
|
|
|
interaction.customId === "removevote"
|
|
|
|
|
|
) {
|
2026-08-28 17:48:09 +01:00
|
|
|
|
const suggestion = (typeof db.getSuggestion === "function" ? db.getSuggestion(interaction.message.id) : null) || {
|
|
|
|
|
|
id: interaction.message.id,
|
|
|
|
|
|
author_id: "",
|
|
|
|
|
|
text: "",
|
|
|
|
|
|
status: "Created",
|
|
|
|
|
|
upvotes: [],
|
|
|
|
|
|
downvotes: [],
|
|
|
|
|
|
};
|
2024-06-13 17:36:44 +01:00
|
|
|
|
|
|
|
|
|
|
const userId = interaction.user.id;
|
|
|
|
|
|
|
2026-08-28 17:48:09 +01:00
|
|
|
|
if (supportbot.Suggestions?.OwnSuggestion === false && suggestion.author_id === userId) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "You cannot vote on your own suggestion.",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
2024-06-13 17:36:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-28 17:48:09 +01:00
|
|
|
|
const voteResult = typeof db.voteSuggestion === "function"
|
|
|
|
|
|
? db.voteSuggestion(interaction.message.id, userId, interaction.customId)
|
|
|
|
|
|
: { upvoteCount: 0, downvoteCount: 0 };
|
|
|
|
|
|
|
|
|
|
|
|
const oldEmbed = interaction.message.embeds?.[0];
|
|
|
|
|
|
if (!oldEmbed) {
|
|
|
|
|
|
return interaction.reply({
|
|
|
|
|
|
content: "Suggestion embed not found.",
|
|
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2024-06-13 17:36:44 +01:00
|
|
|
|
|
2026-08-28 17:48:09 +01:00
|
|
|
|
const suggestionText = suggestion.text || oldEmbed.fields?.find((f) => f.name === "Suggestion")?.value || "";
|
|
|
|
|
|
const authorText = suggestion.author_id
|
|
|
|
|
|
? `<@${suggestion.author_id}>`
|
|
|
|
|
|
: (oldEmbed.fields?.find((f) => f.name === "From")?.value || `<@${userId}>`);
|
2024-06-13 17:36:44 +01:00
|
|
|
|
|
2026-08-28 17:48:09 +01:00
|
|
|
|
const updatedEmbed = Discord.EmbedBuilder.from(oldEmbed).setFields([
|
|
|
|
|
|
{ name: "Suggestion", value: suggestionText, inline: true },
|
|
|
|
|
|
{ name: "From", value: authorText },
|
2024-07-09 22:49:49 +01:00
|
|
|
|
{
|
|
|
|
|
|
name: `${supportbot.Suggestions.UpvoteEmoji} ${supportbot.Suggestions.UpvoteTitle}`,
|
2026-08-28 17:48:09 +01:00
|
|
|
|
value: `${voteResult.upvoteCount}`,
|
2024-07-09 22:49:49 +01:00
|
|
|
|
inline: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: `${supportbot.Suggestions.DownvoteEmoji} ${supportbot.Suggestions.DownvoteTitle}`,
|
2026-08-28 17:48:09 +01:00
|
|
|
|
value: `${voteResult.downvoteCount}`,
|
2024-07-09 22:49:49 +01:00
|
|
|
|
inline: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
2024-06-13 17:36:44 +01:00
|
|
|
|
|
|
|
|
|
|
await interaction.update({ embeds: [updatedEmbed] });
|
|
|
|
|
|
}
|
2021-10-24 22:48:25 +01:00
|
|
|
|
}
|
2024-06-12 12:54:31 +01:00
|
|
|
|
|
|
|
|
|
|
async function handleInvites(interaction, enable) {
|
|
|
|
|
|
if (supportbot.Ticket.Invites.StaffOnly) {
|
2024-07-30 17:45:35 +01:00
|
|
|
|
const { getRole, getChannel } = interaction.client;
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const SupportStaff = await getRole(
|
|
|
|
|
|
supportbot.Roles.StaffMember.Staff,
|
|
|
|
|
|
interaction.guild,
|
|
|
|
|
|
);
|
|
|
|
|
|
const Admin = await getRole(
|
|
|
|
|
|
supportbot.Roles.StaffMember.Admin,
|
|
|
|
|
|
interaction.guild,
|
|
|
|
|
|
);
|
2024-06-12 12:54:31 +01:00
|
|
|
|
|
|
|
|
|
|
if (!SupportStaff || !Admin) {
|
2024-07-09 22:49:49 +01:00
|
|
|
|
return interaction.reply(
|
2026-03-10 20:02:43 +00:00
|
|
|
|
"Some roles seem to be missing!\nPlease check for errors when starting the bot.",
|
2024-07-09 22:49:49 +01:00
|
|
|
|
);
|
2024-06-12 12:54:31 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const NoPerms = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setTitle("Invalid Permissions!")
|
|
|
|
|
|
.setDescription(
|
2026-03-10 20:02:43 +00:00
|
|
|
|
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``,
|
2024-06-12 12:54:31 +01:00
|
|
|
|
)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.Warn);
|
|
|
|
|
|
|
2024-07-09 22:49:49 +01:00
|
|
|
|
if (
|
|
|
|
|
|
!interaction.member.roles.cache.has(SupportStaff.id) &&
|
|
|
|
|
|
!interaction.member.roles.cache.has(Admin.id)
|
|
|
|
|
|
) {
|
2024-06-12 12:54:31 +01:00
|
|
|
|
return interaction.reply({ embeds: [NoPerms] });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await interaction.channel.setInvitable(enable);
|
|
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
const message = enable
|
|
|
|
|
|
? msgconfig.Ticket.EnableInvites
|
|
|
|
|
|
: msgconfig.Ticket.DisableInvites;
|
|
|
|
|
|
const embed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setDescription(message)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.General);
|
2024-06-12 12:54:31 +01:00
|
|
|
|
|
|
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
embeds: [embed],
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2024-06-12 12:54:31 +01:00
|
|
|
|
});
|
|
|
|
|
|
}
|
2024-06-13 17:36:44 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
if (
|
|
|
|
|
|
interaction.type === Discord.InteractionType.ModalSubmit &&
|
|
|
|
|
|
interaction.customId === "editProfileModal"
|
|
|
|
|
|
) {
|
2024-07-03 13:46:57 +01:00
|
|
|
|
const userId = interaction.user.id;
|
|
|
|
|
|
const profilePath = `./Data/Profiles/${userId}.json`;
|
|
|
|
|
|
|
|
|
|
|
|
let profileData;
|
|
|
|
|
|
if (fs.existsSync(profilePath)) {
|
|
|
|
|
|
profileData = JSON.parse(fs.readFileSync(profilePath, "utf8"));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
profileData = {
|
|
|
|
|
|
bio: "",
|
|
|
|
|
|
timezone: "",
|
2024-07-09 22:49:49 +01:00
|
|
|
|
clockedIn: false,
|
2024-07-03 13:46:57 +01:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2024-07-09 22:49:49 +01:00
|
|
|
|
const newBio = interaction.fields.getTextInputValue("bio");
|
|
|
|
|
|
const newTimezone = interaction.fields.getTextInputValue("timezone");
|
2024-07-03 13:46:57 +01:00
|
|
|
|
|
|
|
|
|
|
profileData.bio = newBio;
|
|
|
|
|
|
profileData.timezone = newTimezone;
|
|
|
|
|
|
|
|
|
|
|
|
fs.writeFileSync(profilePath, JSON.stringify(profileData, null, 2));
|
|
|
|
|
|
|
|
|
|
|
|
const updatedProfileEmbed = new Discord.EmbedBuilder()
|
|
|
|
|
|
.setTitle(`${interaction.user.username}'s Profile`)
|
|
|
|
|
|
.setColor(supportbot.Embed.Colours.General)
|
|
|
|
|
|
.setThumbnail(interaction.user.displayAvatarURL())
|
|
|
|
|
|
.addFields(
|
2024-07-09 22:49:49 +01:00
|
|
|
|
{ name: "Bio", value: newBio || "No bio set.", inline: false },
|
2026-03-10 20:02:43 +00:00
|
|
|
|
{
|
|
|
|
|
|
name: "Timezone",
|
|
|
|
|
|
value: newTimezone || "No timezone set.",
|
|
|
|
|
|
inline: true,
|
|
|
|
|
|
},
|
2024-07-03 13:46:57 +01:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (profileData.clockedIn !== undefined) {
|
|
|
|
|
|
updatedProfileEmbed.addFields({
|
2024-07-09 22:49:49 +01:00
|
|
|
|
name: "Clocked In Status",
|
|
|
|
|
|
value: profileData.clockedIn ? "✅ Clocked In" : "❌ Clocked Out",
|
|
|
|
|
|
inline: true,
|
2024-07-03 13:46:57 +01:00
|
|
|
|
});
|
|
|
|
|
|
}
|
2024-06-13 17:36:44 +01:00
|
|
|
|
|
2026-03-10 20:02:43 +00:00
|
|
|
|
await interaction.reply({
|
|
|
|
|
|
embeds: [updatedProfileEmbed],
|
|
|
|
|
|
ephemeral: true,
|
|
|
|
|
|
});
|
2024-07-03 13:46:57 +01:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("Failed to update profile data: ", error);
|
2024-07-09 22:49:49 +01:00
|
|
|
|
await interaction.reply({
|
2026-03-10 20:02:43 +00:00
|
|
|
|
content:
|
|
|
|
|
|
"There was an error while updating your profile. Please try again later.",
|
2025-09-22 18:36:04 +01:00
|
|
|
|
flags: Discord.MessageFlags.Ephemeral,
|
2024-07-09 22:49:49 +01:00
|
|
|
|
});
|
2024-07-03 13:46:57 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-13 17:36:44 +01:00
|
|
|
|
});
|