const { SlashCommandBuilder, EmbedBuilder, ChannelType, PermissionFlagsBits, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); module.exports = { data: new SlashCommandBuilder() .setName('ticket') .setDescription('Support ticket system') .addSubcommand(subcommand => subcommand .setName('create') .setDescription('Create a support ticket') .addStringOption(option => option.setName('reason') .setDescription('Reason for the ticket') .setRequired(false) ) ) .addSubcommand(subcommand => subcommand .setName('close') .setDescription('Close the current ticket') ), async execute(interaction, supabase, client) { const subcommand = interaction.options.getSubcommand(); if (subcommand === 'create') { const reason = interaction.options.getString('reason') || 'No reason provided'; const existingTicket = [...client.activeTickets.entries()].find( ([, data]) => data.userId === interaction.user.id && data.guildId === interaction.guildId ); if (existingTicket) { const embed = new EmbedBuilder() .setColor(0xff0000) .setTitle('Ticket Already Exists') .setDescription(`You already have an open ticket: <#${existingTicket[0]}>`) .setTimestamp(); await interaction.reply({ embeds: [embed], ephemeral: true }); return; } try { const ticketChannel = await interaction.guild.channels.create({ name: `ticket-${interaction.user.username}`, type: ChannelType.GuildText, permissionOverwrites: [ { id: interaction.guild.id, deny: [PermissionFlagsBits.ViewChannel], }, { id: interaction.user.id, allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages], }, ], }); const ticketData = { userId: interaction.user.id, guildId: interaction.guildId, reason: reason, createdAt: Date.now(), }; client.activeTickets.set(ticketChannel.id, ticketData); if (client.saveTicket) { await client.saveTicket(ticketChannel.id, ticketData); } const closeButton = new ActionRowBuilder().addComponents( new ButtonBuilder() .setCustomId(`ticket_close_${ticketChannel.id}`) .setLabel('Close Ticket') .setStyle(ButtonStyle.Danger) ); const ticketEmbed = new EmbedBuilder() .setColor(0x7c3aed) .setTitle('Support Ticket') .setDescription(`Ticket created by ${interaction.user}`) .addFields( { name: 'Reason', value: reason }, { name: 'Created', value: `` } ) .setFooter({ text: 'Click the button below to close this ticket' }) .setTimestamp(); await ticketChannel.send({ embeds: [ticketEmbed], components: [closeButton] }); const successEmbed = new EmbedBuilder() .setColor(0x00ff00) .setTitle('Ticket Created') .setDescription(`Your ticket has been created: ${ticketChannel}`) .setTimestamp(); await interaction.reply({ embeds: [successEmbed], ephemeral: true }); } catch (error) { console.error('Ticket creation error:', error); const errorEmbed = new EmbedBuilder() .setColor(0xff0000) .setTitle('Error') .setDescription('Failed to create ticket. I may not have the required permissions.') .setTimestamp(); await interaction.reply({ embeds: [errorEmbed], ephemeral: true }); } } if (subcommand === 'close') { const ticketData = client.activeTickets.get(interaction.channelId); if (!ticketData) { const embed = new EmbedBuilder() .setColor(0xff0000) .setTitle('Not a Ticket') .setDescription('This channel is not a support ticket.') .setTimestamp(); await interaction.reply({ embeds: [embed], ephemeral: true }); return; } const embed = new EmbedBuilder() .setColor(0xff6600) .setTitle('Closing Ticket') .setDescription('This ticket will be closed in 5 seconds...') .setTimestamp(); await interaction.reply({ embeds: [embed] }); client.activeTickets.delete(interaction.channelId); if (client.closeTicket) { await client.closeTicket(interaction.channelId); } setTimeout(async () => { try { await interaction.channel.delete(); } catch (e) { console.error('Failed to delete ticket channel:', e); } }, 5000); } }, };