const { SlashCommandBuilder, EmbedBuilder, ChannelType, PermissionFlagsBits, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); module.exports = { data: new SlashCommandBuilder() .setName('ticket') .setDescription('Ticket management system') .addSubcommand(subcommand => subcommand .setName('create') .setDescription('Create a new support ticket') .addStringOption(option => option.setName('reason') .setDescription('Brief reason for opening this ticket') .setRequired(true) ) ) .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'); const guild = interaction.guild; const user = interaction.user; const existingTicket = client.activeTickets.get(user.id); if (existingTicket) { return interaction.reply({ content: `You already have an open ticket: <#${existingTicket}>`, ephemeral: true, }); } try { const ticketChannel = await guild.channels.create({ name: `ticket-${user.username}`, type: ChannelType.GuildText, permissionOverwrites: [ { id: guild.id, deny: [PermissionFlagsBits.ViewChannel], }, { id: user.id, allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages], }, { id: client.user.id, allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages, PermissionFlagsBits.ManageChannels], }, ], }); client.activeTickets.set(user.id, ticketChannel.id); 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 ${user}`) .addFields( { name: 'Reason', value: reason }, { name: 'User ID', value: user.id, inline: true }, { name: 'Created', value: ``, inline: true } ) .setFooter({ text: 'A staff member will assist you shortly.' }); await ticketChannel.send({ embeds: [ticketEmbed], components: [closeButton] }); await interaction.reply({ content: `Ticket created: ${ticketChannel}`, ephemeral: true, }); client.sendAlert(`New ticket opened by ${user.tag}: ${reason}`); } catch (error) { console.error('[Ticket] Create error:', error); await interaction.reply({ content: 'Failed to create ticket. Please try again.', ephemeral: true, }); } } if (subcommand === 'close') { const channel = interaction.channel; if (!channel.name.startsWith('ticket-')) { return interaction.reply({ content: 'This command can only be used in ticket channels.', ephemeral: true, }); } const userId = [...client.activeTickets.entries()].find(([k, v]) => v === channel.id)?.[0]; if (userId) { client.activeTickets.delete(userId); } await interaction.reply({ content: 'Closing ticket in 5 seconds...', }); client.sendAlert(`Ticket ${channel.name} closed by ${interaction.user.tag}`); setTimeout(async () => { try { await channel.delete(); } catch (err) { console.error('[Ticket] Delete error:', err); } }, 5000); } }, };