@squiddleton/discordjs-util
v1.3.0
Published
Utility classes and functions for discord.js
Downloads
95
Maintainers
Readme
discord.js-Util
About
Useful utility classes and functions that make discord.js bot developing more efficient.
Usage
Node.js v14+ is required.
First, install this scoped package by running the following command in your terminal:
npm install @squiddleton/discordjs-util
Client
The package exports a Client
class that extends the native discord.js class of the same name. By providing more options when initializing it, more features become available:
const { Client } = require('@squiddleton/discordjs-util'); // This package is compiled to CommonJS, so both require() and import syntax are supported
const { GatewayIntentBits } = require('discord.js'); // This package supplements discord.js instead of replacing it
// 'devGuildId' is one property added to the extended Client options, but
// more are available as shown in the extended ClientOptions TSDoc annotations
const client = new Client({ intents: [GatewayIntentBits.Guilds], devGuildId: '1234567890123456789' });
client.on('ready', () => {
console.log(client.devGuild.name); // Prints the name of the devGuild retrieved from its id
});
client.login('token here');
Commands
The SlashCommand
and ContextMenu
classes provide support for the construction of Chat Input and Context Menu application commands, respectively.
const { Client, ContextMenu, evalCommand, SlashCommand } = require('@squiddleton/discordjs-util');
const pingCommand = new SlashCommand({
name: 'ping',
description: 'Replies with pong',
scope: 'Global', // Scopes determine where commands are deployed to
async execute(interaction) {
await interaction.reply('Pong!');
}
});
const evalContextMenu = new ContextMenu({
name: 'Eval',
type: ApplicationCommandType.Message,
scope: 'Dev', // Only deployed to the server indicated with the "devGuildId" in the ClientOptions
async execute(interaction) {
await evalCommand(interaction, interaction.targetMessage.content, true); // evalCommand() is a function tailored for application commands
}
});
const client = new Client({ intents: [GatewayIntentBits.Guilds], commands: [pingCommand, evalContextMenu] });
client.on('ready', async () => {
if (client.isReady()) {
await client.deploy(); // Deploys all commands from the ClientOptions "commands" array (should only be called when command structures are updated)
}
});
client.login('token here');
The constructor argument can contain other properties familiar to the official discord.js guide's command handler, including options
and permissions
.
The scope
property of a command is entirely custom, and it determines where the command will be deployed. There are four possible scopes:
- Global: The command is deployed globally and is accessible in both servers and direct messages.
- Guild: The command is deployed globally but is only accessible in servers.
- Dev: The command is only deployed in the guild with the id from
devGuildId
in theClientOptions
(if provided). - Exclusive: The command is only deployed in the guild with the id from
exclusiveGuildId
in theClientOptions
(if provided) and deployed in the devGuild (if provided). This is to ensure that all commands are accessible in the devGuild.
Both command class instances have a .toJSON()
method which returns an object in ApplicationCommandData
format. The ContextMenu
class also has .isMessage()
and .isUser()
methods which will narrow down the its specific type.
Events
The ClientEvent
class standardizes the construction of the events that the client emits, and it automatically adds listeners for those events to the client upon construction.
const { Client, ClientEvent } = require('@squiddleton/discordjs-util');
const event1 = new ClientEvent({
name: 'ready',
once: true, // Registers the event using EventEmitter#once() instead of EventEmitter#on()
async execute(client) {
console.log(`Now logged in as ${client.user.tag}!`);
}
});
const event2 = new ClientEvent({
name: 'interactionCreate',
async execute(interaction) { // No "once" property defaults to using #on()
if (interaction.isRepliable()) {
await interaction.reply('Hi!');
}
}
});
const client = new Client({ intents: [GatewayIntentBits.Guilds], events: [event1, event2] });
// When ready, the Client's username will be logged, and any application command interactions will be met with "Hi!"
client.login('token here');
Miscellaneous
Along with the aforementioned evalCommand()
function, this package has two more functions as top-level exports: validateChannel()
and validateGuild()
.
Using the normal discord.js method <Client>.(channels|guild).cache.get(<Id>)
returns a union type of either the expected structure or undefined
. Additionally, getting channels by this method provides no automatic typeguarding, so typeguards like <BaseChannel>.isTextBased()
must be used before calling .send()
on the channel. Both of these methods return solely the structure instead of possibly returning undefined
; if the structure is unavailable, an error will be thrown to call out this unexpected behavior. When the third argument of validateChannel()
is set to true
(the default value), it will also only return a TextBasedChannel
, otherwise throwing an error. Although these functions may seem insignificant, TypeScript users will find this automatic type narrowing much more efficient than manually checking every time a channel/guild is retrieved.
const { Client, ClientEvent, validateChannel, validateGuild } = require('@squiddleton/discordjs-util');
const ready = new ClientEvent({
name: 'ready',
once: true,
async execute(client) {
const channel = validateChannel(client, '1234567890123456789'); // TextBasedChannel instead of Channel|undefined
const guild = validateGuild(client, '987654310987654321'); // Guild instead of Guild|undefined
await channel.send(guild.name);
}
});
const client = new Client({ intents: [GatewayIntentBits.Guilds], events: [ready] });
Credits
This package is fully independent and unaffiliated with both Discord Inc. and discord.js.