UnhandledPromiseRejectionWarning: ReferenceError: client is not defined - javascript

I'm encountering an error while making a command for my discord.js bot which says UnhandledPromiseRejectionWarning: ReferenceError: client is not defined even tho i defined client in the main bot file so i'm pretty confused the code for the command i'm making:
let ticketGen = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split("");
let ticketStr = "";
for(let i = 0; i < 3; i++) {
ticketStr += ticketGen[Math.floor(Math.random() * ticketGen.length)];
}
return ticketStr;
}
const fsn = require("fs-nextra");
const colors = require("colors");
module.exports = {
name: 'order',
description: 'Ordering something',
aliases: ['o'],
execute(message) {
let order = message.content.substring(8);
let customer = message.author.id
fsn.readJSON("./blacklist.json").then((blacklistDB) => {
let entry = blacklistDB[message.guild.id];
// Checks is server is blacklisted or not.
if(entry === undefined) {
// Gets ticket ID.
const ticketID = generateID();
// Sends ticket information to tickets channel.
client.guilds.cache.get("745409671430668389").channels.get("746423099871985755").send({embed: {
color: 0xFFFFFF,
title: message.author.username,
fields: [{
name: "New Order",
value: `${message.author.username} would like to order something.`,
}, {
name: "Order Description",
value: order,
}, {
name: "Order ID",
value: ticketID,
}, {
name: "Guild Infomation",
value: `This order came from ${message.guild} (${message.guild.id}) in ${message.channel} (${message.channel.id}).`,
}, {
name: "Order Status",
value: "Unclaimed",
}],
timestamp: new Date(),
footer: {
text: "Taco Bot"
}
}}).then((m) => {
m = m.id;
//rest of the code
forgive me if it was an stupid error i'm completely new to coding and was watching youtube videos to learn the code for the main bot file:
const fs = require("fs");
const { prefix, token, ownerID } = 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.on("ready", () => {
console.log(`ready!.`);
console.log(token);
// Activities
const activities_list = [
`Serving Tacos | .help`,
`Preparing Orders | .help`
];
setInterval(() => {
const index = Math.floor(Math.random() * (activities_list.length - 1) + 1);
client.user.setActivity(activities_list[index]);
}, 10000);
});
//Joined Guild
client.on("guildCreate", (guild) => {
console.log(colors.green(`Joined New Guild, ${guild.name}`));
});
//Left Guild
client.on("guildDelete", (guild) => {
console.log(colors.green(`Left Guild, ${guild.name}`));
});
client.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();
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 === 'dm') {
return message.reply('I can\'t execute that command inside DMs!');
}
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!');
}
});
process.on("error", () => {
console.log("Oops something happened!");
});
client.login(token);

There is no need to create a new client, and absolutely no need to pass it in as an additional argument in your execute method. As you have seen in the comments, the issue is that while client is defined in your main bot file, it is not defined in your command's file. Variables defined in one file aren't accessible in all other files, unless you specifically export that variable using module.exports.
But luckily, you don't need to export your client or pass it as a parameter; discord.js conveniently has a message.client property on the message object which allows you to access your client easily. All you need to do to fix your code is add a single line to the top of your execute() method in your command file:
module.exports = {
name: 'order',
description: 'Ordering something',
aliases: ['o'],
execute(message) {
const client = message.client; //<- Line added right here
let order = message.content.substring(8);
let customer = message.author.id
fsn.readJSON("./blacklist.json").then((blacklistDB) => {
let entry = blacklistDB[message.guild.id];
// Checks is server is blacklisted or not.
if(entry === undefined) {
// Gets ticket ID.
const ticketID = generateID();
// Sends ticket information to tickets channel.
client.guilds.cache.get("745409671430668389").channels.get("746423099871985755").send({embed: {
color: 0xFFFFFF,
title: message.author.username,
fields: [{
name: "New Order",
value: `${message.author.username} would like to order something.`,
}, {
name: "Order Description",
value: order,
}, {
name: "Order ID",
value: ticketID,
}, {
name: "Guild Infomation",
value: `This order came from ${message.guild} (${message.guild.id}) in ${message.channel} (${message.channel.id}).`,
}, {
name: "Order Status",
value: "Unclaimed",
}],
timestamp: new Date(),
footer: {
text: "Taco Bot"
}
}}).then((m) => {
m = m.id;
//rest of the code
And that's all! Problem solved. That message.client property is amazingly convenient.
Relevant Resources:
https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=client

I will suggest you to add the client in the command.execute() too, because it is easier to use. So you will have:
try {
command.execute(client, message, args);
} catch (error) {
console.error(error);
message.reply('there was an error trying to execute that command!');
}
And in every command file you just simply do this.
execute(client, message, args) {
//code
}

Related

Discord.JS bot not replying to commands nor returning a error in console regarding it

I've been struggling to get my new Discord bot's command handler to work, While it is seeing the command files (as indicated by its log entry on startup stating the amount of commands it has loaded) it either isn't sending the messages, or it isn't even executing them.
Here's my code:
const { Client, Intents, Collection } = require('discord.js');
const { token, ownerid, statuses, embedColors, prefix } = require('./cfg/config.json');
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
const fs = require('fs');
const { config } = require('process');
client.commands = new Collection();
const commands = [];
const cmdfiles = fs.readdirSync('./cmds').filter(file => file.endsWith('.js'));
client.once('ready', () => {
console.clear
console.log(`Ready to go, Found ${cmdfiles.length} commands and ${statuses.length} statuses!`)
setInterval(() => {
var status = Math.floor(Math.random() * (statuses.length -1) +1)
client.user.setActivity(statuses[status]);
}, 20000)
}),
client.on("error", (e) => console.log(error(e)));
client.on("warn", (e) => console.log(warn(e)));
// Command Handler
for (const file of cmdfiles) {
const command = require(`./cmds/${file}`);
commands.push(command.data);
}
client.on('messageCreate', 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 (!client.commands.has(command)) {
embeds: [{
title: ":x: Oopsie!",
color: config.embedColors.red,
description: `Command ${args.[0]} doesn't exist! Run ${config.prefix}help to see the avaliable commands!`,
footer: app.config.footer + " Something went wrong! :("
}];
} else {
try {
client.commands.get(command).execute(message, args);
} catch (error) {
console.error(error);
embeds: [{
title: ":x: Oopsie!",
description: "Command execution failed",
fields: [
{ name: "Error Message", value: `${e.message}` }
],
footer: app.config.footer + " Something went wrong :("
}];
}
message.channel.send
}});
client.login(token);
and the test command is
module.exports = {
name: "test",
description: "does as it implies, dingusA",
async execute(client, message, args) {
message.channel.send("This is a message!");
}
}
You need the GUILD_MESSAGES intent in order to receive messages in guilds.
Add the following intent in your code
const client = new Client({ intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES ]
})
This applies to other things as well eg. DIRECT_MESSAGES for DMs and etc.

Heroku: how to have it access multiple .js files

I'm getting this error message on heroku and I think I'm getting it cause of Procfile.
I'm using Worker at the moment, but I'm trying to figure out how to have heroku access both index.js and ping.js. Unless I'm reading the error message completely wrong and this could be a different issue. Any help is appreciated!
EDIT:
Here's my code for index.js
const Discord = require('discord.js');
const music = require('#koenie06/discord.js-music');
const fs = require('fs');
const { dir } = require('console');
const bot = new Discord.Client({
shards: "auto",
intents: [
Discord.Intents.FLAGS.GUILDS,
Discord.Intents.FLAGS.GUILD_MESSAGES,
Discord.Intents.FLAGS.GUILD_MESSAGE_REACTIONS,
Discord.Intents.FLAGS.DIRECT_MESSAGES,
Discord.Intents.FLAGS.GUILD_VOICE_STATES
]
});
bot.commands = new Discord.Collection();
bot.aliases = new Discord.Collection();
//Command handler and aliases
fs.readdirSync('./commands/').forEach(dir => {
//in the commands folder, we gonna check for the category
fs.readdir(`./commands/${dir}`, (err, files) => {
//console log error(catch error)
if(err)throw err;
//checking if the files ends with .js if its a javascript file
var jsFiles = files.filter(f => f.split('.').pop() === 'js');
//if there is no commands in the file it will return
if(jsFiles.length <= 0) {
console.log("Can't find any commands");
return;
}
jsFiles.forEach(file => {
//console the loaded commands
var fileGet = require(`./commands/${dir}/${file}`);
console.log(`[COMMAND HANDLER] - File ${file} was loaded`);
//gonna let the commands run
try {
bot.commands.set(fileGet.help.name, fileGet);
// it search in the commands folder if there is any aliases
fileGet.help.aliases.forEach(alias => {
bot.aliases.set(alias, fileGet.help.name);
})
} catch(err) {
//catch error in console
return console.log(err);
}
})
})
})
/**
* ECHO STUFF
*/
//slash command to echo
bot.on('ready', async () => {
bot.user.setPresence({ activities: [{ name: "Tedi", type: "WATCHING"}] });
console.log("bye");
const data = {
name: 'echo',
description: 'Echo your text',
options: [{
name: 'text',
type: 'STRING',
description: 'The user input',
required: true,
}],
};
const command = await bot.guilds.cache.get('872986148681703444')?.commands.create(data);
})
bot.on('messageCreate', async message => {
if(message.author.bot || message.channel.type == 'DM') return
let prefix = '~'
let messageArray = message.content.split(' ');
let cmd = messsageArray[0];
let args = messageArray.slice(1);
//it will make the cmd work with his original name and his aliases
let commands = bot.commands.get(cmd.slice(prefix.length)) || bot.commands.get(bot.aliases.get(cmd.slice(prefix.length)));
if(commands) {
if(!message.content.startsWith(prefix)) return
commands.run(bot, message, args, prefix);
}
})
//interactionCreate for echo slash command
bot.on('interactionCreate', async interaction => {
/**
* isButton() used to check if its a button
* isCommand() used to check if its a slash command
* isSelectMenu() used to check if its a dropdown menu
* isMessageComponent()
*/
if(interaction.isCommand()) {
if(interaction.commandName === 'echo') {
const text = interaction.options.getString('text');
await interaction.reply({ content: text, ephemeral: false}); //if ephemeral if true, it would make the slash command private
}
}
})
bot.login(process.env.token);
Here is my ping.js
const Discord = require("discord.js");
module.exports.run = async (Client, message, args, prefix) => {
message.channel.send("pong")
}
module.exports.help = {
name: "ping",
aliases: ["p"]
}
This error is not because of Heroku, it's basically because there is a file in your command handler that doesn't have a name while handling it, as example like this code over here:
const Discord = require("discord.js");
module.exports.run = async (Client, message, args, prefix) => {
message.channel.send("pong")
}
module.exports.help = {
// here the name isn't included
aliases: ["p"]
}
// so just check if you have a file without a name while handling it and put a name, and if you don't want aliases make it `aliases: []`
This command handler should be like thisCommands Folder commands > Subfolder e.g. Moderation > kick.jsThats how it works, also thank you for watching my videos, I'm UltraX :)

Call for a command, multiply every times the embeded fields

Hello.
I coded a simple MessageEmbed function (with Discord.JS) and every time that I call it, the new embed that is sent in the channel has his field who adds up with the precedent
(e.g.: if the embed should have 2 fields, the next time that the command will be called it will have 2*2 the required fields. If you call it again, 3*2, 4*2, etc.).
When I restart the bot it reset. I tried to reset the embed value but it didn't affect the problem.
Could you help me please ?
Here is my JS command :
module.exports = {
name: 'drive',
execute(client, message, args, embed) {
message.channel.send(embed
.setColor('#0099ff')
.setTitle('abcdedfg')
.setDescription('abcdedfg \n\u200B')
.setThumbnail('abcdedfg')
.addFields(
{ name: 'abcdedfg :', value: 'link' },
{ name: 'abcdedfg :', value: 'link \n\u200B' },
)
.setFooter('abcdedfg'))
.catch(console.error);
}
}
And here is my main if needed :
const fs = require('fs');
const { Client, Collection, MessageEmbed } = require('discord.js');
const { TOKEN, PREFIX } = require('./config/config');
const client = new Client();
client.commands = new Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
const embed = new MessageEmbed();
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).split(/ +/);
const command = args.shift().toLowerCase();
if (!client.commands.has(command)) return;
client.commands.get(command).execute(client, message, args, embed);
});
client.login(TOKEN);
I found the answer to block the fields from being added every times to the the fields array here on StackOverFlow.
So the code answer is addind a embed.fields = []; at the end :
module.exports = {
name: 'drive',
execute(client, message, args, embed) {
message.channel.send(embed
.setColor('#0099ff')
.setTitle('abcdedfg')
.setDescription('abcdedfg \n\u200B')
.setThumbnail('abcdedfg')
.addFields(
{ name: 'abcdedfg :', value: 'link' },
{ name: 'abcdedfg :', value: 'link \n\u200B' },
)
.setFooter('abcdedfg'))
.catch(console.error);
embed.fields = [];
}
}
Its quite simple. don't add fields. adding fields is what adds new fields so if you do not want them do not add them. else, clear the old ones before adding new ones.
My recommendation, use this;
module.exports = {
name: 'drive',
execute(client, message, args, embed) {
message.channel.send(embed
.setColor('#0099ff')
.setTitle('abcdedfg')
.setDescription('abcdedfg \n\u200B')
.setThumbnail('abcdedfg')
.setFooter('abcdedfg'))
.catch(console.error);
}
}
Try this and let's see.
As long as the first fields exist, you don't ever have to add.

module.export and getting user information

I'm trying to display client.user.avatarURL in a command file through module.export using:
...
icon_url: client.user.avatarURL;
...
but when I call the command through the bot I have this error in the console:
TypeError: Cannot read property 'avatarURL' undefined
I've tried getting the value of the client on a const and pass it true the command handler but didn't solve it as well. If you delete that line everything works fine, so I guess is just a wrong way to pass client informations.
main.js
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.once('ready', () => {
console.log('Online!');
});
client.on('message', message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const commandName = args.shift().toLowerCase();
if (!client.commands.has(commandName)) return;
const command = client.commands.get(commandName);
if (command.args && !args.length) {
let reply = `You didn't provide enough arguments, ${message.author}!`;
if (command.usage) {
reply += `\nThe proper usage would be: \n\`${prefix}${command.name} ${command.usage}\``;
}
return message.channel.send(reply);
}
try {
command.execute(message, args, client);
}
catch (error) {
console.error(error);
message.reply('there was an error trying to execute that command!');
}
});
client.login(token);
and the command file:
module.exports = {
name: 'help',
description: 'Help file',
execute(message, client) {
message.channel.send({ embed: {
color: 0xf7da66,
author: {
name: 'Bot',
icon_url: client.user.avatarURL,
},
title: 'commands guide',
description: 'This is an discord bot.',
fields: [{
name: 'Command',
value: 'Type: example.',
},
],
timestamp: new Date(),
footer: {
icon_url: client.user.avatarURL,
text: '© Bot',
} } });
},
};
You are doing: command.execute(message, args, client); but then execute(message, client) { wich means that in your command file client is now actually the array args.
You need to do: execute(message, args, client) {
You need to use module.exports = (client, message, args) => { instead.

discord.js list all my bot commands

i made a discord bot with discord.js and tried to do a help command to show the user all available commands.
example command: avatar.js
module.exports.run = async(bot, message, args) => {
let msg = await message.channel.send("doing some magic ...");
let target = message.mentions.users.first() || message.author;
await message.channel.send({files: [
{
attachment: target.displayAvatarURL,
name: "avatar.png"
}
]});
msg.delete();
}
module.exports.help = {
name: "avatar",
description: "show the avatar of a user",
usage: "[#user]"
}
Then i tried to send a message with the complete list of the commands like:
command 1
description
usage
command 2
description
usage
...
help.js
const fs = require("fs");
const Discord = require("discord.js");
module.exports.run = async(bot, message, args, con) => {
fs.readdir("./cmds/", (err, files) => {
if(err) console.error(err);
let jsfiles = files.filter(f => f.split(".").pop() === "js");
if(jsfiles.length <= 0) {
console.log("No commands to load!");
return;
}
var namelist = "";
var desclist = "";
var usage = "";
let result = jsfiles.forEach((f, i) => {
let props = require(`./${f}`);
namelist = props.help.name;
desclist = props.help.description;
usage = props.help.usage;
});
message.author.send(`**${namelist}** \n${desclist} \n${usage}`);
});
}
module.exports.help = {
name: "help",
description: "show all commands",
usage: ""
}
my code is kinda working but it only sends the first command.
Im pretty new to javascript and i can't find a solution to this.
I tried to google everything on foreach maps discord collections and stuff but i cant find a example where the results get combined together.
If anybody can help me or give me a hint where i can search for something like this. Would be awesome.
The reason your code is only sending the one command is because your code only calls message.author.send('...' once. You successfully set the variables namelist, desclist, and usage with data from every file, but your .forEach(... loop just overwrites all of the data when it moves to the next files.
Try to send data inside each iteration of the .forEach(... loop like this:
var namelist = "";
var desclist = "";
var usage = "";
let result = jsfiles.forEach((f, i) => {
let props = require(`./${f}`);
namelist = props.help.name;
desclist = props.help.description;
usage = props.help.usage;
// send help text
message.author.send(`**${namelist}** \n${desclist} \n${usage}`);
});
you should do this in an Array and it'll solve the problem, so it should look like this.
module.exports.run = async(bot, message, args, con) => {
fs.readdir("./cmds/", (err, files) => {
if(err) console.error(err);
let jsfiles = files.filter(f => f.split(".").pop() === "js");
if(jsfiles.length <= 0) {
console.log("No commands to load!");
return;
}
let result = jsfiles.forEach((f, i) => {
let props = require(`./${f}`);
let filesArray = [props.help.name, props.help.description, props.help.usage]
message.author.send(`**${filesArray[0]}** \n${filesArray[1]} \n${filesArray[2]}`);
});
});
}
sorry for the late response.
Here is my take on this.... it works for me.
const Discord = require('discord.js');
const fs = require("fs");
module.exports = {
name: 'help',
description: 'Lists available commands',
async run(client, message, args, con) {
fs.readdir("./commands/", (err, files) => {
if(err) console.error(err);
let jsfiles = files.filter(f => f.split(".").pop() === "js");
if(jsfiles.length <= 0) {
console.log("No commands to load!");
return;
}
var namelist = "";
var desclist = "";
let result = jsfiles.forEach((f, i) => {
let props = require(`./${f}`);
namelist = props.name;
desclist = props.description;
message.author.send(`**${namelist}** \n${desclist} \n`);
});
});
}
I'm using DiscordJS 12 so this may not work on 11.
const discord = require('discord.js')
module.exports = {
name: 'cmd-list',
async run(client, message, args) {
const commandFiles = readdirSync(join(__dirname, "<your commands folder name>")).filter(file => file.endsWith(".js")); // Get files
const cmdmap = commandFiles.map(files => `${files}`).join(' | Working\n')
const embed = new discord.MessageEmbed()
.setDescription(cmdmap)
message.channel.send(embed)
}
}
You can just use discord 's normal embed system like this:
const { Message, MessageEmbed } = require('discord.js');
Add this to the top of your code then type everything as the following to make a normal embed like this:
const embed = new MessageEmbed()
.setTitle(`Your title!`)
.setColor(5814783)
.setTimestamp()
.setThumbnail('')
.setDescription(`Your description`)
.addFields(
{ name: 'Field 1', value: `Filed 1 Value`},
{ name: 'Field 2', value: `Filed 2 Value` },
{ name: 'Field 3', value: `Filed 3 Value`, inline: true },
{ name: 'Field 4', value: `Filed 4 Value`, inline: true },
{ name: 'Field 5', value: `Field 5 Value`, inline: true },
)
message.channel.send(embed2)

Categories