Gouge

A Discord slash commands library

mcpar-land/gouge

Just this month, Discord has released their Slash Commands and Interactions API, which introduces inline commands with suggestion, validation, and everything else you need built in.

a

a

Talk about a UX improvement.

Included is the ability to handle all incoming commands without a running gateway bot. This is awesome! I wanted to start working with this right away. Problem is: none of the big Discord bot frameworks (Discord.js and others) handle these commands (yet, as of this writing on 3/26/2021).

So I wrote my own!

Here’s an example Gouge (like a slash, but deeper) bot with a single command, bagel. This command has two arguments:

  • kind, for which kind of bagel to order. It should only ever be one of these: Plain, Blueberry, Poppy, Cinnamon.
  • amount, an integer for the amount of bagels to order.
import { GougeClient, command } from 'gouge'

const client = new GougeClient({
	id: process.env.CLIENT_ID,
	key: process.env.PUBLIC_KEY,
	secret: process.env.CLIENT_SECRET,
	token: process.env.BOT_TOKEN,
})

client.with(
	command('bagel', 'Order a number of bagels')
		.string('kind', 'The kind of bagel to order', true, [
			'Plain',
			'Blueberry',
			'Poppy',
			'Cinnamon',
		])
		.integer('amount', 'The amount of bagels to order', true)
		.handler(async (client, respond, [kind, amount]) => {
			await respond(
				'You ordered ' + amount + ' ' + kind + ' bagels.'
			)
		})
)

client.start(3000)

Just this code does the following:

A call from a user like this:

/bagel kind:Plain amount:34

Is responded to with:

You ordered 34 Plain bagels.

Slick!

But probably the most ergonomic feature is that a command’s handler arguments are typed. Take this example command, with three arguments of types User, Channel, and Role.

a

That array [user, channel, role]? It’s type is [IUser, IChannel, IRole], determined automatically by the preceding arguments.

a

a

a

I did this with some pretty hideous Typescript cajoling in the background, but it’s all hidden from the developer, with the result being a perfectly type-safe handler-writing experience.

(Also: if an argument is labeled as optional, it’ll type to being | undefined in the handler!)

There’s also support for all the other features that writing a slash command bot might need

  • Subcommands
  • Subcommand Groups
  • Auto-deleting global commands on restart, if they aren’t defined in your code any longer.
  • Optional raw-handling of interactions without a registered handler, for rolling your own method.

There’s also a pretty neat auto-generating docs, and a work in progress wiki that’ll contain tutorials for coders old and new (new especially - in my experience, Discord Bot is a very common first-timer coding project). This is my first real shot at building an open source library for wider use, I want to make sure the developer experience is at least on par with the high-quality mainline stuff I’ve used like Discord.js.

The whole thing is a major work in progress, but I’m hoping to at least get it to a level of stability and testing that I can use it in production for one of my own discord bots.

↑ Top


Teaching Myself Rust, Part 1
Baduk & Bevy
Next →