1.0.4 • Published 2 years ago

@jaxydog/botbuilder v1.0.4

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

BotBuilder

BotBuilder is a utility library for making the process of creating Discord bots a lot easier (and way less prone to outright crashing).

Through its client wrapper, BotBuilder provides methods for easily creating buttons, application commands, embeds, modals, select menus, and more. The wrapper also includes a local cache for creating dynamic local variables on the fly, and a storage module that provides access to the file system (also with a cache, to keep the bot running fast).

Installation

> npm i @jaxydog/botbuilder

Setting up a bot client

Client definition

BotBuilder clients can be created with the BotClient wrapper, and must be at least provided with a client token. See Client configuration for more client configuration options.

// *snip*

import { BotClient } from "@jaxydog/botbuilder"

const client = new BotClient({
	intents: ["DIRECT_MESSAGES", "GUILDS", "GUILD_MESSAGES"],
	token: "Your token here",
})

// *snip*

client.connect()

Source: examples/ping.ts

Creating an application command

Creating application commands has been made as easy as possible while still allowing for as much complexity as vanilla Discord.js. To register a command, you must first .define(...) it and provide the structure that the BotWrapper will use to register it with the API.

Once the command is defined, you may use .create(...) to provide the interaction listener. This listener will only trigger when the interaction's commandName is equal to the provided string identifier. For a complete list of methods, see ActionManager methods.

All interaction listeners are provided with an ActionContext object, which contains the interaction object, the bot client, ID data, as well as some utility functions.

// *snip*

client.action.command
	// `define` stores the structure of the command in memory
	.define("ping", {
		name: "ping",
		description: "Tests the bot's connection",
	})
	// `create` stores the event listener of the command in memory
	.create("ping", async (context) => {
		const reply = (await context.interaction.reply({
			content: "Calculating...",
			ephemeral: true,
			fetchReply: true,
		})) as Message

		const delay = reply.createdTimestamp - context.interaction.createdTimestamp

		await context.interaction.editReply({ content: `Pong! (${delay}ms)` })
	})

// *snip*

Source: examples/ping.ts

Creating other interaction callbacks

The client wrapper also has the functionality to register callbacks for specific interaction types natively. These action managers are accessed through client.action, and do not require a .define(...) call.

client.action.button.create("button", async (context) => {
	// interaction callback
})
client.action.modal.create("modal", async (context) => {
	// interaction callback
})
client.action.selectMenu.create("select_menu", async (context) => {
	// interaction callback
})

Utilizing the Clock

The BotClient provides you with an internal clock, which will regularly execute registered callbacks at the provided interval (see client configuration). This can be used for updating the bot's status at regular intervals or performing other actions that need to occur regularly. The clock is automatically started once the client connects to the API.

If for some reason during runtime you need to remove a clock callback, it will return a symbol that you can use to remove it with clock.remove(...). The clock can also be dynamically stopped and started, and you can trigger all callbacks at any point as well (this does not reset the clock timer).

client.clock.add(async (client) => {
	client.logger.info("This will be called every 30 seconds by default!")
})

Client storage

The client wrapper includes a .cache property, which allows you to save and load local variables dynamically. These values are permanently deleted when the process is closed.

client.cache.set("id", { value: 123 })
client.cache.get<{ value: number }>("id") // => { value: 123 }

If you need a more permanent solution, then the .storage property is for you. It saves files locally to the disk, within the ./data folder (which will be generated if it does not exist). It also includes its own built-in cache so it will be just as fast after the first load. The cache also provides the secondary purpose of behaving as a fallback in case data can't be found on the disk.

client.storage.set("id", { value: 321 })
client.storage.get<{ value: number }>("id") // => { value: 321 }

For all methods provided by storage instances, see Storage methods. For all storage options, see Storage options.

Builders

BotBuilder provides multiple classes that help make creating instances of certain objects less cluttered or confusing.

Most builders that contain a .id(...) method support data IDs, which allow the bot to share data across interactions. Keep in mind that custom IDs have a maximum size of 100 characters, so if the data exceeds that it will be ignored.

