I have a command handler in my main.js file and alias handler is in it too - But when I try to run a command with the alias I've set in module.exports.config it does not respond.
This is my command handler:
fs.readdir(`./commands/`, (error, files) => {
if (error) {return console.log("Error while trying to get the commmands.");};
files.forEach(file => {
const command = require(`./commands/${file}`);
const commandName = file.split(".")[0];
client.commands.set(commandName, command);
if (command.aliases) {
command.aliases.forEach(alias => {
client.aliases.set(alias, command.name)
});
};
});
});
client.on("message", async message => {
if(message.author.bot || message.channel.type === "dm") return;
let prefix = (";");
let messageArray = message.content.split(" ");
let cmd = messageArray[0].toLowerCase();
let args = messageArray.slice(1)
if(!message.content.startsWith(prefix)) return;
let commandfile = client.commands.get(cmd.slice(prefix.length)) || client.commands.get(client.aliases.get(cmd.slice(prefix.length)))
if(commandfile) commandfile.run(client,message,args)
})
And this is my module.exports.config:
module.exports.config = {
name: "eval",
description: "Eval a code",
aliases: ['debug']
};
You don't need to create a new collection for the aliases. You could use collection's .find() method and check if there is an alias with the command name.
So, inside fs.readdir you only set client.commands and when there is an incoming message, you can check if there is an exact command name (using client.commands.get) and if there is not, you check if the command has an aliases property. If it has, you can check if the aliases array includes the command.
Also, if you use cmd.slice(prefix.length) in more than one place and you don't use cmd anywhere, then you probably need to remove the prefix from the command.
The following should work as expected:
fs.readdir(`./commands/`, (error, files) => {
if (error) {
console.log(error);
return console.log('Error while trying to get the commmands.');
}
files.forEach((file) => {
const command = require(`./commands/${file}`);
const commandName = file.split('.')[0];
client.commands.set(commandName, command);
});
});
client.on('message', async (message) => {
let prefix = ';';
if (
message.author.bot ||
message.channel.type === 'dm' ||
!message.content.startsWith(prefix)
)
return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const commandName = args.shift().toLowerCase();
const command =
client.commands.get(commandName) ||
client.commands.find((cmd) => cmd.config?.aliases?.includes(commandName));
if (!command) return;
try {
command.run(client, message, args);
} catch (error) {
console.log('There was an error trying to run that command:');
console.log(error);
}
});
Related
Well, I have a doubt. I want to put "aliases" in my commands in discord.js, but I am stuck without knowing what to do. Help me if something is missing, please.
This is my index.js code
bot.commands = new Discord.Collection();
const commandFolders = fs.readdirSync('./commands')
for (const folder of commandFolders) {
const commandFiles = fs.readdirSync(`./commands/${folder}`).filter(file => file.endsWith('.js'))
for (const file of commandFiles) {
const command = require(`./commands/${folder}/${file}`)
bot.commands.set(command.name, command)
}
}
code 2:
bot.on('message', async (message) => {
if(!message.content.startsWith(process.env.PREFIX) || message.author.bot) return;
if (message.channel.type === 'dm') return;
const args = message.content.slice(process.env.PREFIX.length).split(' ');
const command = args.shift().toLowerCase();
try {
bot.commands.get(command).execute(bot, message, args)
} catch (e) {
message.channel.send('Utilize ``' + `${process.env.PREFIX}` + 'help`` para ver meus comandos.')
.then(message => setTimeout(() => message.delete(), 10000))
}
});
This is the part of the code of the commands, I put the aliases there but it is not working.
const execute = async (bot, message, args) => {
//code
};
module.exports ={
name: "ban",
aliases: ['b', 'banir'],
execute,
};
You need to check client.commands for a module that either has the name of args.shift().toLowerCase() or it's aliases array contains said argument
bot.on('message', async (message) => {
if(!message.content.startsWith(process.env.PREFIX) || message.author.bot) return;
if (message.channel.type === 'dm') return;
const args = message.content.slice(process.env.PREFIX.length).split(' ');
// Aliases Implementing starts here
const commandName = args.shift().toLowerCase();
const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if (!command) return;
try {
bot.commands.get(command).execute(bot, message, args)
} catch (e) {
message.channel.send('Utilize ``' + `${process.env.PREFIX}` + 'help`` para ver meus comandos.')
.then(message => setTimeout(() => message.delete(), 10000))
}
});
Here's an official aliases guide by Discordjs.guide
Simply register your aliases for a command along with the command name, like this:
for (const folder of commandFolders) {
const commandFiles = fs.readdirSync(`./commands/${folder}`).filter(file => file.endsWith('.js'))
for (const file of commandFiles) {
const command = require(`./commands/${folder}/${file}`)
bot.commands.set(command.name, command)
// Register aliases
for (let alias of command.aliases) {
bot.commands.set(alias, command)
}
}
}
The following line throws the error:
if (!client.commands.has(command)) return;
I'm following this tutorial= Tutorial
const fs = require('fs');
const Discord = require('discord.js');
const { prefix, token } = require("./config.json")
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.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 (message.content === `${prefix}serverinfo`) {
message.channel.send(message.guild.name)
message.channel.send(`Total Members: ${message.guild.memberCount}`)
} else if (message.content === `${prefix}me`) {
message.channel.send(`Username: ${message.author.username}`)
message.channel.send(`ID: ${message.author.id}`)
} else if (message.content === `${prefix}boi`) {
message.channel.send('BOI')
}
});
if (!client.commands.has(command)) return;
You can't return in the top scope, return must be inside a function.
You may either put the logic inside an if statement
if (client.commands.has(command)) {
const command = client.commands.get(command);
try {
command.execute(message, args);
} catch (error) {
console.error(error);
message.reply("There was an issue executing that command!")
}
client.login(token);
}
Or wrap the logic inside a function, an IIFE may be a good choice:
(() => {
if (!client.commands.has(command)) return;
const command = client.commands.get(command);
try {
command.execute(message, args);
} catch (error) {
console.error(error);
message.reply("There was an issue executing that command!")
}
client.login(token);
})();
So the error I'm receiving but cannot find is accepting any arguments as a valid command after a space. I believe this might be a .split() error, as if you match the arguments exactly it will produce a different output. Now if you use an argument that is not listed, it will still produce the original command, !qa = !qa mollusk
It should return an error, when an argument passes but is not present, but does not do so.
Here is my index and everything associated for replication:
const fs = require('fs');
const Discord = require('discord.js');
const { prefix, token } = require('./config.json');
const featureFiles = fs.readdirSync('./commands/features').filter(file => file.endsWith('.js'));
for (const file of featureFiles) {
const command = require(`./commands/features/${file}`);
client.commands.set(command.name, command);
}
client.on('message', message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
//.trim() is removed, see notes below on why
const args = message.content.slice(prefix.length).split(/ +/g);
const commandName = args.shift().toLowerCase();
const command = client.commands.get(commandName)
|| client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if (!command) return;
if (command.guildOnly && message.channel.type !== 'text') {
return message.reply('That command cannot be used inside a DM');
}
if (command.args && !args.length) {
let reply = `You didn't provide any arguments!`;
if (command.usage) {
reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``;
}
return message.channel.send(reply);
}
try {
command.execute(message, client, args);
} catch (error) {
console.error(error);
message.channel.send('Error trying to execute command');
}});
client.login(token);
I removed .trim() as it was reading whitespaces in between the prefix and command name, which I did not want, so one could use 100 spaces between the prefix and command, and it will execute it.
Here is my module I am building:
const Discord = require('discord.js');
module.exports ={
name: 'qa',
description: 'Find members who have the QA role and search by specialty.',
usage: '[OptionalArg]',
execute(message, client, args) {
if(message.channel.type === 'dm') {
message.channel.send('Command can\'t be used here')
}
try{
let roleID = "738530035526402100";
let membersWithRole = message.guild.roles.cache.get(roleID).members.map(m=>m.user.tag).join('\n');
const embed = new Discord.MessageEmbed()
.setColor('#008798')
.setTitle('Qualified Advice')
.setDescription(`${membersWithRole}`)
.setTimestamp(new Date)
const testing = new Discord.MessageEmbed()
.setColor('#008798')
.setTitle('Test QA')
.setDescription(`test`)
.setTimestamp(new Date)
const data =[embed];
if (args[0] === 'test') {
return message.channel.send(testing)
}
message.channel.send(data, 'To see focus types, type `!qa [arg]`, example `!qa test`', {split: true});
} catch(e) {
console.log(e)
}
},
};
Am I right for thinking it's found in .split()? This has me stumped, maybe I'm overlooking it, it also does the same thing with regular commands that do not have any arguments. This has lead to believe me this is in the index. I want it to simply return if other input is made (like ?qa alksjdkalsjd) that is not specified as an arg.
Discord.js = v12
What you want to do is restructure your if like this:
if(args.length === 0) { // this runs everytime there are no args provided
return message.channel.send(data, 'To see focus types, type `!qa [arg]`, example `!qa test`', { split: true });
}
if (args[0] === 'test') {
return message.channel.send(testing)
}
/* ........... */
return message.channel.send(error); // send a errror here if the args were not handled by the above cases
I am working on a Discord bot, and trying to improve my already functioning command handler.
I have a folder, and every file is an extra command. I want to expand the system, so I have alias name for the same command, e.g. I want my clearchat command to function with /clearchat or with /cc, but I dont want to create just another file and copy the code. This is what I have:
// I left out the other imports etc.
client.commands = new Discord.Collection();
// Reading commands-folder
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.on("message", msg => {
if (msg.content.startsWith(config.prefix) && !msg.author.bot && msg.guild) {
const args = msg.content.slice(config.prefix.length).split(" ");
const command = args.shift().toLowerCase();
if (client.commands.find(f => f.name === command)) {
client.commands.get(command).execute(client, msg, args);
}
}
});
and then a command file inside the commands-folder:
module.exports = {
name: "clearchat",
execute(client, msg, args) {
if (msg.member.hasPermission("ADMINISTRATOR")) {
msg.channel.messages.fetch({limit: 99}).then(messages => {
msg.channel.bulkDelete(messages);
});
}
}
}
(I know it only deletes 100 messages max, I am fine with that)
I image something in changing a few lines in my client.on("message) function, and just having to write in the clearchat.js file a line like name: ["clearchat", "cc", ...] where I can go writing as much aliases as I want.
Thanks in advance!
First, you'll have to create an array with the aliases in your command.
module.exports = {
name: "clearchat",
aliases: ["cc"],
execute(client, msg, args) {
}
}
Then, the same you did with commands, create a Collection for the aliases.
client.aliases = new Discord.Collection()
And finally, bind the alias to the command:
if (command.aliases) {
command.aliases.forEach(alias => {
client.aliases.set(alias, command)
})
}
Now, when you want to execute a command, you'll have to check if it has an alias.
const commandName = "testcommand" // This should be the user's input.
const command = client.commands.get(commandName) || client.aliases.get(commandName); // This will return the command and you can proceed by running the execute method.
fs.readdir(`./commands/`, (error, files) => {
if (error) {return console.log("Error while trying to get the commmands.");};
files.forEach(file => {
const command = require(`./commands/${file}`);
const commandName = file.split(".")[0];
client.commands.set(commandName, command);
if (command.aliases) {
command.aliases.forEach(alias => {
client.aliases.set(alias, command);
});
};
});
});
Here is what it currently looks like:
const Discord = require("discord.js")
const client = new Discord.Client()
const fs = require("fs")
const ytdl = require("ytdl-core")
const config = require("./config.json")
fs.readdir("./events/", (err, files) => {
if (err) return console.error(err)
files.forEach(file => {
let eventFunction = require(`./events/${file}`)
let eventName = file.split(".")[0]
client.on(eventName, (...args) => eventFunction.run(client, ...args))
})
})
client.on("message", message => {
if (message.author.bot) return
if(message.content.indexOf(config.prefix) !== 0) return
const args = message.content.slice(config.prefix.length).trim().split(/ +/g)
const command = args.shift().toLowerCase()
try {
let commandFile = require(`./commands/${command}.js`)
commandFile.run(client, message, args)
} catch (err) {
console.error(err)
}
if(command === "test"){
let url = args[0]
ytdl(url, {filter:'audioonly', format:'mp3'}).pipe(fs.createWriteStream("audio.mp3"))
message.channel.sendFile("./audio.mp3")
}
});
client.login(config.token)
commands are stored in seperate files, but I write in the
if(command === "test")
for testing commands
Any help is appreciated, thanks
You're using Stream and it's asynchronous. To make it work you need to check is the file's writing process completed or not!
ytdl(url, {filter: 'audioonly', format: 'mp3'})
.pipe(fs.createWriteStream('audio.mp3'))
// End of writing
.on('end', () => {
message.sendFile('./audio.mp3');
});