Is it possible to detect errors before the code starts to run?
I have a Discord bot, and I would like the command handler that prints all loaded commands to the console to show the status for errors in advance.
Command handler at the moment:
const { readdirSync } = require("fs");
const ascii = require("ascii-table");
const list = new ascii('Commands');
list.setHeading('Command', 'Loaded');
module.exports = (bot) => {
let commands = readdirSync(`./commands/`).filter(file => file.endsWith(".js"));
for (let file of commands) {
let command = require(`../commands/${file}`);
if (command.name) {
bot.commands.set(command.name, command);
list.addRow(file, '✅');
} else {
list.addRow(file, '❌');
continue;
}
}
console.log(list.toString());
}
You can simply use the try and catch statements of Javascript. In this way, if an error occurs still it will not break your code or bot. It will continue running without any problem.
If you don't want to show anything and want to continue running the bot:
try {
const { readdirSync } = require("fs");
const ascii = require("ascii-table");
const list = new ascii("Commands");
list.setHeading("Command", "Loaded");
module.exports = (bot) => {
let commands = readdirSync(`./commands/`).filter((file) =>
file.endsWith(".js")
);
for (let file of commands) {
let command = require(`../commands/${file}`);
if (command.name) {
bot.commands.set(command.name, command);
list.addRow(file, "✅");
} else {
list.addRow(file, "❌");
continue;
}
}
console.log(list.toString());
};
} catch (e) {
// Don't do anything
}
Incase you want to print out the error to the console and continue running the bot. Then you can add a console.log() under the catch statement:
try {
const { readdirSync } = require("fs");
const ascii = require("ascii-table");
const list = new ascii("Commands");
list.setHeading("Command", "Loaded");
module.exports = (bot) => {
let commands = readdirSync(`./commands/`).filter((file) =>
file.endsWith(".js")
);
for (let file of commands) {
let command = require(`../commands/${file}`);
if (command.name) {
bot.commands.set(command.name, command);
list.addRow(file, "✅");
} else {
list.addRow(file, "❌");
continue;
}
}
console.log(list.toString());
};
} catch (e) {
console.log(e)
}
Related
I'm Creating a discord bot for a pc game that will run /setup command that will automate some other commands using setInterval(). I'm using a class to group the commands into their own subclass. I wanted to make a command that will run a few certain commands every few secs or hours. I've tried everything I can think, tried to google it but nothin came up.
Here is the Index.js file (main file)
require ('dotenv').config();
const { Client, GatewayIntentBits, Partials, Routes, Collection } = require('discord.js')
const Discord = require('discord.js')
const client = new Client({
intents:[
GatewayIntentBits.GuildMessages,
GatewayIntentBits.Guilds,
GatewayIntentBits.MessageContent
],
rest: {version: '10'},
partials: [Partials.Channel]
});
const {TOKEN, APP, GUILD} = process.env;
const {registerCommands} = require('./handler/registercommand');
client.rest.setToken(TOKEN);
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand()) {
const {commandName} = interaction;
console.log(commandName)
const cmd = client.slashCommands.get(commandName);
if (cmd) {
cmd.execute(client, interaction);
}
else {
interaction.reply({content: 'Error running this slash command'});
}
}
});
async function main() {
try {
client.slashCommands = new Collection;
await registerCommands(client, '../commands');
//console.log(client.slashCommands);
const slashCommandsJson = client.slashCommands.map((cmd) => cmd.getSlashCommandJSON());
console.log(slashCommandsJson);
await client.rest.put(Routes.applicationCommands(APP), {
body: slashCommandsJson,
});
const registeredSlashCommands = await client.rest.get(
Routes.applicationCommands(APP)
);
console.log(registeredSlashCommands);
await client.login(TOKEN);
}
catch(err) {
console.log(err)
}
}
main()
One of the commands I want to automate which in this case is /arbitrations
const unirest = require("unirest");
const { EmbedBuilder, AttachmentBuilder, SlashCommandBuilder } = require("discord.js");
const SlashCommands = require('../handler/slashcommands');
file = new AttachmentBuilder();
module.exports = class arbitration extends SlashCommands {
constructor() {
super('arbitration');
}
async execute(client, interaction) {
const api = unirest("GET", "https://api.warframestat.us/pc/arbitration");
const moment = require("moment");
api.end(function (response) {
//gathers the data from the get request
if (response.error) throw new Error(response.error); // throws(logs) the error
const jsonResponse = response.body; // grabs the body from the response
const jsonEmbed = new EmbedBuilder()
.setTitle("Current Arbitration:")
.setColor("#BF40BF") // sets the color of the embed
.setFooter({ text: "Arbitration" }) // sets the footer text of the embed
if (jsonResponse['enemy'] === 'Grineer'){
file = new AttachmentBuilder('./assets/grineer.jpg')
jsonEmbed.setThumbnail('attachment://grineer.jpg')
}
else if (jsonResponse['enemy'] === 'Corpus'){
file = new AttachmentBuilder('./assets/corpus.jpg')
jsonEmbed.setThumbnail('attachment://corpus.jpg')
}
else if (jsonResponse['enemy'] === 'Corrupted'){
file = new AttachmentBuilder('./assets/corrupted.jpg')
jsonEmbed.setThumbnail('attachment://corrupted.jpg')
}
else {
file = new AttachmentBuilder('./assets/infested.jpg')
jsonEmbed.setThumbnail('attachment://infested.jpg')
}
var d = new Date(jsonResponse["expiry"]);
let date = moment(d, "MMM-DD").format("MMM:DD"); // returns the month and day
date = date.replace(":", " "); // replaces the : with a space
let final = moment(d, "HH:mm:ss").format("h:mm:ss A");
jsonEmbed.addFields({
name: `${jsonResponse["type"]}, \`${jsonResponse["node"]}\``,
value: `\n**Expires on:** \n${date} at ${final}`,`
});
interaction.reply({ embeds: [jsonEmbed], files: [file] });
});
}
getSlashCommandJSON(){
return new SlashCommandBuilder()
.setName(this.name)
.setDescription('Shows current Arbitration')
.toJSON();
}
};
Then the /setup command that will automate certain commands depending on the user's answer, I'm trying to execute /arbitrations command inside the SetInterval() on line 22:
const SlashCommands = require('../handler/slashcommands');
const { EmbedBuilder, Discord, SlashCommandBuilder } = require("discord.js");
module.exports = class setup extends SlashCommands {
constructor() {
super('setup');
}
async execute(client, interaction){
console.log("in the command")
const filter = (m) => m.author.id === interaction.user.id
interaction.channel.send("Would you like to automate the Arbitration command?")
console.log("sent Question")
interaction.channel
.awaitMessages({filter ,max: 1, time: 1000 * 20})
.then((collected) => {
const msg = collected.first()
if (msg.content.toLowerCase() === "yes" || msg.content.toLowerCase() === "y") {
console.log("setting setInterval()")
setInterval(() => {
var minutes = new Date().getMinutes()
if (minutes === 51) {
SlashCommands.get(`arbitrations`).execute(client, interaction)
}
}, 1000 * 5)
interaction.channel.send("Arbitration is Automated")
}
else if (msg.content.toLowerCase() === "no" || msg.content.toLowerCase() === "n") {
interaction.channel.send("Automation for Arbitration is canceled")
}
else {
interaction.channel.send("An error has occured please run again")
}
})
.catch((err) => console.log(err))
}
getSlashCommandJSON(){
return new SlashCommandBuilder()
.setName(this.name)
.setDescription('Automates commands')
.toJSON();
}
}
FYI: first time using this site so sorry if this doesn't look right
I already tried the code that's currently on line 25 and I get error "SlashCommands.get is not a function"
I have a handler which log commands list in console using ascii-table, but list of my commands gets duplicated, for example if I have 10 commands - list gets duplicated 10 times (image). I use discord.js v12.5.3 and here is my code:
index
["command"].forEach(handler => {
require(`./handler/${handler}`)(client);
})
command.js (handler file)
const { readdirSync } = require("fs");
const ascii = require("ascii-table");
let table = new ascii("Commands");
table.setHeading("Command", "Load status");
module.exports = (client) => {
readdirSync("./commands/").forEach(dir => {
const commands = readdirSync(`./commands/`).filter(file => file.endsWith(".js"));
for (let file of commands) {
let pull = require(`../commands/${file}`);
if (pull.name) {
client.commands.set(pull.name, pull);
table.addRow(file, '✅');
} else {
table.addRow(file, `❌ -> missing a help.name, or help.name is not a string.`);
continue;
}
if (pull.aliases && Array.isArray(pull.aliases)) pull.aliases.forEach(alias => client.aliases.set(alias, pull.name));
}
});
// Log the table
console.log(table.toString());
}
Thanks to #CherryDT I realized I just had to remove readdirSync("./commands/").forEach(dir => {}); to fix my handler.
Discord added these slash commands in v13, I have followed the discordjs.guide website on how to do it.
My code is:
//packages
const { Client, Collection, Intents } = require("discord.js");
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
const disbut = require("discord-buttons");
client.commands = new Collection();
const moment = require("moment");
const { MessageEmbed } = require("discord.js");
const AntiSpam = require("discord-anti-spam");
const ms = require("ms");
const { Slash } = require("discord-slash-commands");
const slash = new Slash(client);
const rtkn = ">r";
const { REST } = require("#discordjs/rest");
const { Routes } = require("discord-api-types/v9");
const { token, owner, bowner, clientid, guildid, prefix } = require("./config.json");
const fs = require("fs");
const commandFiles = fs.readdirSync("./commands").filter((file) => file.endsWith(".js"));
const commands = [];
const cmds = [];
disbut(client);
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
commands.push(command.data.toJSON());
}
const commands = [];
client.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: "There was an error while executing this command!", ephemeral: true });
}
});
const rest = new REST({ version: "9" }).setToken(token);
(async () => {
try {
console.log("Started refreshing application (/) commands.");
await rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: commands });
console.log("Successfully reloaded application (/) commands.");
} catch (error) {
console.error(error);
}
})();
const clean = (text) => {
if (typeof text === "string") return text.replace(/`/g, "`" + String.fromCharCode(8203)).replace(/#/g, "#" + String.fromCharCode(8203));
else return text;
};
client.on("message", (message) => {
const args = message.content.split(" ").slice(1);
if (message.content.startsWith(prefix + "eval")) {
if (message.author.id !== owner) return;
try {
const code = args.join(" ");
let evaled = eval(code);
if (typeof evaled !== "string") evaled = require("util").inspect(evaled);
message.channel.send(clean(evaled), { code: "xl" });
} catch (err) {
message.channel.send(`\`ERROR\` \`\`\`xl\n${clean(err)}\n\`\`\``);
}
}
});
client.on("message", (message) => {
const args = message.content.split(" ").slice(1);
if (message.content.startsWith(prefix + "eval")) {
if (message.author.id !== bowner) return;
try {
const code = args.join(" ");
let evaled = eval(code);
if (typeof evaled !== "string") evaled = require("util").inspect(evaled);
message.channel.send(clean(evaled), { code: "xl" });
} catch (err) {
message.channel.send(`\`ERROR\` \`\`\`xl\n${clean(err)}\n\`\`\``);
}
}
});
client.on("warn", (err) => console.warn("[WARNING]", err));
client.on("error", (err) => console.error("[ERROR]", err));
client.on("disconnect", () => {
console.warn("Disconnected!");
process.exit(0);
});
process.on("unhandledRejection", (reason, promise) => {
console.log("[FATAL] Possibly Unhandled Rejection at: Promise ", promise, " reason: ", reason.message);
});
client.login(token);
//ping.js contents below.
const { SlashCommandBuilder } = require("#discordjs/builders");
module.exports = {
data: new SlashCommandBuilder().setName("ping").setDescription("Replies with Pong!"),
async execute(interaction) {
await interaction.reply("Pong!");
},
};
My ping.js file is:
const { SlashCommandBuilder } = require("#discordjs/builders");
module.exports = {
data: new SlashCommandBuilder().setName("ping").setDescription("Replies with Pong!"),
async execute(interaction) {
return interaction.reply("Pong!");
},
};
When I run the code, it registers the slash commands fine, but when I run it, it says "interaction failed." Please help.
Your code is not well structured. You have a lot of deprecated modules and you declared commands twice. The problem however, is that you never call client.commands.set. In your for...of loop, you called commands.push instead of client.commands.set.
I don’t know how the SlashCommandBuilder function works, but I suspect the toJSON method would return something that looks like this:
{
name: 'commandName',
description: 'description',
options: []
}
You have to change your loop to look like this:
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
const data = command.data.toJSON()
client.commands.set(data.name, data);
}
I have a selfbot project for Discord (I know it's against the ToS, but this is just an experiment I'm not going to use it)
I want the selfbot to send a message like "this is an example message" every hour in a specific channel with the ID (783651779207626752)
What and where should I add something in the code?
const Discord = require("discord.js")
const client = new Discord.Client()
const { prefix, token } = require("./config.json")
const fs = require("fs")
const { table, getBorderCharacters } = require("table")
const commands = new Discord.Collection();
let commandFiles
function loadCommands() {
console.log("loading commands..")
const startTime = new Date().getTime()
commandFiles = fs.readdirSync("./commands/").filter(file => file.endsWith(".js"));
const failedTable = []
if (commands.size > 0) {
for (command of commands.keyArray()) {
delete require.cache[require.resolve(`./commands/${command}.js`)]
}
commands.clear()
}
for (file of commandFiles) {
let command
try {
command = require(`./commands/${file}`);
let enabled = true;
if (!command.name || !command.description || !command.run) {
enabled = false;
}
if (enabled) {
commands.set(command.name, command);
} else {
failedTable.push([file, "❌"])
}
} catch (e) {
failedTable.push([file, "❌"])
}
}
}
loadCommands()
exports.reloadCommands = loadCommands
client.once("ready", () => {
console.log("logged in as " + client.user.username + "#" + client.user.discriminator)
})
function runCommand(cmd, message, args) {
args.shift()
try {
commands.get(cmd).run(message, args)
} catch(e) {
console.log(e)
}
}
setTimeout(() => {
client.login(token)
}, 1500)
You can make another file called globalFunctions.js
Add anything that you want to be running globally as an IFFE
This will insure that every IFFE has its own block of code
globalFunctions.js
export default globalFunctions(client, channel){
/*
IFFE
*/
(function(){
setInterval(()=>{
channel.send('some message')
}, /*Time you want*/)
})()
// and so on
}
OR "I recommend this if you want to scale"
you can add other files for each global function and add then to global function file
/*Import other functions*/
import periodicMessage from 'PATH'
export default globalFunctions(client, channel){
periodicMessage(client, channel);
}
and just import this function to the main file and run it after the server runs
main.js
import globalFunctions from 'PATH'
client.once('ready', () => {
// Your code
globalFunctions(client, channel)
})
I have a problem, my code is showing
TypeError: Cannot read property 'execute' of undefined for pause command. All the other commands are working fine.
Reading Files.
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', msg => {
if (!msg.content.startsWith(prefix) || msg.author.bot) {
return;
}
const args = msg.content.slice(prefix.length).trim().split(/ +/);
const command = args.shift().toLowerCase();
if (command === 'ping') {
client.commands.get('ping').execute(msg, args);
} else if (command === 'userinfo') {
client.commands.get('userinfo').execute(msg, args);
} else if (command === 'delete') {
const amount = parseInt(args[0]) + 1;
if (isNaN(amount)) {
return msg.reply('Enter a valid number.');
} else if (amount <= 1 || amount > 100) {
return msg.reply('Enter a number between 1 and 99.');
} else {
msg.channel.bulkDelete(amount, true).catch(err => {
console.error(err);
msg.channel.send('There was an error trying to delete messages');
});
msg.channel.send(`Deleted ${args} messages.`);
}
} else if (command === 'p' || command === 'play') {
client.commands.get('play').execute(msg, args);
} else if (command === 'pause') {
client.commands.get('pause').execute(msg);
}
});
pause.js code:
module.exports = {
title: 'pause',
description: "Pause the current song.",
execute(message){
const queue = message.client.queue.get(message.guild.id);
if(!queue) return message.reply("There is nothing playing").catch(console.error);
if(queue.playing){
queue.playing = false;
queue.connection.dispatcher.pause(true);
return queue.textChannel.send(`⏸ Paused.`).catch(console.error);
}
}
};
If I copy the code and paste the same code in Client.on it's working but it's showing error while using with module.exports .Is there any way to fix this?
Looking at your pause.js export - execute is not a property of the object. Try this:
module.exports = {
title: 'pause',
description: "Pause the current song.",
execute: function (message) {
const queue = message.client.queue.get(message.guild.id);
if(!queue) return message.reply("There is nothing playing").catch(console.error);
if(queue.playing){
queue.playing = false;
queue.connection.dispatcher.pause(true);
return queue.textChannel.send(`⏸ Paused.`).catch(console.error);
}
}
};
Create a property called execute and assign it's value the function that you have.
You are adding the commands with this code:
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);
}
So the command name is the file export .name. On your expore file, you have no name property. instead, you wrote title. Try this:
module.exports = {
name: 'pause',
description: "Pause the current song.",
execute(message){
const queue = message.client.queue.get(message.guild.id);
if(!queue) return message.reply("There is nothing playing").catch(console.error);
if(queue.playing){
queue.playing = false;
queue.connection.dispatcher.pause(true);
return queue.textChannel.send(`⏸ Paused.`).catch(console.error);
}
}
};
so there you are set the command to execute by name but in your export there isn't name , which you are calling in the .get in event side , that why it return undefined , hope it's useful