├── .gitignore ├── utils ├── config.json └── commandCheck.js ├── interactions ├── test.js └── help.js ├── commands ├── test.js └── help.js ├── events ├── ready.js ├── interactionCreate.js └── messageCreate.js ├── package.json ├── index.js ├── handler ├── eventHandler.js ├── commandHandler.js └── interactionHandler.js └── README.MD /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | utils/permisions.js 4 | utils/error.js 5 | .eslintrc.json -------------------------------------------------------------------------------- /utils/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "!", 3 | "colors": { 4 | "default": "606C65", 5 | "error": "FF4500" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /interactions/test.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder } = require("@discordjs/builders"); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName("test") 6 | .setDescription("Just a test command"), 7 | async execute(interaction) { 8 | await interaction.reply("this is the test command"); 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /commands/test.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'test', 3 | description: 'Just a test command', 4 | aliases: [], 5 | usage: '', 6 | guildOnly: false, 7 | args: false, 8 | permissions: { 9 | bot: [], 10 | user: [], 11 | }, 12 | execute: (message, args, client) => { 13 | message.reply('this is the test command'); 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /events/ready.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | module.exports = { 4 | event: "ready", 5 | once: true, 6 | execute(client) { 7 | console.log("Bot ready"); 8 | 9 | //handle all interactions after the bot is online so you have access to guild id's 10 | fs.readdir("./interactions/", (err, files) => { 11 | const interactionsHandler = require("./../handler/interactionHandler"); 12 | interactionsHandler(err, files, client); 13 | }); 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "djs-handler", 3 | "version": "0.0.1", 4 | "description": "A easy to use command/event handler for discord.js", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "LocalStart": "node -r dotenv/config index.js" 9 | }, 10 | "author": "BracketByte", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@discordjs/builders": "^0.10.0", 14 | "@discordjs/rest": "^0.2.0-canary.0", 15 | "ascii-table": "^0.0.9", 16 | "discord-api-types": "^0.26.0", 17 | "discord.js": "^13.4.0", 18 | "dotenv": "^10.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /events/interactionCreate.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | const { prefix } = require("../utils/config.json"); 3 | 4 | module.exports = { 5 | event: "interactionCreate", 6 | execute: async (interaction, client) => { 7 | if (!interaction.isCommand()) return; 8 | 9 | const command = client.interactions.get(interaction.commandName); 10 | 11 | if (!command) return; 12 | 13 | try { 14 | await command.execute(interaction, client); 15 | } catch (error) { 16 | console.error(error); 17 | await interaction.reply({ 18 | content: "There was an error while executing this command!", 19 | ephemeral: true, 20 | }); 21 | } 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const { Client, Intents, Collection } = require("discord.js"); 4 | 5 | const client = new Client({ 6 | intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], 7 | }); 8 | 9 | client.commands = new Collection(); 10 | client.aliases = new Collection(); 11 | client.interactions = new Collection(); 12 | 13 | fs.readdir("./commands/", async (err, files) => { 14 | const commandHandler = require("./handler/commandHandler"); 15 | await commandHandler(err, files, client); 16 | }); 17 | 18 | fs.readdir("./events/", (err, files) => { 19 | const eventHandler = require("./handler/eventHandler"); 20 | eventHandler(err, files, client); 21 | }); 22 | 23 | client.login(process.env.TOKEN); 24 | -------------------------------------------------------------------------------- /handler/eventHandler.js: -------------------------------------------------------------------------------- 1 | module.exports = (err, files, client) => { 2 | if (err) return console.error(err); 3 | files.forEach((file) => { 4 | const eventFunction = require(`./../events/${file}`); 5 | if (eventFunction.disabled) return; 6 | 7 | const event = eventFunction.event || file.split(".")[0]; 8 | const emitter = 9 | (typeof eventFunction.emitter === "string" 10 | ? client[eventFunction.emitter] 11 | : eventFunction.emitter) || client; 12 | const once = eventFunction.once; 13 | 14 | try { 15 | emitter[once ? "once" : "on"](event, (...args) => 16 | eventFunction.execute(...args, client) 17 | ); 18 | } catch (error) { 19 | console.error(error.stack); 20 | } 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /handler/commandHandler.js: -------------------------------------------------------------------------------- 1 | const ascii = require("ascii-table"); 2 | const commandCheck = require("./../utils/commandCheck"); 3 | const table = new ascii().setHeading("command", "Load Status"); 4 | 5 | module.exports = async (err, files, client) => { 6 | if (err) return console.error(err); 7 | files.forEach((file, index) => { 8 | const command = require(`./../commands/${file}`); 9 | if (commandCheck(command.name, command)) { 10 | if (command.name) { 11 | client.commands.set(command.name, command); 12 | table.addRow(command.name, "✔"); 13 | 14 | if (command.aliases && Array.isArray(command)) 15 | command.aliases.foreach((alias) => 16 | client.aliases.set(alias, command.name) 17 | ); 18 | } else { 19 | table.addRow(command.name, "✖"); 20 | } 21 | } 22 | if (index == files.length - 1) console.log(table.toString()); 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /handler/interactionHandler.js: -------------------------------------------------------------------------------- 1 | const { REST } = require("@discordjs/rest"); 2 | const { Routes } = require("discord-api-types/v9"); 3 | const ascii = require("ascii-table"); 4 | 5 | module.exports = async (err, files, client) => { 6 | if (err) return console.error(err); 7 | 8 | client.interactionsArray = []; 9 | files.forEach((file) => { 10 | const interaction = require(`./../interactions/${file}`); 11 | client.interactions.set(interaction.data.name, interaction); 12 | client.interactionsArray.push(interaction.data.toJSON()); 13 | }); 14 | 15 | const rest = new REST({ version: "9" }).setToken(process.env.TOKEN); 16 | 17 | (async () => { 18 | try { 19 | console.log("Refreshing slash command list"); 20 | const guildIds = await client.guilds.cache.map((guild) => guild.id); 21 | const clientId = await client.user.id; 22 | guildIds.forEach(async (guildId) => { 23 | await rest.put(Routes.applicationGuildCommands(clientId, guildId), { 24 | body: client.interactionsArray, 25 | }); 26 | }); 27 | 28 | console.log("Successfully refreshed slash command list"); 29 | } catch (error) { 30 | console.error(error); 31 | } 32 | })(); 33 | }; 34 | -------------------------------------------------------------------------------- /utils/commandCheck.js: -------------------------------------------------------------------------------- 1 | const checkCommandModule = (cmdName, cmdModule) => { 2 | if (!cmdModule.hasOwnProperty("execute")) 3 | throw new Error( 4 | `${cmdName} command module does not have property 'execute'` 5 | ); 6 | 7 | if (!cmdModule.hasOwnProperty("description")) 8 | throw new Error( 9 | `${cmdName} command module does not have property 'description` 10 | ); 11 | 12 | if (!cmdModule.hasOwnProperty("aliases")) 13 | throw new Error( 14 | `${cmdName} command module does not have property 'aliases'` 15 | ); 16 | 17 | return true; 18 | }; 19 | const checkCommandProperties = (cmdName, cmdModule) => { 20 | if (typeof cmdModule.execute !== "function") 21 | throw new Error(`${cmdName} command: execute is not a function`); 22 | 23 | if (typeof cmdModule.description !== "string") 24 | throw new Error(`${cmdName} command: description is not a string`); 25 | 26 | if (!Array.isArray(cmdModule.aliases)) 27 | throw new Error(`${cmdName} command: aliases is not an Array`); 28 | 29 | return true; 30 | }; 31 | 32 | module.exports = (cmdName, cmdModule) => { 33 | return ( 34 | checkCommandModule(cmdName, cmdModule) && 35 | checkCommandProperties(cmdName, cmdModule) 36 | ); 37 | }; 38 | -------------------------------------------------------------------------------- /events/messageCreate.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | const { prefix } = require("../utils/config.json"); 3 | 4 | module.exports = { 5 | event: "messageCreate", 6 | execute: async (message, client) => { 7 | if (!message.content.startsWith(prefix) || message.author.bot) return; 8 | const args = message.content.slice(prefix.length).split(/ +/); 9 | const commandName = args.shift().toLowerCase(); 10 | const command = 11 | client.commands.get(commandName) || 12 | client.commands.find( 13 | (cmd) => cmd.aliases && cmd.aliases.includes(commandName) 14 | ); 15 | 16 | if (!command) return; 17 | 18 | if (command.guildOnly && message.channel.type !== "text") { 19 | return message.reply("I can't execute that command inside DMs!"); 20 | } 21 | 22 | if (command.args && !args.length) { 23 | let reply = `You didn't provide any arguments, ${message.author}!`; 24 | if (command.usage) { 25 | reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``; 26 | } 27 | return message.channel.send(reply); 28 | } 29 | 30 | try { 31 | command.execute(message, args, client); 32 | } catch (error) { 33 | console.error(error); 34 | message.reply("There was an error trying to execute that command!"); 35 | } 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # Command and Event Handler For Discord.js! 2 | 3 | Simple and easy to use command and event handler 4 | with useful features. 5 | 6 | ## INFO 7 | 8 | **!** The command handler used in this repository is based on the official discord.js command handler 9 | 10 | **!** Make sure that you have Node.js and NPM installed and up to to date on your system 11 | 12 | ## HOW DO I SETUP MY BOT? 13 | 14 | **!** If you'r hosting the bot on your loca machine create a new file in the root of the directory of the project called `.env` and write in it `TOKEN=your_token_goes_here` if not, add the token to your bot environtment variables with the name of `TOKEN` 15 | 16 | **!** Set your prefix in `utils/config.json` 17 | 18 | **!** Run `npm install` in your terminal 19 | 20 | ## HOW DO I START THE BOT? 21 | 22 | **!** If it's not your first time running this bot, run `npm run start` in your terminal 23 | 24 | **!** Use `npm run LocalStart` in your terminal if you'r running the bot on a local machine to make use of the .env file 25 | 26 | ## HOW TO ADD NEW COMMANDS? 27 | 28 | **1** Create a new .js file in the commands folder with the name of your command. 29 | 30 | **2** Populate the file with the code reprezented here: 31 | 32 | ```js 33 | module.exports = { 34 | name: "commanad name", 35 | description: "description of your command", 36 | aliases: ["aleas1", "alias2"], 37 | usage: "[argument1] [argument2]", 38 | guildOnly: false, //true if only used in server 39 | args: false, //true if the command cant run without arguments 40 | permissions: { 41 | bot: [], //permissions that the bot requires for the command 42 | user: [], //permissions that the user requires for the command 43 | }, 44 | execute: async (message, args, client) => { 45 | //code for the command goes here 46 | }, 47 | }; 48 | ``` 49 | 50 | **3** start your bot and see if it works! 51 | -------------------------------------------------------------------------------- /interactions/help.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder } = require("@discordjs/builders"); 2 | const Discord = require("discord.js"); 3 | const { colors } = require("./../utils/config.json"); 4 | const embedColor = colors.default; 5 | const embedError = colors.error; 6 | 7 | module.exports = { 8 | data: new SlashCommandBuilder() 9 | .setName("help") 10 | .setDescription("Get help on how to use the bot and the specific commands") 11 | .addStringOption((option) => 12 | option 13 | .setName("name") 14 | .setDescription("Name the command you want help with!") 15 | .setRequired(false) 16 | ), 17 | async execute(interaction, client) { 18 | //await interaction.reply({ content: "work in progress!", ephemeral: true }); 19 | const string = interaction.options.getString("name"); 20 | 21 | if (!string) { 22 | const cmdHelpEmbed = new Discord.MessageEmbed() 23 | .setTitle("**HELP**") 24 | .setDescription( 25 | `Command list: \n\`${client.interactions 26 | .map((command) => command.data.name) 27 | .join( 28 | " | " 29 | )}\`\nYou can use \`/help {command name}\` to get info about a specific command!` 30 | ) 31 | .setColor(embedColor); 32 | return interaction.reply({ 33 | embeds: [cmdHelpEmbed], 34 | }); 35 | } 36 | 37 | const command = client.interactions.get(string); 38 | 39 | if (!command) { 40 | const cmdDoesntExist = new Discord.MessageEmbed() 41 | .setTitle("Command not found!") 42 | .setDescription( 43 | `Command "${string}" doesn't exist! \nUse /help for list of all commands.` 44 | ) 45 | .setColor(embedError); 46 | return interaction.reply({ 47 | embeds: [cmdDoesntExist], 48 | }); 49 | } 50 | 51 | const cmdHelpEmbed = new Discord.MessageEmbed() 52 | .setTitle(`${command.data.name} | Command info`) 53 | .setDescription( 54 | `Command name: **${command.data.name}**\n${command.data.description}` 55 | ) 56 | .setColor(embedColor); 57 | 58 | return interaction.reply({ embeds: [cmdHelpEmbed] }); 59 | }, 60 | }; 61 | -------------------------------------------------------------------------------- /commands/help.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | const { prefix, colors } = require("./../utils/config.json"); 3 | const embedColor = colors.default; 4 | const embedError = colors.error; 5 | 6 | module.exports = { 7 | name: "help", 8 | description: "Get help on how to use the bot and the specific commands", 9 | aliases: ["?", "h"], 10 | usage: "[command name]", 11 | guildOnly: false, 12 | args: false, 13 | slash: true, 14 | permissions: { 15 | bot: [], 16 | user: [], 17 | }, 18 | execute: async (message, args, client) => { 19 | const { commands } = message.client; 20 | 21 | if (!args.length) { 22 | const cmdHelpEmbed = new Discord.MessageEmbed() 23 | .setTitle("**HELP**") 24 | .setDescription( 25 | `Command list: \n\`${commands 26 | .map((command) => command.name) 27 | .join( 28 | " | " 29 | )}\`\nYou can use \`${prefix}help {command name}\` to get info about a specific command!` 30 | ) 31 | .setColor(embedColor); 32 | return message.channel.send({ 33 | embeds: [cmdHelpEmbed], 34 | }); 35 | } 36 | 37 | const name = args[0].toLowerCase(); 38 | const command = 39 | commands.get(name) || 40 | commands.find((cmd) => cmd.aliases && cmd.aliases.includes(name)); 41 | 42 | if (!command) { 43 | const cmdDoesntExist = new Discord.MessageEmbed() 44 | .setTitle("Command not found!") 45 | .setDescription( 46 | 'Command "' + 47 | message.args[0] + 48 | "\" doesn't exist!\nUse `" + 49 | prefix + 50 | "help` for list of all commands." 51 | ) 52 | .setColor(embedError); 53 | return message.channel.send({ 54 | embeds: [cmdDoesntExist], 55 | }); 56 | } 57 | const cmdHelpEmbed = new Discord.MessageEmbed() 58 | .setTitle(`${command.name} | Command info`) 59 | .setDescription(command.description) 60 | .addField("Usage", `\`${prefix + command.name} ${command.usage}\``, true) 61 | .setColor(embedColor); 62 | 63 | if (command.aliases) { 64 | cmdHelpEmbed.addField( 65 | "Aliases", 66 | `\`${command.aliases.join(" | ")}\``, 67 | true 68 | ); 69 | } 70 | 71 | return message.channel.send({ embeds: [cmdHelpEmbed] }); 72 | }, 73 | }; 74 | --------------------------------------------------------------------------------