Why can't I use an interaction collector in a slash command? - discord.js

const { SlashCommandBuilder } = require("#discordjs/builders");
const {
MessageEmbed,
MessageActionRow,
MessageSelectMenu,
} = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("setup")
.setDescription("Setup the bot to your server!"),
async execute(interaction) {
let array = [];
await interaction.guild.members.cache.forEach(async (user) => {
if (user.user.bot === false || user.user.id === "925077132865052702")
return;
array.push({
label: user.user.username,
description: user.id,
value: user.id,
emoji: "<a:right:926857658500251668>",
});
});
let row;
if (array < 5) {
row = new MessageActionRow().addComponents(
new MessageSelectMenu()
.setCustomId("select")
.setMinValues(1)
.setMaxValues(parseInt(array.length))
.setPlaceholder("Nothing selected.")
.addOptions(array)
);
} else {
row = new MessageActionRow().addComponents(
new MessageSelectMenu()
.setCustomId("select")
.setMinValues(1)
.setMaxValues(5)
.setPlaceholder("Nothing selected.")
.addOptions(array)
);
}
let welcome = new MessageEmbed()
.setTitle("UChecker | Setup")
.setDescription(
"Please select from the dropdown below all the bots you would like to be notified for."
)
.setColor("FUCHSIA");
let message = await interaction.reply({
embeds: [welcome],
components: [row],
ephemeral: true,
});
const filter = i => {
return i.user.id === interaction.user.id;
};
await message.awaitMessageComponent({ filter, componentType: 'SELECT_MENU', time: 60000 })
.then(async interaction => await interaction.editReply(`You selected ${interaction.values.join(', ')}!`))
.catch(err => console.log(`No interactions were collected.`));
},
};
Here is my code. As you can see at the bottom I am using awaitMessageComponent and it says an error:
TypeError: Cannot read properties of undefined (reading 'createMessageComponentCollector')
at Object.execute (C:\Users\Owner\Desktop\UChecker\src\setup.js:55:31)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Client.<anonymous> (C:\Users\Owner\Desktop\UChecker\index.js:38:3)
C:\Users\Owner\Desktop\UChecker\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:90
if (this.deferred || this.replied) throw new Error('INTERACTION_ALREADY_REPLIED');
^
Error [INTERACTION_ALREADY_REPLIED]: The reply to this interaction has already been sent or deferred.
at CommandInteraction.reply (C:\Users\Owner\Desktop\UChecker\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:90:46)
at Client.<anonymous> (C:\Users\Owner\Desktop\UChecker\index.js:41:21)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
[Symbol(code)]: 'INTERACTION_ALREADY_REPLIED'
}
I am confused as I thought you could edit a reply? Could someone please help me out because I am really confused. I have created a reply so then it can be edited by the interaction collector and it says it has already replied.

You have to use CommandInteraction#fetchReply() to retrieve the reply message.
await interaction.reply({
embeds: [welcome],
components: [row],
ephemeral: true,
});
const message = await interaction.fetchReply();

Interaction replies are not returned unless you specify fetchReply: true in the options
let message = await interaction.reply({
embeds: [welcome],
components: [row],
ephemeral: true,
fetchReply: true
})

Related

TypeError: command.execute is not a function

