AeThex-Bot-Master/aethex-bot/commands/ticket.js
sirpiglr 42c24762b0 Add optional Supabase integration and improve command reliability
Implement guards for Supabase-dependent commands, refine error handling, and introduce feed synchronization capabilities.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: e72fc1b7-94bd-4d6c-801f-cbac2fae245c
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 48ccfc2d-e27b-4e3b-b0d2-25bdb3ece9c8
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/e72fc1b7-94bd-4d6c-801f-cbac2fae245c/NXjYRWJ
Replit-Helium-Checkpoint-Created: true
2025-12-07 23:19:50 +00:00

139 lines
4.7 KiB
JavaScript

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],
},
],
});
client.activeTickets.set(ticketChannel.id, {
userId: interaction.user.id,
guildId: interaction.guildId,
reason: reason,
createdAt: Date.now(),
});
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: `<t:${Math.floor(Date.now() / 1000)}:F>` }
)
.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);
setTimeout(async () => {
try {
await interaction.channel.delete();
} catch (e) {
console.error('Failed to delete ticket channel:', e);
}
}, 5000);
}
},
};