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 :)
Related
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.
In this line of code I am trying to send private message, to initial message author. For some unknown reason there is an error:
(node:17560) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'send' of undefined
Here is this line of code:
const appStart = await message.author.send(questions[collectCounter++]);
Here is whole file:
const Discord = require("discord.js");
const {Client, Message, MessageEmbed} = require("discord.js");
module.exports = {
name: 'apply',
/**
*
* #param {Client} client
* #param {Messafe} message
* #param {String[]} args
*/
run : async(client, message, args) => {
const questions = [
"What is your in-game name?",
"Do you accept the rules?",
"How old are you?",
"Where are you from?",
"How long have you been playing Minecraft?",
"Where did you find the server?",
"Have you ever been banned from another server on Minecraft? If yes, what was the reason?",
"Why should we accept you?",
]
let collectCounter = 0;
let endCounter = 0;
const filter = (m) => m.author.id === message.author.id;
const appStart = await message.author.send(questions[collectCounter++]);
const channel = appStart.channel;
const collector = channel.createMessageCollector(filter);
collector.on("collect", () => {
if(collectCounter < questions.length) {
channel.send(questions[collectedCounter++]);
} else {
channel.send("Your application has been sent!");
collector.stop("fulfilled");
}
});
const appsChannel = client.channel.cache.get('863534867668009004');
collector.on('end', (collected, reason) => {
if(reason === 'fulfilled') {
let index = 1;
const mappedResponses = collected.map((msg) => {
return `&{index++}) &{questions[endCounter++]}\n-> ${msg.content}`
})
.join('\n\n');
}
appsChannel.send(message.channel.send('New Application!', mappedResponses));
});
},
};
This is my index.js:
const fs = require("fs");
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'));
const BOT_ID = "863550035923697674";
const prefix = "!";
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
client.user.setActivity("ur cheat files...", {
type: "WATCHING",
url: "https://discord.gg/bzYXx8t3fE"
});
});
for(const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
client.on("message", message => {
let userID = message.author.id;
if (userID == BOT_ID) {
return;
}
const version = "Wersja bota 0.2";
///const args = message.content;
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if(!client.commands.has(command)) return;
try{
client.commands.get(command).run(message, args);
}catch(error){
console.error(error);
message.reply('**There was an issue executing that command!**');
}
});
client.login("tokenishere");
Thanks for help!
This just means that message is not what you think it is. In your command handler, you executed the command with the arguments message and args (order matters). However, in the command file, you expected the parameters to be client, message, and then args.
This means, that in your command file, client actually refers to the message, message actually refers to the args, and the third parameter doesn't exist.
To fix this problem, you can modify the names and order of the parameters in either file.
This is an easy fix... as #Lioness100 mentioned your parameters are wrong and im here to show a code example
locate this line of code in index.js :
client.commands.get(command).run(message, args);
// and change it to
client.commands.get(command).run(message, args, client);
after wards go to your "File" and fine this line of code :
run : async(client, message, args) => {
// And change it to
run : async(message, args) => {
Your problem was that you were executing wrong parameters in Your "File" so you just needed to change your parameters from client, message, args to message, args, client
This is a common mistake
So I have help.js file where I require all other commands so that I can have access to their usage,
This is my help.js codes:
//Here is how I require all other commands...
const Discord = require('discord.js');
const client = new Discord.Client();
const fs = require('fs');
//If i removed this from here...
const commandFolders = fs.readdirSync('./commands/');
client.commands = new Discord.Collection();
for (const folder of commandFolders) {
const commandFiles = fs.readdirSync(`./commands/${folder}/`).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`../${folder}/${file}`);
client.commands.set(command.name, command);
}
}
//To here... the syntax is now defined on ban.js...
module.exports = {
name: 'help',
syntax: {
syntax: { //I will use this if for example a command has invalid syntax
color: 0xeb4034,
title: 'Oops!',
description: 'Looks like your syntax is invalid, see\n`?help {command}` for more description.'
},
}
execute: async function(message, args) {
//Here I call the ban usage
switch (args[0]) {
case 'ban':
let { usage } = client.commands.get('ban');
return message.channel.send({ embed: usage }); //This worked
}
More codes...
}
But suddenly if I call the syntax in help.js from other file... it is undefined, but if I hover it, it's showing the value of the syntax,
Heres my ban.js codes:
const Discord = require('discord.js');
const { syntax } = require('../Global/help');
module.exports = {
name: 'ban',
usage: {
color: 0x1e90ff,
title: 'Ban',
description: '`Usage:` {prefix}ban user time {optional reason}\n`Example:` ?ban <#message.author.tag> 1h/1m/1s Bad dude'
},
execute: async function(message, args) {
//If I hover on the syntax, it is showing the value, but the result is undefined...
console.log(syntax); //Shows undefined
if (args.length < 1) return message.channel.send({ embed: syntax }); //Made an error
}
}
This is how my files and folders are setup
How do I fix this?
Edit: I found the solution, its not running the code above the module.exports of ban.js so I made a function that returns the syntax
You didn't constructed your client properly
const client = new Discord.Client({
intents: ["GUILDS","GUILD_MEMBERS","GUILD_MESSAGES"]
});
I was trying to setup the bot's .setActivity(), but it doesn't seem to work, though, if I do it using the eval command, it actually sets it and works. Is this because I tried calling an external functions module?
Files
Essentials: ./resources/utils/essentials.js
placeHolder(client, string) {
const owner = client.users.cache.get(client.config.admin.owner.id);
if (typeof string === "string") {
return string
.replace(/%totalCommands%/g, client.commands.array().length)
.replace(/%clientName%/g, client.name)
.replace(/%clientId%/g, client.user.id)
.replace(/%clientDescription/g, client.package.description)
.replace(/%clientUsername%/g, client.user.username)
.replace(/%clientTag%/g, client.user.tag)
.replace(/%clientDevName%/g, client.dev.name)
.replace(/%clientDevHelpers%/g, client.dev.helpers.join(", "))
.replace(/%clientDefaultPrefix%/g, client.def.prefix)
.replace(/%clientGuildCount%/g, client.guilds.cache.size)
.replace(/%clientChannelCount%/g, client.channels.cache.size)
.replace(/%clientPackageName%/g, client.package.name)
.replace(/%clientVersion%/g, client.package.version)
.replace(/%clientLicense%/g, client.package.license)
.replace(/%clientAvatarURL%/g, client.avatar)
.replace(/%clientRepository%/g, client.package.repository)
.replace(/%clientAuthor%/g, client.package.author)
.replace(/%clientOwnerUsername%/g, owner.username)
.replace(/%clientOwnerTag%/g, owner.tag)
.replace(/%clientOwnerID%/g, owner.id)
.replace(/%clientMainFile%/g, client.package.main)
.replace(/%clientOwnerAvatarURL%/g, owner.avatarURL() || owner.defaultAvatarURL)
.replace(/%clientOriginalAuthor%/g, client.package.original_author);
} else {
return string;
}
}
Event Handler for ready: ./resources/events/ready.js
const Discord = require('discord.js');
const Essentials = require("../utils/essentials.js");
module.exports = {
name: "ready", // Event Name
async execute(
client, event
) {
let activity = {};
async function setActv() {
activity.type = client.config.client.presence.activity.default.name;
activity.status = client.config.client.presence.activity.status;
activity.name = await Essentials.placeHolder(client, client.config.client.presence.activity.default.name);
client.user.setActivity(activity.name, {
type: activity.type
});
client.user.setStatus(activity.status);
}
client.footer = Essentials.placeHolder(client, client.config.client.settings.footer);
try {
// Set Activity every 30 seconds
setInterval(async () => {
await setActv().catch(err => Essentials.log(client, error))
}, 5000);
} catch (error) {
Essentials.log(client, error);
}
// Bot Ready Log //
console.log(
`Logged in as ${client.user.tag}.\n`
+ `There are ${client.users.cache.size} users and/or bots online.\n`
+ `${client.user.tag} connected to:\n${client.guilds.cache
.map(g => g.name)
.join(", ")}`
);
}
};
Main bot file: ./bot.js
client.events = new Discord.Collection();
var eventFiles = fs
.readdirSync(`./resources/events`)
.filter(file => file.endsWith(".js"));
for (var file of eventFiles) {
var event = require(`./resources/events/${file}`);
client.events.set(event.name, event);
console.log(`Loading event handler for event "${event.name}".`);
}
client.on("ready", async () => {
const event = client.events.get("ready");
if (event) {
try {
await event.execute(
client, event
)
} catch (err) {
Essentials.log(client, err)
}
}
});
Eval command: ./resources/commands/eval.js
const Discord = require('discord.js');
const Essentials = require('../utils/essentials.js')
module.exports = {
id: "eval",
name: "Eval", // Command name
description: "A simple eval tool to use on Discord.", // Command Description
aliases: ["evl", "ev"], // Command Aliases
category: "Utilities",
cooldown: 5000, // Command cooldown
examples: ["eval message.author.id", "eval process.cwd()"], // Command Examples
usage: ["<args>"], // Command Usage
permissions: ["SEND_MESSAGES", "READ_MESSAGE_HISTORY"], // Command Permissions
memberPermissions: ["SEND_MESSAGES", "READ_MESSAGE_HISTORY", "MANAGE_SERVER"], // User is required to have these permissions
admin: true, // Command is admin only
async execute(client, command, message, args, auth, channel, guild) { // Function async execute()
// Command Starts Here
try {
let evaled = eval(args.join(" "));
if (typeof evaled !== "string") evaled = require("util").inspect(evaled);
const avtr = message.author.avatarURL() || message.author.defaultAvatarURL;
const embed = new Discord.MessageEmbed()
.setAuthor(client.name, client.avatar)
.setTitle(command.name)
.setTimestamp()
.setColor(client.color.default)
.addField("**Input**", '```' + args.join(" ") + '```')
.addField("**Result**", '```' + Essentials.clean(evaled) + '```')
.setFooter(`${message.author.username} evaled`, avtr);
message.channel.send(embed);
} catch (err) {
const embed = Essentials.errorEmbed(err);
message.channel.send((embed), { split: true });
}
}
};
I've tried a lot of combinations, ranging from actually putting it outside of the Event Handler and straight to the bot.js until actually using eval(), shown above is my current code. NO error codes were thrown, and all of the other components in ready.js works, including client.footer = ..., except for setting the activity, did I miss something?
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);
});
};
});
});