I am aware that this problem has been discussed already, but I don't seem to fit the solutions found into my code. I've created some commands to this bot and they seem to work, although they are only basic slash commands (e.g. /ping). This problem came in when I try to run a moderation command or a play command.
This is the code with the error
const { Interaction } = require("discord.js");
module.exports = {
name: 'interactionCreate',
async execute(interaction, client) {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return
try{
await command.execute(interaction, client);
} catch (error) {
console.log(error);
await interaction.reply({
content: 'A aparut o eroare cu aceasta comanda!',
ephemeral: true
});
}
},
};
None of the fixes that I found seem to fit, at least to my rather unexperienced eye.
The command I try to run is this:
const { SlashCommandBuilder } = require("#discordjs/builders")
const { MessageEmbed } = require("discord.js")
const { QueryType } = require("discord-player")
module.exports = {
data: new SlashCommandBuilder()
.setName("play")
.setDescription("Asculta muzica")
.addSubcommand((subcommand)=>
subcommand
.setName("song")
.setDescription("Incarca o singura melodie printr-un url")
.addStringOption((option) => option.setName("url").setDescription("url-ul melodiei").setRequired(true)))
.addSubcommand((subcommand) =>
subcommand
.setName("playlist")
.setDescription("Incarca un playlist printr-un url")
.addStringOption((option) => option.setName("url").setDescription("url-ul playlist-ului").setRequired(true)))
.addSubcommand((subcommand) =>
subcommand
.setName("search")
.setDescription("Cauta o melodie pe baza cuvintelor-cheie")
.addStringOption((option) =>
option.setName("searchterms").setDescription("the search keywords").setRequired(true))),
run: async ({ client, interaction }) => {
if (interaction.member.voice.channel)
return interaction.editReply("Trebuie sa fii pe un voice channel pentru a folosi aceasta comanda!")
const queue = await client.player.createQueue(interaction.guild)
if (!queue.connection) await queue.connect(interaction.member.voice.channel)
let embed = new MessageEmbed()
if (interaction.options.getSubcommand() === "song"){
let url = interaction.options.getString("url")
const result = await client.player.search(url, {
requestedBy: interaction.user,
searchEngine: QueryType.YOUTUBE_VIDEO
})
if (result.tracks.length === 0)
return interaction.editReply("Niciun rezultat")
const song = result.tracks[0]
await queue.addTrack(song)
embed
.setDescription(`**[${song.title}](${song.url})**a fost adaugata`)
.setFooter({ text: `Durata: ${song.duration}`})
} else if (interaction.options.getSubcommand() === "playlist"){
let url = interaction.options.getString("url")
const result = await client.player.search(url, {
requestedBy: interaction.user,
searchEngine: QueryType.YOUTUBE_PLAYLIST
})
if (result.tracks.length === 0)
return interaction.editReply("Niciun rezultat")
const playlist = result.tracks
await queue.addTrack(result.tracks)
embed
.setDescription(`**${result.tracks.length} melodii din [${playlist.title}](${playlist.url})**a fost adaugata`)
.setFooter({ text: `Durata: ${playlist.duration}`})
} else if (interaction.options.getSubcommand() === "search"){
let url = interaction.options.getString("seatchterms")
const result = await client.player.search(url, {
requestedBy: interaction.user,
searchEngine: QueryType.AUTO
})
if (result.tracks.length === 0)
return interaction.editReply("Niciun rezultat")
const song = result.tracks[0]
await queue.addTrack(song)
embed
.setDescription(`**[${song.title}](${song.url})**a fost adaugata`)
.setFooter({ text: `Durata: ${song.duration}`})
}
if (!queue.playing) await queue.play()
await interaction.editReply({
embeds: [embed]
})
}
}
and the corresponding error:
TypeError: command.execute is not a function
at Object.execute (C:\Users\shelby\Bot\src\events\interactionCreate.js:15:27)
at Client.<anonymous> (C:\Users\shelby\Bot\src\functions\handelEvents.js:8:58)
at Client.emit (node:events:513:28)
at InteractionCreateAction.handle (C:\Users\shelby\Bot\node_modules\discord.js\src\client\actions\InteractionCreate.js:97:12)
at module.exports [as INTERACTION_CREATE] (C:\Users\shelby\Bot\node_modules\discord.js\src\client\websocket\handlers\INTERACTION_CREATE.js:4:36)
at WebSocketManager.handlePacket (C:\Users\shelby\Bot\node_modules\discord.js\src\client\websocket\WebSocketManager.js:352:31)
at WebSocketShard.onPacket (C:\Users\shelby\Bot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:489:22)
at WebSocketShard.onMessage (C:\Users\shelby\Bot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:328:10)
at callListener (C:\Users\shelby\Bot\node_modules\ws\lib\event-target.js:290:14)
at WebSocket.onMessage (C:\Users\shelby\Bot\node_modules\ws\lib\event-target.js:209:9)
You should be using command.run() instead of command.execute(), as your exported Slash Command uses this property name to store the core function.
const { Interaction } = require("discord.js");
module.exports = {
name: 'interactionCreate',
async execute(interaction, client) {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return
try{
await command.run({ interaction, client });
} catch (error) {
console.log(error);
await interaction.reply({
content: 'A aparut o eroare cu aceasta comanda!',
ephemeral: true
});
}
},
};
Additionally, you have to use an object that contains your interaction and client to run the function instead of using two arguments.

