npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

djs-message-commands

v1.2.0

Published

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

Downloads

2

Readme

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