I can't get one of my variables to pass to the command modules.
Its declared at const { token, ownerid, botid } = require('./config.json'); and passed through command.execute(message, args, prefix, ownerid); and read through execute(message, args, prefix, ownerid) { but when I try to log ownerid in the module, it turns up as undefined. Somewhere its getting erased I think. I tried logging it right before the command.execute and it reads it fine there, I think its getting lost on the way somehow.
Oh here is what ownerid should look like: [ 'xxxxxxxxxxxxxx' ] (but with numbers obviously)
Anyone have any idea where my variable has gone to?
My temporary solution is to use fs to just read the file in the module instead of importing the variable.
Code: in order of use:
const { token, ownerid, botid } = require('./config.json'); //declared
//command defined
client.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 commandfile = require(`./commands/${folder}/${file}`);
client.commands.set(commandfile.name, commandfile);
}
}
client.on('message', message => {
//filters and stuff
try {
command.execute(message, args, prefix, ownerid);
} catch (error) {
console.error(error);
message.reply('There was an error trying to execute that command!');
}
});
//in module
execute(message, args, prefix, ownerid) {
for (let i = 0; i < ownerid.length; i++) {
const dmme = message.client.users.cache.get(ownerid[i])
const bugreportembed = new Discord.MessageEmbed()
.setTitle('New bug report!')
.addField('Info', `From ${message.author.tag}`)
.setColor('RANDOM')
.addField('Description', message.content.replace(`${prefix}bugreport `, ""))
dmme.send(bugreportembed)
message.channel.send('Sent!')
}
}
Related
I try making a command that I can use to show me the servers the bot is in, but when I start making the command it doesn't work in every way I try it and always tells me that one of the things was not defined or cannot read property mostly it tells me that bot or guilds is not defined or cannot read properly.
I want to make a command that only I can use in discord to see all the servers that my bot is in.
I use command handler that means that every single command is in separate js file.
My discord client variable is set to "bot" (as shown in the code).
This is the command (servers.js):
module.exports = {
name: 'servers',
execute(bot, message, args) {
bot.guilds.cache.forEach(guild => {
message.channel.send(`Servers: ${guild.name}`);
})
}
}
This is the command handler/the main file (index.js):
const Discord = require('discord.js');
const bot = new Discord.Client();
const fs = require('fs');
const { prefix, token } = require('./config.json');
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);
}
const cooldowns = new Discord.Collection();
bot.once('ready', () => {
console.log('Online!');
});
bot.on('message', message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const commandName = args.shift().toLowerCase();
if (!bot.commands.has(commandName)) return;
const command = bot.commands.get(commandName);
if (command.args && !args.length) {
let reply = `You didn't provide any arguments, ${message.author}!`;
if (command.usage) {
reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``;
}
return message.channel.send(reply);
}
try {
command.execute(message, args);
}
catch (error) {
console.error(error);
message.reply('there was an error trying to execute that command!').then(msg => {
msg.delete({timeout:6000});
});
}
});
And there is the error:
TypeError: Cannot read property 'cache' of undefined
at Object.execute (D:\Users\USER\Desktop\Bot\commands\serversinfo.js:4:20)
at Client.<anonymous> (D:\Users\USER\Desktop\Bot\index.js:64:21)
at Client.emit (node:events:376:20)
at MessageCreateAction.handle (D:\Users\USER\Desktop\Bot\node_modules\discord.js\src\client\actions\MessageCreate.js:31:14)
at Object.module.exports [as MESSAGE_CREATE] (D:\Users\USER\Desktop\Bot\node_modules\discord.js\src\client\websocket\handlers\MESSAGE_CREATE.js:4:32)
Your execute function takes 3 arguments execute(bot, message, args), but you are only giving it 2 arguments when you use it in the main file: command.execute(message, args);
Adding that missing argument should fix that:
command.execute(bot, message, args)
The easiest way to list all the servers the bot is in is by mapping all the servers like this:
message.channel.send(client.guilds.cache.map(s => s.name))
Then you can put it in to your command however needed - Feel free to reply to this if you have any questions or it doesn't work.
module.exports = {
name: 'servers',
execute(bot, message, args) {
message.channel.send(client.guilds.cache.map(s => s.name))
}
Please feel free to reply to me if this doesn't work or you have any other questions!
I am attempting to make a command like dank memer has, when someone says F or f, the bot replies with F. My problem is that it will not work without the prefix, but I would like to be able to do it without the prefix.
Here is my code. I use a command handler.
//THIS IS THE INDEX.JS FILE
const Discord = require('discord.js');
const { default_prefix, token_bot } = require('./config.json');
const client = new Discord.Client();
const fs = require('fs');
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('Ready Player One!');
});
client.on('message', message => {
if (!message.content.startsWith(default_prefix) || message.author.bot) return;
const args = message.content.slice(default_prefix.length).trim().split(/ +/);
const command = args.shift().toLowerCase();
if (command === 'f'){
client.commands.get('f').execute(message, args);
}
And this one is the f.js command that it calls on.
module.exports = {
name: 'f',
description: "This is an f command",
execute(message, args){
message.channel.send('F');
},
};
This is not all of my index.js file, it is too long.
The solution to this is very simple. All commands have prefixes, so I would not consider what you are trying to create as a command, I would say it is technically more of an auto-response. Therefore, you should not be using the code of your args or command variables to check if "F" has been sent, you should instead directly check the message's content.
client.on('message', message => {
if (!message.content.startsWith(default_prefix) || message.author.bot) return;
const args = message.content.slice(default_prefix.length).trim().split(/ +/);
const command = args.shift().toLowerCase();
if (message.content.toLowerCase() == 'f'){
client.commands.get('f').execute(message, args);
}
});
I would advise looking into the args and command variables and learning how their values are being retrieved. Your code, as it is, seems to heavily rely on a simple template, but you cannot entirely depend on this template if you want to fully customize how your bot/commands will look and function.
I was trying to make a lockdown command, at my point of knowlead, its fine, but something is going wrong.
const Discord = require('discord.js');
const client = new Discord.Client();
module.exports = async (msg,client,args) => {
const channel = msg.channel;
const roles = msg.guild.roles;
if(!msg.guild) return;
if(!msg.member.hasPermission("MANAGE_CHANNELS"))
msg.channel.send("Você não tem permissão para executar esse comando.")
else{
roles.forEach((roles) => {
channel.overwritePermissions (roles ,{
SEND_MESSSAGES: false,
ADD_REACTIONS: false
})
})
msg.channel.send("Canal bloqueado com sucesso.")
}
}```
**error recived: TypeError: Cannot read property 'roles' of undefined**
In your main file you are passing in the arguments as: (client, msg), so in the command file you will need to get the arguments in the right order,
so from:
module.exports = async (msg, client, args) => {
}
to this:
module.exports = async (client, msg, args) => {
}
also you aren't passing in args in your main file so change from:
if (commands[args[0]]) commands[args[0]](client,msg);
else if(args[0].split("")[0] == config.prefix) unknownCommand(client,msg);
To:
const first = args[0];
if(commands[first]) {
commands[first](client, msg, args);
} else if(first[0] === config.prefix) {
unknownCommand(client, msg, args);
}
The next improvement is in your foreach statement:
roles.forEach((roles) => {
//code
});
Here you have an array of roles and then the variable you are passing is also called roles, you should instead call it role or something else,
Also in v12 <Message>.guild.roles is a Manager not a collection, so you need to add `.cache
You will also either need to change the parameters in channel.overwritePermission or switch to channel.updateOverwrite:
roles.cache.forEach(role => {
channel.updateOverwrite(role, {
SEND_MESSSAGES: false,
ADD_REACTIONS: false
})
})
or
roles.cache.forEach(role => {
channel.overwritePermissions([
{
id: role.id,
deny: ["SEND_MESSAGE", "ADD_REACTIONS"]
}
]);
})
You might also want to look into some better command handlers, currently yours doesn't have any config option for commands from what I can tell
My problem is the following: when compiling, I get the error that the property 'execute' is not defined. What I'm trying to do is open a file that is in another folder and dock it in the if, I was guided by the command handling documentation, I don't know if the error is in the other file which is called 'ping.js'. I recently started, so I don't fully understand it.
The main code is as follows:
const Discord = require('discord.js');
const { token, default_prefix } = require('./conf.json');
const client = new Discord.Client();
const fs = require('fs');
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('Ready!');
});
client.on('message', async message => {
if (!message.content.startsWith(default_prefix) || message.author.bot) return;
const args = message.content.slice(default_prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
if (command === 'ping') {
client.commands.get('ping').execute(message, args);
}
});
client.login(token);
While the 'ping.js' code is:
const Discord = require('discord.js');
module.exports = {
description: "Get the latency of the bot.",
usage: {},
examples: {},
aliases: [ "pong", "latency", "uptime" ],
permissionRequired: 0,
checkArgs: (args) => !args.length
}
module.exports.run = async function (client, message, args, config, gdb, prefix, permissionLevel, db) {
let botMsg = await message.channel.send("Pinging")
botMsg.edit({
embed: {
name: "ping",
title: "📶 Ping",
color: 0x2ed32e,
description: [
"**Server**: `" + (message.createdAt - message.createdAt) + "ms`",
"**API**: `" + Math.round(client.ws.ping) + "ms`",
"**Uptime**: `" + msToTime(client.uptime) + "`"
].join("\n"),
footer: { text: "Requested by " + message.author.tag, icon_url: message.author.displayAvatarURL }
}
})
}
function msToTime(ms) {...
}
It works, but if I add it directly to the main code, but I don't want that. If you have any ideas or know the solution, I would appreciate it.
It's saying execute is undefined because you didn't define execute it in ping.js.
You can do either:
In ping.js change module.exports.run to module.exports.execute
OR in your main file, change client.commands.get('ping').execute to client.commands.get('ping').run
The reasoning for the is when calling command.execute() you are attempting to call a function named 'execute' in the command's module. Since you named it run instead of execute, it looks for the wrong function and doesn't find it.
That's because you named it run and not execute on this line:
module.exports.run = async function ()
change it to execute and it should work fine, if you wanna keep the keyword run, instead of client.commands.get('ping').execute(message, args), use client.commands.get('ping').run(message, args)
Also I should mention you have a lot of parameters:
execute function (client, message, args, config, gdb, prefix, permissionLevel, db) {
//...
}
Any after args will be undefined as you only pass in messsage and args, here:
client.commands.get('ping').execute(message, args)
Please help me understand how can i call that ping.js from user input, like if a user type ping it will Trigger cuz of the aliases but if a user types a full phrase it won't trigger.
Or in a non headic question how can i implent this to work -> if (message.content.includes('ping'))
Sorry in advance and thanks a lot
ping.js
const Discord = require('discord.js')
const colors = require('../lib/colors.json')
exports.run = async (client, message, args, level) => {
try {
const pingEmbed = new Discord.RichEmbed()
.setColor(colors.default)
.setFooter('ping)
.addField(`${message.author.id}`, 'hey')
const msg = await message.channel.send(pingEmbed)
const embed = new Discord.RichEmbed()
.setColor(colors.default)
.addField('...',
`${msg.createdTimestamp - message.createdTimestamp}ms`)
msg.edit(embed)
} catch (err) {
message.channel.send('There was an error!\n' + err).catch()
}
}
exports.conf = {
enabled: true,
aliases: ['ping'],
guildOnly: false,
permLevel: 'User'
}
exports.help = {
name: 'ping,
category: 'tools,
description: 'ping pong',
usage: 'ping'
}
If you want to check whether a message contains any of the aliases you can just use Array.some() like this:
let aliases = ['your', 'command', 'aliases']
client.on('message', message => {
if (aliases.some(trigger => message.content.includes(trigger))) {
// The message includes at least one of your keywords
}
})
In this example is just declared aliases, but you can use the array from your command and integrate this method in your normal command handler.