Discord.js Ticket system doesn't send an ephemeral message

I'm trying to make a ticket system with discord.js v13, but the ephemeral method doesn't work and, when my bot turn on, i need to click one time in the button to activate the system.
print
My code:
const { MessageActionRow, MessageButton, MessageEmbed, Permissions } = require('discord.js');
const db = require("quick.db");
exports.run = async (client, interaction) => {
if (!interaction.isButton()) return;
interaction.deferUpdate();
let getContador = await db.get('counter')
if(getContador === null) {
let contador = await db.set("counter", 1)
}
await db.add("counter", 1)
let tcID = "895323735702253569"
let tmID = "895358127950659604"
const filter = i => i.customId === 'OPENTICKET'
const collector = interaction.channel.createMessageComponentCollector({ filter, max: 1 });
collector.on("collect", async i => {
let cTicket = await i.guild.channels.create(`πŸŽ«β”†Ticket ${getContador}`, {
type: 'GUILD_TEXT',
permissionOverwrites: [
{
id: i.guild.id,
deny: [Permissions.FLAGS.VIEW_CHANNEL],
},
{
id: i.user.id,
allow: [Permissions.FLAGS.VIEW_CHANNEL, Permissions.FLAGS.SEND_MESSAGES],
},
]
})
await interaction.channel.messages.cache.get(tmID).reply({ content: `... ${cTicket.toString()}...`, ephemeral: true })
})
}
You are replying to a normal message. If you would like an ephemeral message, you have to directly reply to the interaction.
interaction.reply({
content: `... ${cTicket.toString()}...`,
ephemeral: true
})

discord.js get message id from interaction message

I want to get message id from interaction message, but i can't get it :|
discord.js verson : ^13.1.0
client.on('interactionCreate',async interaction => {
if(interaction.commandName==='test') {
let message = await interaction.reply({content:'testing...',ephemeral:true});
console.log(message); //undefined
}
});
You can use the CommandInteraction#fetchReply() method to fetch the Message instance of an initial response.
Example:
client.on('interactionCreate', async (interaction) => {
if (interaction.commandName === 'test') {
interaction.reply({
content: 'testing...',
ephemeral: true,
})
const message = await interaction.fetchReply()
console.log(message)
}
})
For latest version of Discord.js:
You can use the fetchReply property of InteractionReplyOptions to fetch the Message object after send it.
let message = await interaction.reply({content:'testing...',ephemeral:true, fetchReply: true});
console.log(message); //Message Object

TypeError: Cannot read properties of null (reading 'id')