Buttons

new ButtonBuilder()
	.id("button", "custom_data_max_100_chars")
	.style("PRIMARY")
	.emoji("🙂")
	.label("Clicky clicky")
	.build()

Embeds

new EmbedBuilder()
	.color("BLURPLE")
	.author("Discord Bot")
	.title("Rich embed!")
	.description("💰 We're rich! 💰")
	.footer("Embed footer")
	.build()

Modals

new ModalBuilder()
	.id("modal", "custom_data_max_100_chars")
	.title("My very cool epic modal")
	.field(
		new ModalFieldBuilder()
			.id("field")
			.style("SHORT")
			.label("Text field")
			.min(5)
			.max(100)
			.placeholder("Text value between 5 and 100 chars")
			.required(true)
			.build()
	)
	.build()

Select Menus

new SelectMenuBuilder()
	.id("select_menu", "some_more_custom_data")
	.option({
		label: "First",
		value: "1",
	})
	.option({
		label: "Second",
		value: "2",
	})
	.option({
		label: "Third",
		value: "3",
	})
	.option({
		label: "Fourth",
		value: "4",
	})
	.option({
		label: "Fifth",
		value: "5",
	})

Other features

Client configuration

clockInterval - Clock interval in milliseconds; defaults to 30_000 (30 seconds)

color - Log color; defaults to "#5865F2"

devGuilds - Development guild identifiers; application commands are always updated here

globalUpdate - Whether to update global application commands; defaults to false

intents - Client intents bitfield

name - Bot name; used in logging and defaults to "Discord Bot"

saveLogs - Whether to save log files; defaults to false

silent - Disables logging when enabled; defaults to false

token - Client token

version - Bot version; used in logging

ActionContext methods

guild() - Returns the interaction guild, throwing an error if it does not exist

channel() - Returns the interaction channel, throwing an error if it does not exist

member() - Returns a promise that resolves to the member instance of the user who created the interaction, throwing an error if it does not exist

requirePermissions(...) - Ensures that the interaction member has the required permissions, and throws an error if it does not

ActionManager methods

create(...) - Creates an action callback

invoke(...) - Invokes an action callback

DefinedActionManager methods

create(...) - Creates an action callback

invoke(...) - Invokes an action callback

define(...) - Defines a data structure

Storage options

extension - File extension

noCache - Tells the request to ignore the cache

noFile - Tells the request to ignore the file system

Storage methods

has(...) - Checks whether data exists at the given identifier

hasAll(...) - Checks whether data exists at all given identifiers

hasAny(...) - Checks whether data exists at any given identifiers

get<T>(...) - Fetches the data at the given identifier, if it exists

getAll<T>(...) - Fetches the data at the given identifiers, if it exists

set<T>(...) - Stores the given data within the provided identifier

setAll<T>(...) - Stores all given data within the provided identifiers

del(...) - Deletes the data within the given identifier

delAll(...) - Deletes the data within the given identifiers

list<T>(...) - Fetches all identifiers and their data within the given directory

ids(...) - Fetches all identifiers within the given directory

values<T>(...) - Fetches all data within the given directory

ensure<T>(...) - Fetches the data within the identifier, saving it as the fallback if it does not exist

expect<T>(...) - Returns whether the requested data matches the given predicate, if it exists

expectAll<T>(...) - Returns whether all of the requested data matches the given predicate, if it exists

expectAny<T>(...) - Returns whether any of the requested data matches the given predicate, if it exists

action<T>(...) - Executes the given action on the requested data, if it exists

actionIf<T>(...) - Executes the given action on the requested data, if it exists and matches the provided predicate

actionAll<T>(...) - Executes the given action on the requested data, if it exists

actionAllIf<T>(...) - Executes the given action on the requested data, if it exists and matches the provided predicate

modify<T>(...) - Modifies the requested data, if it exists

modifyIf<T>(...) - Modifies the requested data, if it exists and matches the provided predicate

modifyAll<T>(...) - Modifies the requested data, if it exists

modifyAllIf<T>(...) - Modifies the requested data, if it exists and matches the provided predicate