I have a command handler for my discord bot. It loads the command modules fine, (and console logs indicate as much), but I'm having trouble getting it to execute commands beyond the first command module. Here's the code:
const Discord = require("discord.js");
const client = new Discord.Client();
client.commands = new Discord.Collection();
const prefix = "f$";
const fs = require("fs");
try {
const files = fs.readdirSync("./commands/");
let jsFiles = files.filter(filename => filename.split(".").pop() === "js");
for (const filename of jsFiles) {
let command = require(`./commands/${filename}`);
if (!command) return console.error(`Command file '${filename}' doesn't export an object.`);
client.commands.set(command.name, command);
console.log(`Loaded command: ${command.name}`);
}
} catch (err) {
console.error(`Error loading command: '${err}'`);
}
console.log("Finished loading\n");
client.on("ready", () => {
console.log("Client ready!");
});
client.on("message", async message => {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
let args = message.content.slice(prefix.length).trim().split(/ +/g);
//console.log(args);
let cmdName = args.shift().toLowerCase();
for (const command of client.commands.values()) {
console.log(command.name);
console.log(cmdName);
console.log(command === cmdName);
if (command.name !== cmdName /*&& !command.aliases.includes(cmdName)*/) return;
try {
await command.executor(message, args, client);
} catch (err) {
console.error(`Error executing command ${command.name}: '$```{err.message}'`);
}
}
});
client.login(TOKEN).catch(err => console.log(`Failed to log in: ${err}`));
and in each command module you have this bit:
module.exports = {
name: "command",
description: "description of command",
aliases: [],
executor: async function (message, args, client) {
(I have not done aliases for this yet, so alias lines are either empty or remmed out.)
You've incorrectly referenced your variable in the template literal which meant lots of your code was ignored, this likely is the entirety of the problem, it should look like this:
console.error(`Error executing command ${command.name}: ${err.message}`);
For guidance regarding template literals use https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals. If you wanted to use the ``` but have them ignored use this code:
console.error(`Error executing command ${command.name}: \`\`\` ${err.message} \`\`\` `);
In addition on your execute function you don't have closing braces so that should be:
module.exports = {
name: "command",
description: "description of command",
aliases: [],
executor: async function (message, args, client) {
// code to be executed
}
Related
I am trying to make a discord bot with discordJS (v14) and I followed the tutorial from
https://discordjs.guide/creating-your-bot/slash-commands.html#individual-command-files and created a slash command. However, when I call the slash command, it always shoe DiscordAPIError[10062]: Unknown interaction I tried to use the command await interaction.deferReply() but it still failed.
Here are my code of that function
play.js
const { SlashCommandBuilder } = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("play")
.setDescription("Play the song from the url or search query")
.addStringOption(option =>
option.setName("query")
.setDescription("The url or search query")
.setRequired(true)
),
async execute(interaction) {
console.log("interaction received"); // This part can run
await interaction.deferReply()
console.log("play command executed"); // cannot run
await interaction.editReply({ content: interaction.options.getString("query"), ephemeral: true });
}
}
index.js
const fs = require('node:fs');
const path = require('node:path');
const {
Client,
Collection,
Events,
GatewayIntentBits,
REST,
Routes,
} = require('discord.js');
require("dotenv").config();
// Tokens
const BOT_TOKEN = process.env.DISCORD_TOKEN;
const CLIENT_ID = process.env.CLIENT_ID;
// Create a new client instance
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const rest = new REST({ version: 10 }).setToken(BOT_TOKEN);
// When the client is ready, run this code (only once)
// We use 'c' for the event parameter to keep it separate from the already defined 'client'
client.once(Events.ClientReady, c => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
// Create a new collection for commands
client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
// Set a new item in the Collection with the key as the command name and the value as the exported module
if ('data' in command && 'execute' in command) {
client.commands.set(command.data.name, command);
} else {
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
console.log(interaction);
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
console.log(`Executing ${interaction.commandName} command.`);
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
});
const commands = [];
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
console.log(command.data.toJSON());
commands.push(command.data.toJSON());
}
// try to register the slash commands
(async () => {
try {
console.log(`Started refreshing ${commands.length} application (/) commands.`);
// The put method is used to fully refresh all commands in the guild with the current set
const data = await rest.put(
Routes.applicationCommands(CLIENT_ID),
{ body: commands },
);
console.log(`Successfully reloaded ${data.length} application (/) commands.`);
// Log in to Discord with your client's token
client.login(BOT_TOKEN);
} catch (error) {
// And of course, make sure you catch and log any errors!
console.error(error);
}
})();
The terminal result shows that it received the message but it continue to have the error
DiscordAPIError[10062]: Unknown interaction
May I ask how can I solve the problem and why it would happen?
this code is not executing the desired function which is to be able to initiate a message to repeat on a set interval. When debugging there are no errors and the bot comes online fine but the command can't be used and it says nothing to suggest what the problem is.
I need a professionals help to identify the reason this code is not working and why the bot acts as if it does not even exist.
This is the shortest amount of code to replicate the results I have left out the config.json because it has my token but I know for sure that that file is configured properly anyway
Test.ts file in commands folder
const Discord = require("discord.js");
const source = require('../index');
module.exports.run = (Client, message, args) => {
if (!args [0]) return message.reply(`Please specify if you are turning the command on or off!`);
if (args[1]) return message.reply(`Please specify if you are turning the command on or off! [Too many Arguments!]`);
switch (args[0])
{
default:
{
message.reply('Invalid argument specified.')
break;
}
case "on":
{
if (!source.timedCheck){
source.timedCheck =setInterval(() =>{
// Function for set interval
console.log("Interval cycle run!" + (val++) + "times!");
valcheck();
}, 25 * 10000);
message.reply('command started!');
} else {
return message.reply(`command already running!`)
}
break;
}
case "off":
{
if (source.timedCheck){
message.reply(`user has turned off command!`);
clearInterval(source.timedCheck);
source.timedCheck = undefined;
} else {
return message.reply(`command already offline!`)
}
break;
}
}
let valcheck = () => {
if (source.val > 5){
clearInterval(source.timedCheck);
source.timedCheck = undefined;
message.channel.send(`command finished as scheduled!`);
}
};
};
module.exports.help = {
name: "test",
usage: "test <on/off>"
};
Index.js file
// Require the necessary discord.js classes
const { Client, Intents } = require('discord.js');
const { token } = require('./config.json');
// Create a new client instance
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
// When the client is ready, run this code (only once)
client.once('ready', () => {
console.log('Ready!');
});
// Export variables for commands
module.exports.timedCheck = undefined;
module.exports.val = 0;
// Login to Discord with your client's token
client.login(token);
You didn't tell the bot to execute this command. In your Index file you have to require the command file, catch the "message" or the "interactionCreate" events and then execute your command.
This code is incomplete and I can only guide you in a direction as you miss many things in your code.
You should read a tutorial: https://discordjs.guide/creating-your-bot/creating-commands.html#command-deployment-script
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./src/commands');
// require every command and add to commands collection
for (const file of commandFiles) {
const command = require(`./src/commands/${file}`);
client.commands.set(command.name, command);
}
client.on('message', async message => {
// extract your args from the message, something like:
const args = message.content.slice(prefix.length).split(/ +/);
try {
command.execute(message, args, client); // provide more vars if you need them
} catch (error) {
// handle errors here
}
I am new to command handler I am trying to execute commands for different js file
but I get this error
TypeError: Cannot read property 'execute' of undefined
this is my main.js
// Import the discord.js module
const Discord = require('discord.js');
const fs = require('fs');
// Create an instance of a Discord client
const client = new Discord.Client();
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
const prefix = "$"
/**
* The ready event is vital, it means that only _after_ this will your bot start reacting to information
* received from Discord
*/
client.on('ready', () => {
console.log('I am ready!');
});
client.on('message', message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const command = args.shift().toLowerCase();
if(command === 'pingg'){
client.commands.get('pingg').execute(message, args);
}
if (!client.commands.has(command)) return;
try {
client.commands.get(command).execute(message, args);
} catch (error) {
console.error(error);
message.reply('there was an error trying to execute that command!');
}
});
client.login('censored');
fs.readdir("./commands/", (err, files) => {
if(err) console.error(error)
let jsfiles = files.filter(f => f.split(".").pop() === "js")
if (jsfiles.length <= 0) {
return console.log("No commands to log in FOLDER NAME")
}
console.log(`Loading ${jsfiles.length} commands from FOLDER NAME...`)
jsfiles.forEach((f,i) => {
let props = require(`./commands/${f}`)
console.log(`${i + 1}: ${f} loaded!`)
client.commands.set(f, props)
})
})
my ping.js
module.exports = {
name : 'pingg',
description : 'Test',
execute(message, args){
message.channel.send('pongg')
}
}
The commands are registered in client.commands collection in the bot application lifecycle after the client is ready.
This is because client.login is invoked before it.
You can use commandFiles to load the commands from their modules. This was already performed sychronously so you have some guarantee on the order.
Also do that before the client.login statement.
Another issue is that the command module is named ping.js and as such your current implementation registers ping command to client.command collection.
However, you are resolving pingg command from the collection which returns an undefined
commandFiles.forEach(file => {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
});
client.login('censored');
//...
I explain my problem: I use a js file external to my commands for my Events and I have the impression that there are some things that do not work correctly in my messageCreate.js which however worked before with Discord .JS in version 12.
For example, when I want to return as soon as the bot sends a message it doesn't work via the messageCreate.js, I have to put it in all of my commands etc.
In my commands I noticed that the arguments do not work whereas before I had no problems. I was able to verify this by putting a
if(args == undefined) return console.log("test")
and the message "test" was displayed in the console as soon as I tried.
I put my code below, hoping you can help me. :)
the part of my index.js that deals with events:
fs.readdir("./Events/", (err, files) => {
Debug.logs(`[${chalk.cyan(moment(Date.now()).format('h:mm:ss'))}] ${chalk.cyan('Chargement des évènements ...')}`)
if (err) return Debug.logs(err)
files.forEach(async (file) => {
if (file.endsWith(".js")) {
const event = require(`./Events/${file}`)
let eventName = file.split(".")[0]
try {
bot.on(eventName, event.bind(null, bot))
delete require.cache[require.resolve(`./events/${file}`)]
Debug.logs(`[${chalk.cyan(moment(Date.now()).format('h:mm:ss'))}] ${chalk.green('Event Chargé :')} ${chalk.cyan(file)}`)
} catch (error) {
Debug.logs(error)
}
} else {
return
}
})
})
my messageCreate.js :
const env = process.env
const chalk = require('chalk')
const moment = require('moment')
const Debug = require('../utils/Debug')
const config = require("../config.json")
module.exports = async (bot, message) => {
if(message.channel.type === "DM"){
if(message.author.bot) return;
message.reply("Les commandes en **messages privés** sont actuellement **désactivées** !")
Debug.logs(`[${chalk.cyan(moment(Date.now()).format('h:mm:ss'))}] [${chalk.yellow(message.author.tag)}] a envoyé ${chalk.green(message.content)} en DM`)
}else{
if (!message.author.bot) {
if (message.content.startsWith(config.prefix)) {
const args = message.content.slice(config.prefix.length).trim().split(/ +/g)
const command = args.shift().toLowerCase()
const cmd = bot.commands.get(command)
if (cmd) {
await cmd.run(bot, message, args)
Debug.logs(`[${chalk.cyan(moment(Date.now()).format('h:mm:ss'))}] [${chalk.yellow(message.author.tag)}] a utilisé ${chalk.green(command)} ${chalk.cyan(args.join(" "))}`)
} else {
return
}
} else {
return
}
} else {
return
}
}
}
and one exemple of command who not work with messageCreate.js :
const Discord = require("discord.js");
module.exports.run = async (bot, message, config, args) => {
message.delete();
if(args == undefined) return console.log("wtf that not work ?")
}
module.exports.help = {
name:"test",
desc:"test commands !",
usage:"test",
group:"autre",
examples:"$test"
}
module.exports.settings = {
permissions:"false",
disabled:"false",
owner:"false"
}
as soon as I run the command with argument or without any argument, in both cases the console receives the message "wtf that not work?"
I hope you can help me! thanks in advance :)
Sorry if my english is bad but i'm french, not english !
In messageCreate.js, you call your command with the following:
// 3 arguments
await cmd.run(bot, message, args);
However, your command's run function is defined with 4 parameters:
async (bot, message, config, args) => {
// config = 'args', and args = undefined
}
To fix the issue, either:
Pass in a value for config, such as null:
await cmd.run(bot, message, null, args);
Make your function only have 3 parameters:
async (bot, message, args) => {
// ...
}
I'm writing a NodeJS application that can do some queueing in Discord. My main includes an array called queuedPlayers and is defined in the following code:
// Define our required packages and our bot configuration
const fs = require('fs');
const config = require('./config.json');
const Discord = require('discord.js');
// Define our constant variables
const bot = new Discord.Client();
const token = config.Discord.Token;
const prefix = config.Discord.Prefix;
let queuedPlayers = [];
// This allows for us to do dynamic command creation
bot.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
bot.commands.set(command.name, command)
}
// Event Handler for when the Bot is ready and sees a message
bot.on('message', message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(' ');
const command = args.shift().toLowerCase();
if (!bot.commands.has(command)) return;
try {
bot.commands.get(command).execute(message, args);
} catch (error) {
console.error(error);
message.reply('There was an error trying to execute that command!');
}
});
// Start Bot Activities
bot.login(token);
I then create a command in a seperate JS file and I am trying to access the Queued Players array so that way I can add to them:
module.exports = {
name: "add",
description: "Adds a villager to the queue.",
execute(message, args, queuedPlayers) {
if (!args.length) {
return message.channel.send('No villager specified!');
}
queuedPlayers.push(args[0]);
},
};
However, it keeps telling me that it is undefined and can't read the attributes of the variable. So I'm assuming it isn't passing the array over properly. Do I have to use an exports in order to able to access it between different Javascript files? Or would it be best just to use a SQLite local instance to create and manipulate the queue as needed?
It's undefined because you aren't passing the array
Change
bot.commands.get(command).execute(message, args);
to
bot.commands.get(command).execute(message, args, queuedPlayers);