${msg.author.tag}
${convertMarkdownToHTML(msg.content)}
const fs = require("fs"); const Discord = require("discord.js"); const yaml = require("js-yaml"); const supportbot = yaml.load( fs.readFileSync("./Configs/supportbot.yml", "utf8") ); const cmdconfig = yaml.load( fs.readFileSync("./Configs/commands.yml", "utf8") ); const msgconfig = yaml.load( fs.readFileSync("./Configs/messages.yml", "utf8") ); const Command = require("../Structures/Command.js"); module.exports = new Command({ name: cmdconfig.CloseTicket.Command, description: cmdconfig.CloseTicket.Description, type: Discord.ApplicationCommandType.ChatInput, options: [ { name: "reason", description: "Ticket Close Reason", type: Discord.ApplicationCommandOptionType.String, }, ], permissions: cmdconfig.CloseTicket.Permission, async run(interaction) { const { getRole, getChannel } = interaction.client; if (supportbot.Ticket.Close.StaffOnly) { let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild); let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild); if (!SupportStaff || !Admin) return interaction.reply( "Some roles seem to be missing!\nPlease check for errors when starting the bot." ); const NoPerms = new Discord.EmbedBuilder() .setTitle("Invalid Permissions!") .setDescription( `${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\`` ) .setColor(supportbot.Embed.Colours.Warn); if ( !interaction.member.roles.cache.has(SupportStaff.id) && !interaction.member.roles.cache.has(Admin.id) ) return interaction.reply({ embeds: [NoPerms] }); } if (interaction.channel.type !== Discord.ChannelType.PrivateThread) { const NotTicketChannel = new Discord.EmbedBuilder() .setTitle("Invalid Channel!") .setDescription("This command can only be used in a ticket thread.") .setColor(supportbot.Embed.Colours.Warn); return interaction.reply({ embeds: [NotTicketChannel], ephemeral: true }); } await interaction.deferReply(); let tickets = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8")); let TicketData = tickets.tickets.findIndex((t) => t.id === interaction.channel.id); let ticket = tickets.tickets[TicketData]; if (TicketData === -1) { const Exists = new Discord.EmbedBuilder() .setTitle("No Ticket Found!") .setDescription(msgconfig.Error.NoValidTicket) .setColor(supportbot.Embed.Colours.Warn); return interaction.followUp({ embeds: [Exists] }); } let reason = interaction.options?.getString("reason") || "No Reason Provided."; const CloseButton = new Discord.ButtonBuilder() .setCustomId("confirmCloseTicket") .setLabel(supportbot.Ticket.Close.Confirmation_Button) .setStyle(Discord.ButtonStyle.Danger); const row = new Discord.ActionRowBuilder().addComponents(CloseButton); const CloseTicketRequest = new Discord.EmbedBuilder() .setTitle(`**${supportbot.Ticket.Close.Title}**`) .setDescription( `${msgconfig.Ticket.ConfirmClose}` ) .setColor(supportbot.Embed.Colours.General); await interaction.followUp({ embeds: [CloseTicketRequest], components: [row], }); const filter = (btnInteraction) => btnInteraction.customId === "confirmCloseTicket" && btnInteraction.user.id === interaction.user.id; interaction.channel.awaitMessageComponent({ filter, time: 20000 }) .then(async (btnInteraction) => { await handleCloseTicket(interaction, reason, ticket, TicketData); await btnInteraction.reply({ content: "Ticket successfully closed.", ephemeral: true }); }) .catch((err) => { interaction.followUp(`${msgconfig.Ticket.CloseTimeout}`); console.error(err); }); }, }); async function handleCloseTicket(interaction, reason, ticket, TicketData) { const { getChannel } = interaction.client; let tickets = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8")); let tUser = interaction.client.users.cache.get(ticket.user); let transcriptChannel = await getChannel(supportbot.Ticket.Log.TranscriptLog, interaction.guild); let logChannel = await getChannel(supportbot.Ticket.Log.TicketLog, interaction.guild); if (!transcriptChannel || !logChannel) return interaction.followUp("Some Channels seem to be missing!"); try { tickets.tickets[TicketData].open = false; fs.writeFileSync( "./Data/TicketData.json", JSON.stringify(tickets, null, 4), (err) => { if (err) console.error(err); } ); const transcriptEmbed = new Discord.EmbedBuilder() .setTitle(supportbot.Ticket.Log.TranscriptTitle) .setColor(supportbot.Embed.Colours.General) .setFooter({ text: supportbot.Embed.Footer, iconURL: interaction.user.displayAvatarURL(), }) .addFields( { name: "Ticket", value: `${interaction.channel.name} (${interaction.channel.id})` }, { name: "User", value: `${tUser?.username || "N/A"}#${tUser?.discriminator || "N/A"} (${tUser?.id || ticket.user})` }, { name: "Closed By", value: interaction.user.tag }, { name: "Reason", value: reason } ); const logEmbed = new Discord.EmbedBuilder() .setTitle(supportbot.Ticket.Log.TicketLog_Title) .setColor(supportbot.Embed.Colours.General) .setFooter({ text: supportbot.Embed.Footer, iconURL: interaction.user.displayAvatarURL(), }) .addFields( { name: "Ticket", value: `${interaction.channel.name} (${interaction.channel.id})` }, { name: "User", value: `${tUser?.username || "N/A"}#${tUser?.discriminator || "N/A"} (${tUser?.id || ticket.user})` }, { name: "Closed By", value: interaction.user.tag }, { name: "Reason", value: reason } ); let msgs = await interaction.channel.messages.fetch({ limit: 100 }); let html = `
Server Name: ${interaction.guild.name}
Ticket: ${interaction.channel.name}
Messages: ${msgs.size} Messages
code
text = text.replace(/`(.*?)`/g, '$1');
// Convert blockquotes > quote to quotetext = text.replace(/^> (.*?$)/gm, '
$1'); // Convert multiline code blocks ```code``` to
code
text = text.replace(/```(.*?)```/gs, '$1');
// Convert line breaks to