Receiving button interactions

Hello there, I'd like some help regarding button interactions. I know how to build a button row and send it (see code below) But I don't know how to receive interactions from it... I've read this page : https://discordjs.guide/interactions/buttons.html#receiving-button-interactions But still. So if someone can help a bit with that, it'd be appreciated ! :)
discord.js Guide
Imagine a guide... that explores the many possibilities for your discord.js bot.
9 Replies
Unknown User
Unknown User15mo ago
Message Not Public
Sign In & Join Server To View
RAH3RI
RAH3RI15mo ago
-- discord.js@14.8.0 v16.16.0
const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
const { ownerID } = require('../config.json');
const { spamChannelID } = require('../config.json').channelIDs;
const { rawRulesMessageIDs } = require('../config.json').messageIDs;
const { viewerRoleID } = require('../config.json').roleIDs;

module.exports = {
data: new SlashCommandBuilder()
.setName("rules-messages")
.setDescription("Sends the rules messages to the channel")
.setDefaultMemberPermissions(0),

async execute(interaction) {

// Only allow the bot owner to use this command (double security)
if (interaction.user.id !== ownerID) {
interaction.reply({ content: 'Seul le propriétaire du bot peut utiliser cette commande.', ephemeral: true });
return;
}

// Get the channels
const channel = interaction.channel;
const spamChannel = interaction.guild.channels.cache.get(spamChannelID);

// Build the button row
const buttonRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('acceptRulesMessage')
.setLabel('Accepter le règlement')
.setStyle(ButtonStyle.Success),
);

// Send the messages (iterate through the message IDs)
for (const messageID of rawRulesMessageIDs) {
const message = (await spamChannel.messages.fetch(messageID));
await channel.send(message.content);
}

// Send the button row
await channel.send({ content: 'Pour accepter le règlement et accéder au reste du serveur, cliquez sur le bouton ci-dessous', components: [buttonRow] });

// Confirm the command was sent
interaction.reply({ content: 'Roles message sent.', ephemeral: true });
const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
const { ownerID } = require('../config.json');
const { spamChannelID } = require('../config.json').channelIDs;
const { rawRulesMessageIDs } = require('../config.json').messageIDs;
const { viewerRoleID } = require('../config.json').roleIDs;

module.exports = {
data: new SlashCommandBuilder()
.setName("rules-messages")
.setDescription("Sends the rules messages to the channel")
.setDefaultMemberPermissions(0),

async execute(interaction) {

// Only allow the bot owner to use this command (double security)
if (interaction.user.id !== ownerID) {
interaction.reply({ content: 'Seul le propriétaire du bot peut utiliser cette commande.', ephemeral: true });
return;
}

// Get the channels
const channel = interaction.channel;
const spamChannel = interaction.guild.channels.cache.get(spamChannelID);

// Build the button row
const buttonRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('acceptRulesMessage')
.setLabel('Accepter le règlement')
.setStyle(ButtonStyle.Success),
);

// Send the messages (iterate through the message IDs)
for (const messageID of rawRulesMessageIDs) {
const message = (await spamChannel.messages.fetch(messageID));
await channel.send(message.content);
}

// Send the button row
await channel.send({ content: 'Pour accepter le règlement et accéder au reste du serveur, cliquez sur le bouton ci-dessous', components: [buttonRow] });

// Confirm the command was sent
interaction.reply({ content: 'Roles message sent.', ephemeral: true });
Unknown User
Unknown User15mo ago
Message Not Public
Sign In & Join Server To View
RAH3RI
RAH3RI15mo ago
I'm having trouble finding out where to put my code, as I already have an interaction handler in my index.js for command (/) interactions and it then triggers the right command (which is in its own file) But as we're not talking about slash commands here, I'm not sure how to setup my file, what should I put instead of this :
module.exports = {
data: new SlashCommandBuilder()
module.exports = {
data: new SlashCommandBuilder()
For the functions which should be called on my button interaction thank you, I think it's more clear now, I'll give it a try and let you know if I finally got it :) 2nd option, should I export the customId in a data : ? Then what class should I use instead of SlashCommandBuilder ? Something like this then ?
module.exports = {
customId : "",

async execute(interaction) {

}
}
module.exports = {
customId : "",

async execute(interaction) {

}
}
Then I have an error when deploying commands :
commands.push(command.data.toJSON());
^
TypeError: Cannot read properties of undefined (reading 'toJSON')
commands.push(command.data.toJSON());
^
TypeError: Cannot read properties of undefined (reading 'toJSON')
Do I need to deploy it or is it useless and I should rather put the button files in a separate folder ? okay thanks
RAH3RI
RAH3RI15mo ago
ok so it looks like it's working (logs + rôle added correctly) but I still get this :
RAH3RI
RAH3RI15mo ago
well I handle it like that :
} else if (interaction.isButton()) {
// Buttons
const button = interaction.client.buttons.get(interaction.customId);

// Check if the button exists
if (!button) {
console.error(`No button matching ${interaction.customId} was found.`);
return;
}

try {
// Execute the button function
await button.execute(interaction);
// Log
console.log(`Button ${interaction.customId} executed by ${interaction.user.tag} in ${interaction.guild.name} at ${interaction.createdAt}`);

} catch (error) {
// Catch and log any errors
console.error(error);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({ content: "Il semblerait qu'il y ait eu une erreur...", ephemeral: true });
} else {
await interaction.reply({ content: 'Une erreur est survenue !', ephemeral: true });
}
}
} else if (interaction.isButton()) {
// Buttons
const button = interaction.client.buttons.get(interaction.customId);

// Check if the button exists
if (!button) {
console.error(`No button matching ${interaction.customId} was found.`);
return;
}

try {
// Execute the button function
await button.execute(interaction);
// Log
console.log(`Button ${interaction.customId} executed by ${interaction.user.tag} in ${interaction.guild.name} at ${interaction.createdAt}`);

} catch (error) {
// Catch and log any errors
console.error(error);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({ content: "Il semblerait qu'il y ait eu une erreur...", ephemeral: true });
} else {
await interaction.reply({ content: 'Une erreur est survenue !', ephemeral: true });
}
}
oh I didn't know I needed an interaction.reply(), I just added one anyway thank you again !
d.js docs
d.js docs15mo ago
Responding to interactions: • #reply immediately respond with a message • #update immediately update the original message (buttons, select menus)#showModal immediately show a modal (cannot be deferred)#deferReply/Update respond later (up to 15 minutes)#followUp post an additional message The initial response has to happen within 3s of receiving the interaction!
RAH3RI
RAH3RI15mo ago
got it :) oh and, as we're here, I'd like to move my handlers code to a dedicated file in a handlers folder (just so the code is cleaner) but I don't really know how to do that (I want to move those : https://discord.com/channels/222078108977594368/1089990904451960903/1090355280090509424) My problem is that I don't know how to exactly setup the file and have the index.js to run them correctly before login
d.js docs
d.js docs15mo ago
guide Creating Your Bot: Individual event files read more