Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Disploy/disploy

Warning: We're still in development, and packages are published to npm every 12 hours to the @dev tag. You can view our v1.0.0 milestone to see what features are planned for the first release and their current status.

Disploy is a flexible router for building HTTP interaction-based Discord bots with ease. It's designed to make it easy to build, test and deploy Discord bots.

Features

Disploy features a library and an opinionated framework with tooling inspired by Next.js.

Library

Disploy does not come included with a "server", that's up to you to implement. We have a guide showcasing you how to do so with Express (Node.js) and Deno's inbuilt server.

This is a slimmed-down guide to using Disploy with Next.js as your server.

Usage with Next.js

The API entry point:

// Entrypoint - pages/api/interactions.ts
import { createNextAdapter } from 'disploy';
import { ExampleApp } from '../../lib/main';
export default createNextAdapter(ExampleApp);

Note: An "adapter" is a function that transforms requests from your server implementation of choice and creates a TRequest that's fed into App#router#entry which returns a Promise<TResponse> which your adapter should transform and return to Discord.

Setting up the Disploy App:

// Main Bot - lib/core/main.ts
import { App } from 'disploy';
import commands from './commands/commands';
const clientId = process.env.DISCORD_CLIENT_ID;
const token = process.env.DISCORD_TOKEN;
const publicKey = process.env.DISCORD_PUBLIC_KEY;
if (!clientId || !token || !publicKey) {
	throw new Error('Missing environment variables');
}
export const ExampleApp = new App({
	logger: {
		debug: true,
	},
	commands,
});
ExampleApp.start({
	clientId,
	token,
	publicKey,
});

Setting up an array of commands:

// Command Array - lib/core/commands/commands.ts
import Ping from './core/ping';
const c = [Ping];
export default c;

Example command:

import type { ChatInputInteraction, Command } from 'disploy';
const Ping: Command = {
	name: 'ping',
	description: 'pong!',
	run(interaction: ChatInputInteraction) {
		interaction.reply({
			content: 'Hello World!',
		});
	},
};
export default Ping;

Framework

Disploy comes inbuilt with a CLI that can bundle your bot based on a file system structure, which is inspired by Next.js.

Use the "TypeScript Framework" boilerplate from create-disploy-app.

npx create-disploy-app@latest

Here are two examples, a command and a message component handler. Keep in mind none of this is exclusive to the framework, the only "framework exclusive" feature showcased here is the file structure and default exports.

// Example command - commands/ping.ts
import type { Command } from 'disploy';
export default {
	// Command "data"
	name: 'ping',
	description: 'pong!',
	// Command entrypoint
	async run(interaction) {
		if (!interaction.guild) {
			return void interaction.reply({
				content: 'You must use this in a guild.',
			});
		}
		interaction.deferReply(); // Synchronously reply to the incoming HTTP request
		const guild = await interaction.guild.fetch(); // BaseInteraction#guild is a ToBeFetched class, awaiting fetch on it will return the full structure
		// All our methods take in raw JSON (or our Message structure, coming soon)
		return void interaction.editReply({
			content: 'hello world!!!!!!!!',
			components: [
				{
					type: 1,
					components: [
						{
							type: 2,
							label: 'Click me!',
							style: 1,
							custom_id: `ping-${interaction.user.id}`, // You can handle message components with express-like routes.
						},
					],
				},
			],
		});
	},
} satisfies Command;
// Example message component handler - handlers/ping.ts
import type { ButtonHandler } from 'disploy';
export default {
	customId: 'ping-:userId',
	async run(interaction) {
		const originalUser = await interaction.params.getUserParam('userId'); // This fetches a user structure from the interaction's params, it would be better to use getParam in this use case, but we're showcasing the getUserParam method here.
		const clicker = interaction.user;
		return void interaction.reply({
			content: `hello world!!!!!!!! (clicked by ${clicker}) [made by ${originalUser}]`,
		});
	},
} satisfies ButtonHandler;
disploy dev # test your bot locally with hot-reloading and tunneling
disploy deploy # deploy your bot to Cloudflare Workers

The CLI bundles your app by taking in commands and message components and turning them into a single bundle. It accomplishes this by transforming your default exports into an array, creating an App instance, and attaching an adapter for your specified target.

Planned Features

Testing

@disploy/disbench will be a testing library that will allow you to test your bot in a similar way to how you would test a web app with a mocked Discord API. View the repository here.

Example usage (this is not final):

// Disbench demo snippet (fake code)
import { Disbench } from '@disploy/disbench';
const disbench = new Disbench({
	app: 'dist/bot.js',
});
await disbench.setup(); // This will start the bot and start communicating with the framework to "deploy" commands to the mocked API
const echoCommand = disbench.commands.find({ name: 'echo' });
const response = await disbench.interact(echoCommand, {
	options: {
		message: 'Hello World!',
	},
});
expect(response).toEqual('Hello World!');

Join our Discord server for support and updates!

About

Flexible router for building HTTP interaction-based Discord bots with ease.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

Contributors

AltStyle によって変換されたページ (->オリジナル) /