So I was updating my bot to discord.js v13 and apparently my logging system has now broke, for some reason it can't read the ID of the guild where this log is occurring.
banAdd.js
const { MessageEmbed} = require("discord.js");
const {red_light} = require("../../other/colors.json");
const Channel = require('../../models/ModerationModel.js');
module.exports = async (bot, guild, user) => {
const guildDB = await Channel.findOne({
guildId: guild.id
}, async (err, guild) => {
if(err) console.error(err)
if (!guild) {
const newGuild = new Channel({
guildId: guild.id,
modChannel: null,
msgChannel: null
});
await newGuild.save().then(result => console.log(result)).catch(err => console.error(err));
}
});
const modChannel = guild.channels.cache.get(guildDB.modChannel);
if (!modChannel) {
return console.log(`No message channel found`);
}
let mEmbed = new MessageEmbed()
.setAuthor(`Member Unbanned`, user.displayAvatarURL({dynamic : true}))
.setColor(red_light)
.setDescription(`${user} ${user.tag}`)
.setThumbnail(`${user.displayAvatarURL({dynamic : true})}`)
.setFooter(`ID: ${user.id}`)
.setTimestamp()
modChannel.send({embeds:[mEmbed]});
}
Error
/home/runner/switch-beta-test/events/guild/banRemove.js:13
guildId: guild.id,
^
TypeError: Cannot read properties of null (reading 'id')
at /home/runner/switch-beta-test/events/guild/banRemove.js:13:27
at /home/runner/switch-beta-test/node_modules/mongoose/lib/model.js:5074:18
at processTicksAndRejections (node:internal/process/task_queues:78:11)
I have no idea why this is not working as it works in previous versions but updating to discord.js V13 completely broke this system. I tried looking at any possible solution but I can't find a single solution.
The cause of this error was because guild can no longer be defined during a users ban or unban, guild and user should be replaced with ban in both the unban and ban logs.
CODE
const { MessageEmbed} = require("discord.js");
const {red_light} = require("../../other/colors.json");
const Channel = require('../../models/ModerationModel.js');
module.exports = async (bot, ban) => {
const guildDB = await Channel.findOne({
guildId: ban.guild.id
}, async (err, guild) => {
if(err) console.error(err)
if (!guild) {
const newGuild = new Channel({
guildId: ban.guild.id,
modChannel: null,
msgChannel: null
});
await newGuild.save().then(result => console.log(result)).catch(err => console.error(err));
}
});
const modChannel = ban.guild.channels.cache.get(guildDB.modChannel);
if (!modChannel) {
return console.log(`No message channel found`);
}
let mEmbed = new MessageEmbed()
.setAuthor(`Member Unbanned`, ban.user.displayAvatarURL({dynamic : true}))
.setColor(red_light)
.setDescription(`${ban.user} ${ban.user.tag}`)
.setThumbnail(`${ban.user.displayAvatarURL({dynamic : true})}`)
.setFooter(`ID: ${ban.user.id}`)
.setTimestamp()
modChannel.send({embeds:[mEmbed]});
}
After this the error should no longer show.
The error says that the guild variable is empty doesn't have a value null and when you do guild.id you're trying to access a property that don't exist
Make sure that the guild variable is assigned to a value
Probably they add some changes to the new version of npm package go check the docs

JavaScript discord bot TypeError: Cannot read property 'guild' of undefined

I am trying this JavaScript ticket code in my discord bot, but the error TypeError: Cannot read property 'guild' of undefined keeps showing up. I don't understand why. Could someone guide me in the correct direction?
module.exports = {
name: "ticket",
aliases: [],
permissions: [],
description: "Open a ticket!",
async execute(message, args, cmd, client, discord) {
const channel = await message.guild.channels.create(`ticket: ${message.author.tag}`);
channel.setParent("820276801652916270");
channel.updateOverwrite(message.guild.id, {
SEND_MESSAGE: false,
VIEW_CHANNEL: false,
});
channel.updateOverwrite(message.author, {
SEND_MESSAGE: true,
VIEW_CHANNEL: true,
});
const reactionMessage = await channel.send("Thank you for contacting support!");
try {
await reactionMessage.react("πŸ”’");
await reactionMessage.react("β›”");
} catch (err) {
channel.send("Error sending emojis!");
throw err;
}
const collector = reactionMessage.createReactionCollector(
(reaction, user) => message.guild.members.cache.find((member) => member.id === user.id).hasPermission("ADMINISTRATOR"),
{ dispose: true }
);
collector.on("collect", (reaction, user) => {
switch (reaction.emoji.name) {
case "πŸ”’":
channel.updateOverwrite(message.author, { SEND_MESSAGES: false });
break;
case "β›”":
channel.send("Deleting this channel in 5 seconds!");
setTimeout(() => channel.delete(), 5000);
break;
}
});
message.channel
.send(`We will be right with you! ${channel}`)
.then((msg) => {
setTimeout(() => msg.delete(), 7000);
setTimeout(() => message.delete(), 3000);
})
.catch((err) => {
throw err;
});
},
}
Using the info in your comment, your command handler was set up incorrectly. When you put execute(message.args), the code tried to pass the args property of your message argument which returns undefined.
Instead, you should use execute(message, args) to properly pass in each argument for your command.

Resources