djs-message-commands
TypeScript icon, indicating that this package has built-in type declarations

1.2.0 • Public • Published

Prerequisites

  • Node v16.x or higher.
  • Any package manager (npm, yarn, pnpm)

Installation

With npm:

npm install djs-message-commands

With yarn:

yarn add djs-message-commands

With pnpm:

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. I recommend looking into this guide for more in-depth details.

Documentation

Learn more and read the full documentation here!

Quick Start

Importing

JavaScript:

const { MessageCommandBuilder } = require('djs-message-commands');

TypeScript:

// 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

// **/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

// 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

// **/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!

License

MIT

Package Sidebar

Install

npm i djs-message-commands

Weekly Downloads

4

Version

1.2.0

License

MIT

Unpacked Size

36.9 kB

Total Files

9

Last publish

Collaborators

  • shockch4rge