Reputation: 11
I am trying to code this discord bot by using Javascript and I am currently following the discordjs guide step by step and I am making the exact same steps as the guide. Now I am currently learning about the dynamic commands and it seems I've got stuck for like 4 days in this big hole. The problem is that the command handler does detect the command files inside the commands folder but it only detects the last command in that order. This is the code in my bot.js file from my main folder:
const fs = require('fs');
const {prefix, token} = require('./config.json');
const Discord = require('discord.js');
const client = new Discord.Client();
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
client.once('ready', () =>{
console.log('Imperial Bot is online!');
});
client.on('message', message => {
console.log(message.content);
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const commandName = args.shift().toLowerCase();
if (!client.commands.has(commandName)) return;
const command = client.commands.get(commandName);
try {
command.execute(message, args);
} catch (error) {
console.error(error);
message.reply('there was an error trying to execute that command!');
}
})
client.login(token);
And this is the code in the file fun.js from the commands folder:
module.exports = {
name: 'avatar',
description: '...',
execute(message, args){
if(!message.mentions.users.size){
message.channel.send(`Poza ta de profil: <${message.author.displayAvatarURL({ format: "png", dynamic: true })}>`)
}
// the array of avatars of the tagged users get put in a constant and shown in the chat.
const avatarList = message.mentions.users.map(user => { //for every user tagged in the message, an avatar of theirs will get shown
return `Avatarul lui ${user.username}: <${user.displayAvatarURL({ format: "png", dynamic: true })}>`;
});
message.channel.send(avatarList);
},
}
module.exports = {
name: 'gaymeter',
description: '...',
execute(message, args){
let gen = Math.floor(Math.random()*100 + 1);
let tagged = message.mentions.users.first();
if(!args[0]){
message.channel.send(`Esti ${gen}% gay!`);
} else {
message.channel.send(`${tagged.username} este ${gen}% gay! :gay_pride_flag: `);
}
}
}
module.exports = {
name: 'delete',
description: '...',
execute(message, args){
let checkINT = parseInt(args[0]);
let amount = args[0];
if(isNaN(checkINT) || !args[0]){
message.channel.send("Trebuie precizat un numar.");
} else if(amount < 2 || amount > 99){
message.channel.send("Limita de mesaje care pot fii sterse este intre 2 si 99.");
} else {
message.channel.bulkDelete(amount, true);
message.reply(`sterse ${amount} mesaje!`).catch(err => {
console.error(err);
message.channel.send('Eroare! Nu au putut fii sterse mesajele.');
});
}
},
}
If I run the bot, the only command that it detects is the delete command which is the last one in that file. My question is how can I arrange or fix the code so that all the module.exports work in that fun.js file and not only that delete command? Do I have to put only one command in one module export and make separate files for each command?
Upvotes: 1
Views: 391
Reputation: 1245
What I assume you want to achive by putting all the commands into one file is to create a category. Here is a way to do that more effectively. And yes, you need to create separate files for all your commands.
We create another folder inside your commands folder and place the commands in there.
Note: because this is a dynamic way of creating categories you can just add additional folders and a new category is born.
Your folder structure should look something like this
-- Your bot folder
- index.js
- package.json
- package-lock.json
-- commands
-- fun
- kick.js
- ban.js
-- some other category
Now we need to include a litte something in your command reader.
// create a new collection called catergories
client.categories = new Discord.Collection();
client.aliases = new Discord.Collection(); // only if you want aliases
// Read every commands subfolder
fs.readdirSync("./commands/").forEach(dir => {
// Read all files in the commands folder and that ends in .js
const commands = fs.readdirSync(`./commands/${dir}/`).filter(file => file.endsWith(".js"));
// Loop over the commands, and add all of them to a collection
// If there's no name found, prevent it from returning an error
for (let file of commands) {
const command = require(`../commands/${dir}/${file}`);
// Check if the command has a name, a category and a description
// add or remove things here as you need
if (command.name && command.category && command.description) {
client.commands.set(command.name, command);
} else {
console.log("A file is missing something");
continue;
}
// use this if you wish to include an alias array in your commands
// check if there is an alias and if that alias is an array
if (command.aliases && Array.isArray(command.aliases))
command.aliases.forEach(alias => client.aliases.set(alias, command.name));
};
})
Note: if you want to use aliases you need to check for them in your command handler after no command has been found.
// you only need this if you want to use aliases
if (!command) command = client.commands.get(client.aliases.get(commandName));
Now you should include the category in your command file.
module.exports = {
name: 'avatar',
description: '...',
category: "fun",
aliases: ["all", "your", "aliases"], // this is optional
execute(message, args) {
// your code
}
}
Upvotes: 1