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.
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"
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)
}
I just finished my bot and wanted to invite it to another server to test it out.
However, when I typed / no commands showed up.
When I invited the bot I enabled application.commands so I can use the slashcommands but it still did not work. My bot also has a global slashcommand handler so it should normally work right?
I don't know if the handler code is needed but I'll still add it here in case you do need it:
const { Perms } = require('../Validation/Permissions');
const { Client } = require('discord.js');
/**
* #param {Client} client
*/
module.exports = async (client, PG, Ascii) => {
const Table = new Ascii("Command Loaded");
CommandsArray = [];
(await PG(`${process.cwd()}/Commands/*/*.js`)).map(async (file) => {
const command = require(file);
if(!command.name)
return Table.addRow(file.split("/")[7], "⛔ FAILED", "Missing a name.")
if(command.type !== "USER" && !command.description)
return Table.addRow(command.name, "⛔ FAILED", "Missing a description.")
if(command.permission){
if(Perms.includes(command.permission))
command.defaultPermission = false;
else
return Table.addRow(command.name, "⛔ FAILED", "Permission is invalid.")
}
client.commands.set(command.name, command);
CommandsArray.push(command);
await Table.addRow(command.name, "✅ SUCCESSFUL");
});
console.log(Table.toString());
// PERMISSIONS CHECK //
client.on("ready", async () =>{
client.guilds.cache.forEach((g) => {
g.commands.set(CommandsArray).then(async (command) =>{
const Roles = (commandName) => {
const cmdPerms = CommandsArray.find((c) => c.name === commandName).permission;
if(!cmdPerms) return null;
return g.roles.cache.filter((r) => r.permissions.has(cmdPerms) && !r.managed).first(10);
}
const fullPermissions = command.reduce((accumulator, r) =>{
const roles = Roles(r.name);
if(!roles) return accumulator;
const permissions = roles.reduce((a, r) =>{
return [...a, {id: r.id, type: "ROLE", permission:true}]
}, []);
return [...accumulator, {id: r.id, permissions}]
}, []);
await g.commands.permissions.set({ fullPermissions });
});
})
});
}
You have to register the command first, which is essentially creating the command within Discord. Follow the guide to get it set up. And to clarify, you only register the command once, if that isn't obvious.
You can use Postman to create/edit the commands if you are comfortable with it.
This question already has answers here:
What are the rules for JavaScript's automatic semicolon insertion (ASI)?
(7 answers)
Closed last year.
I am making a Discord bot command handler, and I keep getting this error:
(await PG(`${process.cwd()}/Commands/*/*js`)).map(async (file) => {
^
TypeError: [] is not a function
Here is my code:
const { Perms } = require('../Validation/Permissions');
const { Client } = require('discord.js')
const { promisify } = require("util")
const { glob } = require('glob');
const PG = promisify(glob)
const Ascii = require('ascii-table')
/**
* #param {Client} client
*/
module.exports = async (client) => {
const Table = new Ascii('Command Loaded')
CommandsArray = []
(await PG(`${process.cwd()}/Commands/*/*js`)).map(async (file) => {
const command = require(file);
if (!command.name)
return Table.addRow(file.split("/")[7], 'FAILED', 'Missing a name.')
if (!command.description)
return Table.addRow(command.name, 'FAILED', 'Missing the description.')
if (command.permission) {
if (Perms.includes(command.permission))
command.defaultPermission = false;
else
return Table.addRow(command.name,'FAILED','Permission is invalid')
}
client.commands.set(command.name, command);
CommandsArray.push(command);
await Table.addRow(command.name, 'SUCCESSFUL');
})
console.log(Table.toString())
// Permissions check //
client.on('ready', async() => {
const MainGuild = await client.guilds.cache.get('940180806696058910');
MainGuild.commands.set(CommandsArray).then(async (command) => {
const Roles = (commandName) => {
const cmdPerms = CommandsArray.find((c) => c.name === commandName).permission
if (!cmdPerms) return null;
return MainGuild.roles.cache.filter((r) => r.permissions.has(cmdPerms))
}
const fullPermissions = command.reduce((accumulator, r) => {
const roles = Roles(r.name);
if (!roles) return accumulator;
const permissions = roles.reduce((a, r) => {
return [...a,{id: r.id, type: 'ROLE', permission: true}]
}, [])
return [...accumulator, {id: r.id, permissions}]
}, [])
await MainGuild.commands.permissions.set({ fullPermissions });
})
})
}
I've done some googling, but I was unable to find anything related to just [], type error usually appears when there is a spelling mistake in your code. I have gone through my code numerous times and have been completely unable to find any mistakes, I just cannot figure this out.
I would really appreciate some help, thank you!
Please use semi-colons!
Add ; onto the line above the PG where you define an empty array, JS sees the array and also brackets right after and this thinks you are executing a function because JS when compiled does not look at lines or spacing.
CommandsArray = [];
(await PG(`${process.cwd()}/Commands/*/*js`)).map(async (file) => {
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)
})