📜 Commands
Slash commands have changed the game in Discord, making it a breeze for users to interact with bots (or as we like to call them, Robos). And with Robo.js, weaving your own slash commands is as easy as pie. Let's unravel this together!
Crafting Simple Commands 🛠️
Start off with a simple command. Create a file in the commands
directory. The file name? That's your command!
For instance, to create a /ping
command, your file structure would look like this:
src/
└── commands/
└── ping.js
And inside your ping
command file? Straightforward:
- Javascript
- Typescript
export default () => {
return 'Pong!'
}
import type { CommandResult } from 'robo.js'
export default (): CommandResult => {
return 'Pong!'
}
To use the interaction object directly:
- Javascript
- Typescript
export default (interaction) => {
interaction.reply('Pong!')
}
import type { CommandInteraction } from 'discord.js'
export default (interaction: CommandInteraction) => {
interaction.reply('Pong!')
}
In this case, Sage steps back, letting you handle the interaction directly.
Subcommands and Subcommand Groups 📚
Creating subcommands with Robo.js is as simple as creating new files in a folder. The folder name becomes the parent command, and the file names become the subcommands. But remember, you can't have a parent command file and subcommand files together.
src/
└── commands/
└── ban/
└── user.js
And subcommand groups? It's the same concept, but one level deeper. Again, parent commands or subcommands can't live alongside subcommand groups.
src/
└── commands/
└── settings/
└── update/
└── something.js
Customizing Commands 🖋️
Give your commands some context with descriptions. You can do this by exporting a config
object from your command file.
export const config = {
description: 'Responds with Pong!'
}
For TypeScript users, you can add typings for both the config
object and the command result.
import type { CommandConfig, CommandResult } from 'robo.js'
export const config: CommandConfig = {
description: 'Responds with Pong!'
}
export default (): CommandResult => {
return 'Pong!'
}
The `` object also lets you customize stuff like locale translations, Sage options, and command timeouts. To understand more about the available uration options, check out the configuration section.
Command Options 🎚️
Robo.js allows you to further customize your commands with options. You can define these options in your config
object and then access their values in your command function.
- Javascript
- Typescript
export const config = {
description: 'Responds with Pong!',
options: [
{
name: 'loud',
description: 'Respond loudly?',
type: 'boolean'
}
]
}
export default (interaction) => {
const loud = interaction.options.get('loud')?.value as boolean
return loud ? 'PONG!!!' : 'Pong!'
}
import type { CommandConfig, CommandResult } from 'robo.js'
import type { CommandInteraction } from 'discord.js'
export const config: CommandConfig = {
description: 'Responds with Pong!',
options: [
{
name: 'loud',
description: 'Respond loudly?',
type: 'boolean'
}
]
}
export default (interaction: CommandInteraction): CommandResult => {
const loud = interaction.options.get('loud')?.value as boolean
return loud ? 'PONG!!!' : 'Pong!'
}
You can also use a second parameter next to the interaction object to access the options directly. These are automatically parsed and passed to your command function, with full type support too!
- Javascript
- Typescript
export const config = {
description: 'Responds with Pong!',
options: [
{
name: 'loud',
description: 'Respond loudly?',
type: 'boolean'
}
]
}
export default (interaction, options) => {
return options.loud ? 'PONG!!!' : 'Pong!'
}
import { createCommandConfig } from 'robo.js'
import type { CommandOptions, CommandResult } from 'robo.js'
import type { CommandInteraction } from 'discord.js'
export const config = createCommandConfig({
description: 'Responds with Pong!',
options: [
{
name: 'loud',
description: 'Respond loudly?',
type: 'boolean'
}
]
} as const)
export default (interaction: CommandInteraction, options: CommandOptions<typeof config>): CommandResult => {
return options.loud ? 'PONG!!!' : 'Pong!'
}
Heads up!
createCommandConfig
andas const
are important for TypeScript!createCommandConfig
creates a command configuration object with the correct type, which tells your editor which options are available for your command for better autocompletion and type checking.
Want to explore more options? Check the configuration section.
DM Permission
Control whether your command is accessible in direct messages with dmPermission
. Setting this to true
allows users to use the command in DMs with the bot, while false
restricts it.
export const config = {
// ... other configuration options
dmPermission: false // Restricts this command in DMs
}
Default Member Permissions
Use defaultMemberPermissions
to define server-based permissions for your command. This field accepts PermissionFlagsBits
from Discord.js, allowing you to specify which roles or permissions are needed to access the command in a server context.
import { PermissionFlagsBits } from 'discord.js'
export const config = {
// ... other configuration options
defaultMemberPermissions: PermissionFlagsBits.KickMembers // Only users who can kick members can use this command
}
Remember, server admins can adjust these default permissions for their own servers. Also, due to a Discord quirk, default permissions might not apply as expected to subcommands.
Autocomplete 🧠
Autocomplete can take your commands to the next level by providing suggestions as users type. You can implement autocomplete by exporting an autocomplete
function in your command file.
- Javascript
- Typescript
export const config = {
description: 'Chooses a color',
options: [
{
name: 'color',
description: 'Your favorite color',
type: 'string',
autocomplete: true
}
]
}
const colors = ['red', 'green', 'blue', 'yellow', 'black', 'white', 'pink', 'purple', 'brown']
export default (interaction) => {
return `You chose ${interaction.options.get('color')?.value}`
}
export const autocomplete = (interaction) => {
const colorQuery = interaction.options.get('color')?.value
const filtered = colors.filter((color) => color.startsWith(colorQuery))
return filtered.map((colors) => ({ name: colors, value: colors }))
}
import type { CommandConfig, CommandResult } from 'robo.js'
import type { CommandInteraction, AutocompleteInteraction } from 'discord.js'
export const config: CommandConfig = {
description: 'Chooses a color',
options: [
{
name: 'color',
description: 'Your favorite color',
type: 'string',
autocomplete: true
}
]
}
const colors: Array<string> = ['red', 'green', 'blue', 'yellow', 'black', 'white', 'pink', 'purple', 'brown']
export default (interaction: CommandInteraction): CommandResult => {
return `You chose ${interaction.options.get('color')?.value}`
}
export const autocomplete = (interaction: AutocompleteInteraction) => {
const colorQuery = interaction.options.get('color')?.value as string
const filtered = colors.filter((color) => color.startsWith(colorQuery))
return filtered.map((colors) => ({ name: colors, value: colors }))
};
In this example, the autocomplete
function returns an array of colors that start with the user's input, providing a dynamic and responsive user experience.
Note: the type of the Interaction is: AutocompleteInteraction
Command Registration 📝
The cherry on top? You don't need to manually register your commands. Robo.js handles it for you when you run robo dev
or robo build
, automatically! However, if things go sideways for some reason, you can use the --force
flag to force registration.
npx robo build --force
This will also clean up any commands that are no longer in your commands
directory. Pretty neat, right?
User Installs
Robo.js now supports commands for user-installed apps! You will need to set experimental userInstall
to true
in your config file to enable this feature.
export default {
// ... other config options
experimental: {
userInstall: true
}
}
With this enabled, users can install your app and use its commands anywhere!
Make sure you update your install settings in the Discord Developer Portal to allow user installs.