I'm trying to implement a ticket system on my discord bot, I don't understand why when I go to click on the ticket opening emoji I get the following: this is my code in discord.js v14. his stored in: ../Clippy/events/buttonResponse.js
const { ChannelType, PermissionFlagsBits, ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, AttachmentBuilder, Attachment } = require('discord.js');
const fs = require('fs');
module.exports = {
name: 'interactionCreate',
once: false,
async execute(interaction, client) {
if (!interaction.isButton()) return;
const button = interaction.customId;
if (button === 'open-ticket') {
await interaction.deferReply({ ephemeral: true });
const ticketData = JSON.parse(fs.readFileSync('../Clippy/ticket.json', 'utf-8')); // Leggi i dati dal file.
const supportRole = interaction.guild.roles.cache.get(ticketData.supportRoleID); // Ottieni il ruolo di supporto dai dati.
const openCategory = interaction.guild.channels.cache.get(ticketData.openCategoryID); // Ottieni la categoria di apertura dai dati.
const closeCategory = interaction.guild.channels.cache.get(ticketData.closeCategoryID); // Ottieni la categoria di chiusura dai dati.
if (!supportRole) return interaction.editReply({ embeds: [client.config.embeds.E('Il ruolo di supporto non esiste!')] });
if (!openCategory) return interaction.editReply({ embeds: [client.config.embeds.E('La categoria di apertura non esiste!')] });
if (!closeCategory) return interaction.editReply({ embeds: [client.config.embeds.E('La categoria di chiusura non esiste!')] });
const createdChannel = await interaction.guild.channels.create({
name: `ticket-${interaction.user.username}`,
type: ChannelType.GuildText,
parent: openCategory,
permissionOverwrites: [
{
id: interaction.guild.id,
deny: PermissionFlagsBits.ViewChannel // Negare il permesso di visualizzazione del canale a tutti i ruoli.
},
{
id: interaction.user.id,
allow: PermissionFlagsBits.ViewChannel // Consentire il permesso di visualizzazione del canale all'utente che ha fatto clic sul pulsante.
},
{
id: supportRole.id,
allow: PermissionFlagsBits.ViewChannel // Consentire il permesso di visualizzazione del canale al ruolo di supporto.
}
],
topic: `🎫 Ticket creato da ${interaction.user.tag}! - ${interaction.user.id}` // Impostare il topic del canale.
});
const createdEmbed = new EmbedBuilder()
.setTitle('🎫 Ticket System')
.setDescription(`Ciao ${interaction.user}👋, benvenuto nel tuo ticket!\nPerfavore spiega dettagliatamente il tuo problema.\n <@&${supportRole.id}> ti risponderò a breve!`)
.setColor(client.config.colors.info)
.setTimestamp();
const createdRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('close-ticket')
.setLabel('Chiudi Ticket')
.setStyle(ButtonStyle.Danger)
);
await createdChannel.send({ embeds: [createdEmbed], components: [createdRow] });
await interaction.editReply({ embeds: [client.config.embeds.S(`Il tuo ticket è stato creato! ${createdChannel}`)] });
} else if (button === 'close-ticket') {
const ticketEmbed = new EmbedBuilder()
.setTitle('🎫 Ticket System')
.setDescription(`Stai per chiudere il tuo ticket!\nSicuro di voler procedere?`)
.setColor(client.config.colors.error)
.setTimestamp();
const ticketRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('confirm-close-ticket')
.setLabel('Conferma chiusura Ticket')
.setStyle(ButtonStyle.Danger),
new ButtonBuilder()
.setCustomId('cancel-close-ticket')
.setLabel('Annulla chiusura Ticket')
.setStyle(ButtonStyle.Success)
);
await interaction.reply({ embeds: [ticketEmbed], components: [ticketRow], ephemeral: true });
} else if (button === 'confirm-close-ticket') {
const ticketData = JSON.parse(fs.readFileSync('ticket.json', 'utf-8')); // Read the data from the file.
const closeCategory = interaction.guild.channels.cache.get(ticketData.closeCategoryID); // Get the close category from the data.
if (!closeCategory) return interaction.editReply({ embeds: [client.config.embeds.E('La categoria chiusa non esiste!')] });
const closedRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('delete-ticket')
.setLabel('Elimina Ticket')
.setStyle(ButtonStyle.Danger),
new ButtonBuilder()
.setCustomId('reopen-ticket')
.setLabel('Riapri Ticket')
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId('transcript-ticket')
.setLabel('Trascrivi Ticket')
.setStyle(ButtonStyle.Primary)
);
await interaction.update({ embeds: [client.config.embeds.S('Il tuo ticket è stato chiuso!')], components: [] });
await interaction.channel.send({ embeds: [client.config.embeds.S(`\🎫 : ${interaction.user} ha chiuso questo ticket!`)], components: [closedRow] });
// Change the parent of the channel.
await interaction.channel.setParent(closeCategory);
} else if (button === 'cancel-close-ticket') {
await interaction.update({ embeds: [client.config.embeds.S('Il tuo ticket non è stato chiuso!')], components: [] });
} else if (button === 'delete-ticket') {
await interaction.reply({ embeds: [client.config.embeds.S(`Ticket eliminato! \`${interaction.channel.name}\` Questo canale verrà eliminato tra 5 secondi!`)], ephemeral: true });
setTimeout(() => interaction.channel.delete(), 5000);
} else if (button === 'reopen-ticket') {
const ticketData = JSON.parse(fs.readFileSync('ticket.json', 'utf-8')); // Read the data from the file.
const openCategory = interaction.guild.channels.cache.get(ticketData.openCategoryID); // Get the open category from the data.
if (!openCategory) return interaction.reply({ embeds: [client.config.embeds.E('La categoria aperta non esiste!')] });
// Change the parent of the channel.
await interaction.channel.setParent(openCategory);
await interaction.update({ embeds: [client.config.embeds.S(`${interaction.user} ha riaperto questo ticket!`)], components: [] });
} else if (button === 'transcript-ticket') {
await interaction.deferReply({ ephemeral: true });
const transcript = await interaction.channel.messages.fetch({ limit: 100 }); // Fetch the last 100 messages from the channel.
const transcriptText = transcript.map(m => `[${m.createdAt.toDateString()}] [${m.createdAt.toTimeString().split(' ')[0]}] [${m.author.tag}]: ${m.content}`).join('\n'); // Map the messages and join them with a new line.
const transcriptData = `🎫 Transcript for #${interaction.channel.name}\n\n${transcriptText}`; // Create the transcript data.
const transcriptFile = new AttachmentBuilder()
.setName(`transcript-${interaction.channel.name}.txt`) // Set the name of the file.
.setFile(Buffer.from(transcriptData)); // Set the file data.
await interaction.editReply({ files: [transcriptFile] });
}
}
}
when i click in a button:"open-ticket" i have this error:
node:events:491
throw er; // Unhandled 'error' event
^
DiscordAPIError[40060]: Interaction has already been acknowledged.
at SequentialHandler.runRequest (/home/enigma/opt/progetti/Clippy/node_modules/@discordjs/rest/dist/index.js:667:15)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async SequentialHandler.queueRequest (/home/enigma/opt/progetti/Clippy/node_modules/@discordjs/rest/dist/index.js:464:14)
at async REST.request (/home/enigma/opt/progetti/Clippy/node_modules/@discordjs/rest/dist/index.js:910:22)
at async ButtonInteraction.reply (/home/enigma/opt/progetti/Clippy/node_modules/discord.js/src/structures/interfaces/InteractionResponses.js:111:5)
Emitted 'error' event on Client instance at:
at emitUnhandledRejectionOrErr (node:events:394:10)
at process.processTicksAndRejections (node:internal/process/task_queues:84:21) {
requestBody: {
files: [],
json: {
type: 4,
data: {
content: 'Ruolo non trovato',
tts: false,
nonce: undefined,
embeds: undefined,
components: undefined,
username: undefined,
avatar_url: undefined,
allowed_mentions: undefined,
flags: 64,
message_reference: undefined,
attachments: undefined,
sticker_ids: undefined,
thread_name: undefined
}
}
},
rawError: {
message: 'Interaction has already been acknowledged.',
code: 40060
},
code: 40060,
status: 400,
method: 'POST',
url: 'https://discord.com/api/v10/interactions/1087867648693522442/aW50ZXJhY3Rpb246MTA4Nzg2NzY0ODY5MzUyMjQ0MjplVW41eXBCNXJJYnlBNEUwYjNjYlQ1WUhTMFQ4M0pmNVdyT3FpNm5kRFNWWTVqNGE3ZnJ6UHJjRlIzSjIybzJ4YmY1NUhZZ0tJZnBrbVVENTlmc3dDaFhteFBseU1EMW90Y3g4RWpaZ2FsQm5WNXhRQ0JCVEhFdWZWNURpVzhVbQ/callback'
}
Node.js v18.14.2
i tried everything but i can't fix it, can you help me please? regards, Darla
Thanks for your reply, I solved this problem by binding my button id as below:
if (interaction.isButton() && interaction.customId === 'MEMBER')
this part was missing in another script and therefore conflicted with the iteration I was trying to run in the script I posted.