UNPKG

djs-message-commands

Version:

Build easy, safe, and testable message commands for discord.js

203 lines (143 loc) 6.25 kB
## Prerequisites - Node v16.x or higher. - Any package manager (npm, yarn, pnpm) ## Installation With npm: ```bash npm install djs-message-commands ``` With yarn: ```bash yarn add djs-message-commands ``` With pnpm: ```bash pnpm install djs-message-commands ``` With djs-message-commands comes a few features: - **Command aliases** Commands with long names can be given multiple aliases, reducing the user fatigue required to execute it and at the same time keeping full detail. - **Roles and permissions checking** Each command can be prerequisited by a list of roles and permissions before executing it, so that you can focus on a pure command implementation by separating adminstrative validation. - **Options** Similar to discord.js' SlashCommandOption, these are simply parameters of a message command. They are used to define the type of arguments that are expected to be passed in by the user. - **Options (choices)** For some option types, you can define a list of choices that the user can choose from. ## Background Ever since discord.js v13, slash commands have been far superior to message commands for both the developers and users. **Implementing a system for message commands is hard because:** - Commands need to be parsed into reliable, consistent formats, while handling _way_ too many edge cases (e.g. spacing between each argument, missing arguments, etc.) - Restricting specific arguments to pre-determined values (e.g. only allow specific strings, numbers etc.) and validating argument types requires special implementation and complicated regular expressions. - A scalable way to create commands had to be scrutinised over. - Handle permission/role descrepancies. Checking administrative privileges was often mixed in with command execution. - _and a lot more..._ you know what I'm talking about. While these problems have been widely acknowledged by the community, they are still a pain to deal with, as other packages don't quite hit the mark in terms of ease of use, e.g. consistency with discord.js, robustness etc. This package aims to provide a safe and easy way to manage, create, and validate message commands, with an architecture reminiscent of discord.js' slash command builders. > - Required options are not supported as of now. They might come in later release. > - While this package tries to be unopinionated, it still follows [discord.js' guide on managing file structure.](https://discordjs.guide/creating-your-bot/command-handling.html#individual-command-files) I recommend looking into this guide for more in-depth details. ## Documentation Learn more and read the full documentation [here!](https://shockch4rge.github.io/djs-message-commands/) ## Quick Start ### Importing JavaScript: ```js const { MessageCommandBuilder } = require('djs-message-commands'); ``` TypeScript: ```ts // with "allowSyntheticDefaultImports": false // recommended way to import, even when set to true import { MessageCommandBuilder } from "djs-message-commands"; // with "allowSyntheticDefaultImports": true import DMC from "djs-message-commands"; // or any other name you want ``` ### Defining commands ```js // **/commands/message/foo.js const { MessageCommandBuilder } = require("djs-message-commands"); module.exports = { builder: new MessageCommandBuilder().setName("foo").setDescription("bar"), execute: async (client, message, options) => { // some code here... }, }; ``` ### Receiving commands ```js // index.js // Collection util class from discord.js const commands = new Collection(); // saving the commands defined in the 'commands' directory for (const file of fs.readdirSync("./commands/message")) { const command = require(`./commands/message/${file}`); // use the builder's name as the key commands.set(command.builder.name, command); // set potential aliases the command may have with the same data for (const alias of command.builder.aliases) { commands.set(alias, command); } } client.on("messageCreate", async message => { if (message.author.bot) return; const args = message.content.trim().split(/\s+/); // if the prefix doesn't match, ignore the message if (args[0].slice(0, PREFIX.length) !== PREFIX) return; await message.channel.sendTyping(); const commandName = args[0].slice(PREFIX.length); const command = commands.get(commandName); if (!command) { // handle command not found return; } // get errors and parsed options const [errors, options] = command.builder.validate(message); if (errors) { console.warn(errors); return; } try { await command.execute(client, message, options); } catch (err) { // handle execution error... } }); ``` ### Handling options ```js // **/commands/message/foo.js const { MessageCommandBuilder } = require("djs-message-commands"); module.exports = { builder: new MessageCommandBuilder() .setName("send-dm") .setDescription("Sends a DM to a member.") .addStringOption(option => option // you can name this however you want .setName("content") .setDescription("The text to send.") ) .addNumberOption(option => option.setName("repeats").setDescription("How many times to repeat the message.") ) .addMemberOption(option => option.setName("member").setDescription("The member to send the DM to.")), execute: async (client, message, options) => { const [content, repeats, memberId] = options; // any mentionable option extracts the Snowflake from the message // to get the actual target, use fetch() or cache.get() const member = await message.guild?.members.fetch(memberId); // OR const member = await message.guild?.members.cache.get(memberId); if (member) { for (let i = 0; i < repeats; i++) { // send the message based on the number of repeats await member.send(content); } } }, }; ``` ## Contribution If you have any enquiries, please open an issue or pull request on the [GitHub repository](https://github.com/Shockch4rge/djs-message-commands)! ## License MIT