const { query, queryMulti } = require("./helper"); const { ticket_settings } = require("../config"); const discordTranscripts = require("discord-html-transcripts"); const { EmbedBuilder, ButtonBuilder, ActionRowBuilder, ModalBuilder, TextInputBuilder } = require('discord.js'); module.exports = async (client, db) => { client.on("interactionCreate", async interaction => { if (!interaction.customId) { return; } if (interaction.customId === "newTicket") { const [, ticketOptionId] = interaction.values[0].split("newTicket_"); const ticketOption = await query( db, `SELECT * FROM options WHERE id='${ticketOptionId}' AND guildID='${interaction.guildId}'` ); const questions = await queryMulti( db, `SELECT * FROM questions WHERE optionID='${ticketOptionId}' AND guildID='${interaction.guildId}'` ); if (questions) { const modal = new ModalBuilder() .setTitle("Ticket Form") .setCustomId(`ticket_${ticketOptionId}`); questions.forEach((question, index) => { const textInput = new TextInputBuilder() .setLabel(question.question) .setStyle(question.answer_type) .setRequired(question.required) .setCustomId(`input_${question.id}`) .setPlaceholder(question.place_holder); const actionRow = new ActionRowBuilder().addComponents(textInput); modal.addComponents(actionRow); }); return interaction.showModal(modal); } else { await interaction.deferReply({ ephemeral: true }); const embed = new EmbedBuilder() .setTimestamp() .setColor(ticket_settings.embed_color) .setDescription(ticket_settings.ticket_message.replace("{user}", interaction.user)) .setThumbnail(ticket_settings.ticket_thumbnail) .setAuthor({ name: interaction.user.tag, iconURL: interaction.user.avatarURL() }); const existingTicket = await query( db, `SELECT * FROM tickets WHERE status='open' AND userID='${interaction.user.id}' AND guildID='${interaction.guildId}'` ); const existingChannel = client.channels.cache.get(existingTicket?.channelID); if (existingTicket && existingChannel) { return interaction.editReply({ content: `You already have a ticket! Please check the ${existingChannel}`, ephemeral: true }); } const settings = await query(db, `SELECT * FROM settings WHERE guildID='${interaction.guildId}'`); db.query(`UPDATE settings SET ticket_counter=ticket_counter+1 WHERE guildID='${interaction.guildId}'`); const permissions = [ { id: interaction.guildId, deny: ["ViewChannel", "SendMessages"] }, { id: interaction.member.id, allow: ["ViewChannel", "SendMessages"] }, { id: client.user.id, allow: ["ViewChannel", "SendMessages"] }, { id: settings?.support_roleID, allow: ["ViewChannel", "SendMessages"] } ]; const channel = await interaction.guild.channels.create({ parent: ticketOption?.categoryID, name: `ticket-${pad(settings.ticket_counter + 1, 4)}`, topic: `#Ticket | From ${interaction.user.username}`, permissionOverwrites: permissions }); const closeButton = new ButtonBuilder() .setEmoji(ticket_settings.buttoncloseemoji) .setLabel(ticket_settings.buttoncloselabel) .setStyle(ticket_settings.buttonclosestyle) .setCustomId("close_ticket"); const actionRow = new ActionRowBuilder().addComponents(closeButton); await channel.send({ content: `<@&${settings?.support_roleID}>`, embeds: [embed], components: [actionRow] }); await interaction.editReply({ content: `You successfully created a ticket! Please check the ${channel}`, ephemeral: true }); db.query( "INSERT INTO tickets (id, status, userID, guildID, channelID) VALUES (?, ?, ?, ?, ?)", [pad(settings.ticket_counter + 1, 4), "open", interaction.user.id, interaction.guildId, channel.id] ); } } else if (interaction.customId.startsWith("ticket_")) { if (!interaction.isModalSubmit()) { return; } await interaction.deferReply({ ephemeral: true }); const ticketOptionId = interaction.customId.split("ticket_")[1]; const ticketOption = await query( db, `SELECT * FROM options WHERE id='${ticketOptionId}' AND guildID='${interaction.guildId}'` ); const userEmbed = new EmbedBuilder() .setTimestamp() .setColor(ticket_settings.embed_color) .setDescription(ticket_settings.ticket_message.replace("{user}", interaction.user)) .setAuthor({ name: interaction.user.tag, iconURL: interaction.user.avatarURL() }); const answerEmbed = new EmbedBuilder() .setTimestamp() .setColor(ticket_settings.embed_color) .setAuthor({ name: interaction.user.tag, iconURL: interaction.user.avatarURL() }); interaction.fields.fields.forEach(async field => { const question = await query( db, `SELECT * FROM questions WHERE id='${field.customId.split("input_")[1]}' AND guildID='${interaction.guildId}'` ); answerEmbed.addFields({ name: question.question, value: `\`\`\`${field.value}\`\`\``, inline: false }); }); const existingTicket = await query( db, `SELECT * FROM tickets WHERE status='open' AND userID='${interaction.user.id}' AND guildID='${interaction.guildId}'` ); const existingChannel = client.channels.cache.get(existingTicket?.channelID); if (existingTicket && existingChannel) { return interaction.editReply({ content: `You already have a ticket! Please check the ${existingChannel}`, ephemeral: true }); } const settings = await query(db, `SELECT * FROM settings WHERE guildID='${interaction.guildId}'`); db.query(`UPDATE settings SET ticket_counter=ticket_counter+1 WHERE guildID='${interaction.guildId}'`); const permissions = [ { id: interaction.guildId, deny: ["ViewChannel", "SendMessages"] }, { id: interaction.member.id, allow: ["ViewChannel", "SendMessages"] }, { id: client.user.id, allow: ["ViewChannel", "SendMessages"] }, { id: settings?.support_roleID, allow: ["ViewChannel", "SendMessages"] } ]; const channel = await interaction.guild.channels.create({ parent: ticketOption?.categoryID, name: `ticket-${pad(settings.ticket_counter + 1, 4)}`, topic: `#Ticket | From ${interaction.user.username}`, permissionOverwrites: permissions }); const closeButton = new ButtonBuilder() .setEmoji(ticket_settings.buttoncloseemoji) .setLabel(ticket_settings.buttoncloselabel) .setStyle(ticket_settings.buttonclosestyle) .setCustomId("close_ticket"); const actionRow = new ActionRowBuilder().addComponents(closeButton); await channel.send({ content: `<@&${settings?.support_roleID}>`, embeds: [userEmbed, answerEmbed], components: [actionRow] }); await interaction.editReply({ content: `You successfully created a ticket! Please check the ${channel}`, ephemeral: true }); db.query( "INSERT INTO tickets (id, status, userID, guildID, channelID) VALUES (?, ?, ?, ?, ?)", [pad(settings.ticket_counter + 1, 4), "open", interaction.user.id, interaction.guildId, channel.id] ); } else if (interaction.customId === "close_ticket") { const modal = new ModalBuilder() .setTitle("Close Ticket") .setCustomId("close_ticket_form"); const textInput = new TextInputBuilder() .setRequired(false) .setCustomId('input') .setStyle("Paragraph") .setLabel("Close message"); const actionRow = new ActionRowBuilder().addComponents(textInput); modal.addComponents(actionRow); return interaction.showModal(modal); } else if (interaction.customId === "close_ticket_form") { if (!interaction.isModalSubmit()) { return; } await interaction.deferReply({ ephemeral: true }); const closeMessage = interaction.fields.getTextInputValue("input"); const transcript = await discordTranscripts.createTranscript(interaction.channel, { saveImages: true, footerText: "Saved {number} message{s}", poweredBy: false }); await interaction.editReply({ content: "You successfully closed the ticket!", ephemeral: true }); const ticket = await query( db, `SELECT * FROM tickets WHERE status='open' AND channelID='${interaction.channel.id}' AND guildID='${interaction.guildId}'` ); const settings = await query(db, `SELECT * FROM settings WHERE guildID='${interaction.guildId}'`); const logChannel = settings?.log_channelID; const logChannelObj = client.channels.cache.get(logChannel); const user = client.users.cache.get(ticket.userID); const embed = new EmbedBuilder() .setTimestamp() .setColor(ticket_settings.embed_color) .setFooter({ text: interaction.guild.name }) .setAuthor({ name: "Ticket has been closed!" }) .addFields( { name: 'Ticket', value: `\`\`\`${interaction.channel.name}\`\`\``, inline: true }, { name: "Ticket Author", value: `\`\`\`${user.tag}\`\`\``, inline: true }, { name: "Server", value: `\`\`\`${interaction.guild.name}\`\`\``, inline: true }, { name: "Reason", value: `\`\`\`${closeMessage}\`\`\``, inline: false } ); await user?.send({ embeds: [embed], files: [transcript] }).catch(() => {}); await logChannelObj?.send({ embeds: [embed], files: [transcript] }).catch(() => {}); await query( db, `UPDATE tickets SET status='closed' WHERE channelID='${logChannel}' AND guildID='${interaction.guildId}'` ); return interaction.channel.delete(); } }); }; function pad(num, size) { let numStr = num.toString(); while (numStr.length < size) { numStr = '0' + numStr; } return numStr; }