Reputation: 37
The buttons work after doing the command but after restarting the bot and pressing the button, it says interaction failed
Here's my ticket.js
const { MessageButton } = require('discord-buttons');
module.exports = {
name: 'ticket-setup',
aliases: ['close'],
category: 'Miscellaneous',
description: 'Makes a ticket embed',
async execute(message, args, cmd, client, Discord){
if(!message.member.permissions.has("MANAGE_CHANNELS")) return message.reply("Normies can't do this command")
if (cmd == 'close') {
if (!message.channel.name.includes('ticket-')) return message.channel.send('You cannot use that here!');
message.channel.delete();
}
let title;
let desc;
let ticketMsg;
const filter = msg => msg.author.id == message.author.id;
let options = {
max: 1
};
message.channel.send("What will the ticket title be?\nSay cancel to cancel")
let col = await message.channel.awaitMessages(filter, options)
if(col.first().content == 'cancel') return message.channel.send("Cancelled");
title = col.first().content
message.channel.send('What will the description be?\nSay cancel to cancel')
let col2 = await message.channel.awaitMessages(filter, options)
if(col2.first().content == 'cancel') return message.channel.send("Cancelled");
desc = col2.first().content
message.channel.send('What is the message that the user will see when they make a ticket?\nSay cancel to cancel')
let col3 = await message.channel.awaitMessages(filter, options)
if(col3.first().content == 'cancel') return message.channel.send("Cancelled");
ticketMsg = col3.first().content
const setupEmbed = new Discord.MessageEmbed()
.setTitle(title)
.setDescription(desc)
.setFooter(message.guild.name, message.guild.iconURL({ dynamic: true }))
.setColor('00f8ff')
const hiEmbed = new Discord.MessageEmbed()
.addField(ticketMsg, "\n\nDo a.close or press the button to close the ticket")
.setColor("RANDOM")
.setTimestamp()
const createTicketButton = new MessageButton()
.setID("ticketCreate")
.setStyle("blurple")
.setLabel("📨");
const closeTicketButton = new MessageButton()
.setID("ticketClose")
.setLabel("Close ticket")
.setStyle("red");
if(cmd == 'ticket-setup'){
message.channel.send({embed: setupEmbed, button: createTicketButton })
}
client.on('clickButton', async (button) => {
await button.clicker.fetch();
await button.reply.defer();
const user = button.clicker.user
if (button.id === 'ticketCreate') {
button.guild.channels.create(`ticket-${user.id}`, {
permissionOverwrites: [
{
id: user.id,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
},
{
id: button.message.guild.roles.everyone,
deny: ['VIEW_CHANNEL'],
},
],
type: 'text',
}).then(async (channel) =>{
channel.send({embed: hiEmbed, button: closeTicketButton })
})
} else if(button.id == 'ticketClose'){
button.message.channel.delete()
}
});
}
}
I use the package discord-buttons
Docs link
I tried putting the clickButton event in my event handler but it didn't work as I get a lot of errors. How do I still make the buttons work even after restart?
Upvotes: 2
Views: 9692
Reputation: 4520
The Problem
The reason why your buttons aren't working after your bot restarts is because your client.on("clickButton")
event handler is inside your "ticket-setup" command's code. That means your event is only setup once the ticket-setup command is used after the bot restarts, or in other words once execute()
is called on this file after the bot has started up.
Think about this: your client.on("clickButton")
code is not reached until your ticket-setup
command's execute()
function is called. This will cause multiple problems for you. First of all, as mentioned above, the clickButton
event is not even being handled until you've used ticket-setup
at least once after the bot has started up. Secondly, this will create an additional event handler every time the command is used. In other words, if you were to use the ticket-setup
command twice or more, the code within your clickButton
handler would execute more than once every time your buttons are clicked (in your specific scenario, it would create more than one ticket per button click).
The Solution
The problem you are facing has a pretty simple solve. You simply need to move the entirety of your clickButton
event handler out of the execute()
method. Perhaps move it into your main server.js
or bot.js
file, alongside your client.on("ready")
and client.on("message")
event handlers. This will ensure that the clickButton
event handler is setup only once, and immediately when the bot starts up.
Note, however, that you do need to make some slight additions to your clickButton
event handler to ensure this works properly. You need to move the code for your hiEmbed
and closeTicketButton
into your client.on("clickButton")
handler.
Here's how that might look, in server.js
, based on the code in your question:
client.on('clickButton', async (button) => {
await button.clicker.fetch();
await button.reply.defer();
const user = button.clicker.user;
const hiEmbed = new Discord.MessageEmbed()
.addField(ticketMsg, "\n\nDo a.close or press the button to close the ticket")
.setColor("RANDOM")
.setTimestamp();
const closeTicketButton = new MessageButton()
.setID("ticketClose")
.setLabel("Close ticket")
.setStyle("red");
if (button.id === 'ticketCreate') {
button.guild.channels.create(`ticket-${user.id}`, {
permissionOverwrites: [
{
id: user.id,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
},
{
id: button.message.guild.roles.everyone,
deny: ['VIEW_CHANNEL'],
},
],
type: 'text',
}).then(async (channel) =>{
channel.send({embed: hiEmbed, button: closeTicketButton })
})
} else if(button.id == 'ticketClose'){
button.message.channel.delete()
}
});
You may have noticed another problem with this: the ticketMsg
variable will not be defined. You will need to make changes to solve that issue as well. I would recommend saving the value of ticketMsg
to a JSON file or database, and accessing that information within your client.on("clickButton")
. If this code represents a proper ticketing system, you will need to do this regardless of whether you use this solution or not, as otherwise your users will need to use ticket-setup
to setup the ticketing system again every time your bot restarts.
Upvotes: 3
Reputation: 9041
I had this problem too, but instead of interaction failed, I got incomplete button info.
client.ws.on('INTERACTION_CREATE', interaction => {
//complete interaction
})
Buttons are interactions which trigger this, and you can check whether this is a slash command or button with interaction.data.custom_id
(This may be wrong, I couldn’t test it). It will be undefined if it isn’t a button, but will hold the custom id of the button if it is a button.
Upvotes: 0