Adding a command
createCommands returns a handle for one owner. Call register on it with your commands, keyed by name. The commands appear in the / picker and in the list that opens when you type /.
name is a string in execute because the option is required. Returning a string sends it to the channel as a normal message from you.
You don’t need a stop for commands. Unbound removes a plugin’s commands when the plugin stops, fails to start, is disabled, is unloaded, or is reloaded with ubd push. Command ids come from the owner id and the command’s path, so a reload registers the same ids and Discord’s recently used list keeps them.
The owner id
string
required
The id that owns the commands, the same way
patcher.createPatcher takes a caller. In a plugin,
pass the plugin’s id from manifest.json. Unbound removes commands by this id when the plugin
ends. In an Unbound built-in, pass 'unbound' and call unregisterAll() in stop.{ name: string; icon?: number | string }
Gives the owner its own section in the picker.
icon is an asset id from assets.Icons, or a
data: or https: uri. Without section, commands go in the shared Unbound section.Options
options is a record keyed by option name. Make each value with a builder on commands.option.
Every builder takes
description and required. A required option has the type T. An optional option has the type T | undefined, so default it while you destructure: execute({ style = 'wave' }). Unbound lists required options before optional ones, because Discord requires that order.
Mentionable and attachment options are not supported.
Choices
option.choice takes values, or { label, value } pairs when the picker should show a label other than the value. It accepts 1 to 25 choices with unique labels. The picker shows at most 10 matches at a time.
style is 'wave' | 'bow' | 'high-five' | undefined in execute. Numbers make an integer option, or a number option if one of them has a fraction.
Autocomplete
Give astring, integer or number option an autocomplete function. It receives what the user typed and a context with channel, guild, and values. values holds the raw values of the other options filled in so far. Return values, or { label, value } pairs, synchronously or from a promise. The picker shows the first 25.
autocomplete throws, the picker shows no suggestions and Unbound logs the error.
Subcommands
A command withsubcommands instead of options and execute is a group. subcommands is a record with the same shape. Discord allows two levels below the root: /root group command.
Replies
Whatexecute returns decides what happens. execute can be async.
The second argument of
execute is the context: channel, and guild outside of DMs.
Errors
Ifexecute throws or rejects, you see an ephemeral message such as /tag add failed: <error message>, and Unbound logs the error with the owner id. If Discord can’t find the user, channel, or role an option names, you see the same kind of message and execute does not run.
register throws a CommandDefinitionError and registers nothing from that call when the commands break one of Discord’s rules:
- Names are 1 to 32 lowercase letters, digits,
-, or_. - Descriptions are 1 to 100 characters.
- A command has at most 25 options, and a group has 1 to 25 subcommands.
- A command has either
executeorsubcommands. - Another owner already registered the same root name.
Removing commands
register returns a function that removes the commands from that call. Use it for commands that come and go while your plugin runs. You can call it more than once, and after the plugin stopped. Registering a root name that the same owner already registered replaces the whole command, subcommands included.
unregisterAll() removes every command of the owner.
Built-in commands
Unbound registers these commands in the Unbound section. You can’t register a command with one of these names.
The
/eval result is cut to fit Discord’s 2,000-character message limit. If the code throws, you see the error in an ephemeral message.