Work In Progress
This documentation is in beta. It's missing lots of content, search is broken, and many links go nowhere. These problems will be fixed before release, but there's plenty of work left!
Skip to main content

Chat Commands

Warnings and Notes

Before getting started, please make sure you read the below notices!

Privileged intents required!

Chat commands require the "message content" privileged intent. While chat commands were traditionally how users interacted with bots on Discord, this is no longer what Discord recommends or encourages for your bots.

If your bot is on 75 or more guilds (or you plan to grow it to that point), you should consider using Application Commands instead of chat commands as much as possible.

Your bot will need to go through a verification process (which starts at 75 guilds) before it can join over 100 guilds. Discord will not verify bots that are using the "message content" privileged intent without a good reason.

The only situations that we advise you to use chat commands for are those where the other types of commands provide an objectively worse user experience. This largely only applies to commands that need to take a large amount of text as input (if modals do not suffice).

Additionally, it is worth noting that users will expect your bots to support Application Commands as a default mode of interaction.

Maintenance Status

Due to the situation explained in the above warning, Kord Extensions' users and developers don't regularly use or test chat commands. As a result, there may be small bugs or formatting problems that we haven't noticed, or had the time and energy to fix.

If you run into any problems with the chat commands framework or its help extension, please let us know or submit a Pull Request to address the issue.


Introduction

Chat commands are a fairly simple concept. When a user sends a message starting with a command prefix (or bot mention), the command name and arguments, Kord Extensions can process it accordingly.

Call the builder functions within your setup function when you're registering commands before the bot starts up. You can also register commands later in the bot's lifecycle by calling the same functions.

Chat commands support command arguments, as explained on the arguments page. However, unlike the other command types, they do not support Modals.

As Discord recommends against using chat commands, you must enable them before your bot will respond to them. For more information, see the configuration documentation.

chatCommand(::MyArguments) {
name = Translations.Commands.Ping.name
description = Translations.Commands.Ping.description
aliasKey = Translations.Commands.Ping.aliases

check { hasPermission(Permission.MentionEveryone) }

action {
message.respond(
"Hey, ${arguments.user.mention}! Get pinged!"
)
}
}

Argument Parsing

Like all command types, chat commands parse their arguments in the order you defined them, allowing converters that take lambdas to reference previous arguments. This follows a specific string-parsing strategy:

  1. Parse keyword arguments and remove them from the arguments string.
  2. Scan the string from left to right, with converters pulling tokens from it as needed.
  3. Ensure all required converters fill, and no extra arguments remain.

Chat commands support keyword arguments in the following forms:

  • Command-line style: --name value
  • Properties style: name=value

They also support the following extras:

  • Double-quoted values, to allow passing arguments with spaces: "like this"
  • Escaped double quotes, to allow passing them within a quoted argument: "like \" this"

The parser code is available here. We're sure it has some shortcomings, so feel free to let us know if you think you can improve it.

Extension API

The following APIs are available on the Extension type, which you can use to define your chat commands and modify their behaviour.

chatCommand(...) { ... }Receiver: ChatCommandFunction Returns: ChatGroup

Use this builder to register a standalone chat command, as explained in the sections below.

Function Arguments
argumentsType: () -> T

Optional callable returning an instance of your Arguments subtype, as explained on the arguments page. You'll usually want to pass a constructor here.

Type Parameters
TType: Arguments

Optional generic type referring to your Arguments subtype, as explained on the arguments page.

chatGroupCommand(...) { ... }Receiver: ChatGroupCommandFunction Returns: ChatGroupCommand

Use this builder to register a grouped chat command, as explained in the sections below.

Function Arguments
argumentsType: () -> T

Optional callable returning an instance of your Arguments subtype, as explained on the arguments page. You'll usually want to pass a constructor here.

Type Parameters
TType: Arguments

Optional generic type referring to your Arguments subtype, as explained on the arguments page.



chatCommandCheck { ... }Receiver: CheckContext<MessageCreateEvent>

Register a check that must pass for any of the chat commands in this extension to run.

Standalone Commands

Standalone commands are the simplest type of chat command, defined using the chatCommand builder function. This builder is a receiver function against the ChatCommand type, providing APIs you can use to configure your command and its metadata.

At minimum, a standalone command must have a name and action defined.

The following APIs are available for use when writing a chat command, along with those provided by the base Command type.

Builders

action { ... }Receiver: ChatCommandContext

Register your command's action block, defining what it will do when executed.

See the context API section for more information on what you can do here.

check { ... }Receiver: CheckContext<MessageCreateEvent>

Register a [check] which mass pass for the command to execute when invoked.

Functions

We consider all plain functions defined in the chat command API internal, but you may find some of them useful for a small handful of advanced use-cases.

Show/Hide Internal APIs
open call(...)

Attempt to execute this command based on the provided arguments. This function runs the defined checks by default, which will prevent command execution if they fail.

This function is normally called by the ChatCommandRegistry when someone invokes a chat command on Discord.

Arguments
eventType: MessageCreateEvent

Message creation event triggering this command execution.

commandNameType: String

Name used to invoke this command. This is specifically the text that was sent to invoke this command by a Discord user, and not a translation key.

parserType: StringParser

The parser used to parse this command's arguments.

argStringType: String

String containing this command invocation's unparsed arguments.

skipChecksType: BooleanDefault: false

Whether to skip running the command's registered checks.

cacheType: MutableMap<String, Any>Default: mutableMapOf()

Map representing a data cache shared with the command's registered checks, and made available in the command context.

open getSignature(...)Returns:String

Retrieve the command's translated signature, which explains how users should structure the arguments this command takes. Usually used by the help command in your bot's help extension.

Command signatures are usually generated by the chat command parser, but you can provide one manually when you define your command.

This function's output is cached.

Arguments
localeType: Locale

Locale used to translate the command name for generated signatures, or the entire signature if provided.

open getTranslatedName(...)Returns:String

Retrieve the command's translated name.

This function's output is cached.

Arguments
localeType: Locale

Locale used to translate the command name.

open getTranslatedAliases(...)Returns:Set<String>

Get a set of the command's translated aliases.

This function's output is cached.

Arguments
localeType: Locale

Locale used to translate the command's aliases.

open runChecks(...)Returns:Boolean

Run this command's registered checks, returning true if they all pass, or false if any fail.

Arguments
eventType: MessageCreateEvent

Message creation event triggering this command execution.

sendMessageType: BooleanDefault: true

Whether to send any failure messages generated by the checks in response to the command invocation.

cacheType: MutableMap<String, Any>Default: mutableMapOf()

Map representing a data cache passed to each check, and made available in the command context.

open validate(...)

Validation function that throws an InvalidCommandException if there are any problems.

Properties

open var aliasKeyType: Key?Default: null

Translation key that resolves to a comma-separated list of command aliases.

If a locale shouldn't contain any aliases, set the corresponding translation value to the universal empty translation string, represented by three "empty set" characters (∅∅∅).

open var allowKeywordArgumentsType: BooleanDefault: true

Whether to allow users to specify keyword-style arguments, as specified above.

open var descriptionType: KeyDefault: CoreTranslations.Commands.defaultDescription

This command's description, used by the help command in your help extension, and shown in argument parsing errors.

Defaults to No description provided. We strongly recommend providing your own description!

open var enabledType: BooleanDefault: true

Whether this command can be executed. Set this to false to disable this command, which will hide it from the help command and prevent users from executing it.

You can set this property at runtime, by storing the return value of your chatCommand(...) { } builder invocation.

open var hiddenType: BooleanDefault: false

Whether to hide this command from the help command's output.

Users can still run hidden commands, so remember to lock them down with permissions checks as appropriate.

open var localeFallbackType: BooleanDefault: false

Whether to fall back to your bot's configured default locale when resolving command names for execution.

Enabling this allows users to execute your command by providing its name or aliases in your bot's default locale, as well as those provided in the locale returned by your bot's configured locale resolvers.

open var signatureType: Key?Default: null

Translation key that resolves to a custom signature representing how users should supply command arguments.

By default, the ChatCommandParser will generate a signature suitable for most commands:

  • Argument names will be translated into the user's locale as appropriate.
  • Required arguments will be wrapped with <> - e.g. <name>
  • Optional arguments will be wrapped with [] - e.g. [name]
  • Converters set to show argument types will:
    • Append the type to the name with a colon - e.g. [name: type]
    • Append any default value with an equals sign - e.g. [name: type=default]
  • List-based converters will append an ellipsis to show that multiple arguments are accepted - for example:
    • [name...]
    • [name: type=default...]

Provide this property to override the generated signature and provide your own.

val registryType: ChatCommandRegistry

Easy access to the current ChatCommandRegistry object.

Show/Hide Internal APIs
open val aliasTranslationCacheType: MutableMap<Locale, Set<String>>Default: mutableMapOf()

Map representing the alias translation cache, used to store translated aliases so they don't have to be re-translated all the time.

open val argumentsType: (() -> T)?Default: null

Optional callback returning the Arguments subtype this command uses to parse and store arguments.

open var bodyType: ChatCommandContext.() -> Unit

Your command's body, set using the action { } builder.

open val checkListType: MutableList<ChatCommandCheck>Default: mutableListOf()

List of this command's registered checks.

open var signatureCacheType: MutableMap<Locale, String>Default: mutableMapOf()

Map representing the signature translation cache, used to store translated signatures so they don't have to be re-translated all the time.

Grouped Commands

Grouped commands work just like standalone commands, but they let you nest other commands within them, creating a tree of subcommands as deep as you need. They're defined using the chatGroupCommand builder, a receiver function against the ChatGroupCommand type, which itself extends the ChatCommand type.

At minimum, a grouped command must have a name defined.

Grouped commands expose the same API provided by standalone commands, aside from a few additions and changes.

Behaviour

When compared to standalone commands, grouped commands provide a slightly different execution flow.

When executed, these commands check the first argument provided against their registered subcommands, passing the rest of the arguments to the matching subcommand if one exists. If no matching subcommand exists, the grouped command will execute its own action block using the full set of arguments.

By default, grouped commands provide their own action block, which simply calls the sendHelp() function provided by the context API. However, you can override this behaviour by providing your own action block if needed.

Subcommands always run the [checks] defined on their parent commands along with their own, traversing the entire tree. They all need to pass for the command to execute.

Builders

chatCommand(...) { ... }Receiver: ChatCommandFunction Returns: ChatGroup

Use this builder to register a standalone chat subcommand.

This builder functions identically to the builder provided by the extension API.

chatGroupCommand(...) { ... }Receiver: ChatGroupCommandFunction Returns: ChatGroupCommand

Use this builder to register a nested grouped chat subcommand.

This builder functions identically to the builder provided by the extension API.

Functions

Show/Hide Internal APIs
open getCommand(...)Returns:ChatCommand?

Retrieve the subcommand matching the given name, or null if no matching, enabled command exists.

Arguments
nameType: String?

Command name to match on. Providing null makes the function always return null.

eventType: MessageCreateEvent

Message creation event triggering this command execution.

open getFullTranslatedName(...)Returns:String

Retrieve the command's translated name. If there are any parent commands, their names will be prepended along with a space.

Arguments
localeType: Locale

Locale used to translate the commands' names.

Properties

Show/Hide Internal APIs
open val commandsType: MutableList<ChatCommand>Default: mutableListOf()

List containing this command's subcommands.

open val parentType: ChatGroupCommand?Default: null

This command's parent command, if it has one.

Context API

The action { } builder is a receiver against the ChatCommandContext type. This type provides a set of APIs, along with those provided by the base CommandContext type, which allow your bot to respond to command invocations.

Show/Hide Class Definition
open class ChatCommandContext : CommandContext

Context object containing the APIs you need to respond to a chat command.

Type Parameters
TType: Arguments

Generic representing the correct Arguments subtype.

Constructor Arguments
val chatCommandType: ChatCommand<out T>

Reference to the object representing the current command.

eventObjType: MessageCreateEvent

Reference to the event that triggered this command invocation.

commandNameType: Key

Translation key representing the name used to invoke this command.

This key contains the name as provided on Discord, wrapped into a Key object along with the event's locale. Use commandName.key to get the name used.

open val parserType: StringParser

String parser used to parse the arguments for this command invocation.

val argStringType: String

The raw, unparsed command arguments as sent by the user on Discord.

cacheType: MutableMap<String, Any>

Data cache map shared with this command's checks.

Builders

paginator { ... }Receiver: PaginatorBuilderFunction Returns: MessageButtonPaginator

Convenience builder for creating a paginator.

For more information, see the paginator documentation (TODO).

Function Arguments
defaultGroupType: KeyDefault: EMPTY_KEY

The default paginator group to use for pages.

pingInReplyType: BooleanDefault: true

Whether to ping the author of the targetMessage when sending the paginator, if you provide targetMessage.

targetChannelType: MessageChannelBehavior?Default: null

Channel to send the paginator to.

If both targetChannel and targetMessage are omitted, this will default to the channel this command was invoked in.

targetMessageType: Message?Default: null

Message to respond to when sending the paginator.

This will override targetChannel with the message's channel if you provide both.

Functions

suspend respondTranslated(...)

Generate and send the help embed for this command, generated using your bot's help extension.

Returns true if your bot has a proper help extension and the message was sent, false otherwise.

suspend Message.sendHelp(...)Returns:Boolean

Convenience function for quickly replying to a message using a translation key.

Arguments
keyType: Key

Translation key representing the message content.

placeholdersTypes:Array<Any?>Map<String, Any?>Default: Empty array/map

An array or map containing placeholder values to fill.

useReplyType: BooleanDefault: true

Whether to explicitly reply to the message.

pingInReplyType: BooleanDefault: true

Whether to ping the message author:

  • When useReply is true, pings the author using the Discord reply feature.
  • When useReply is false, pings the author by adding a mention to the start of the message content.
Show/Hide Internal APIs
open suspend getMessage(...)Returns:Message

Retrieve the message from the event property. Used internally to populate the message property.

populateArgs(...)

Internal function used to set the arguments property.

Arguments
argsType: T: Arguments

Arguments object to store.

Properties

open var argumentsType: T: Arguments

Object containing this command invocation's parsed arguments, matching the type of the subtype you provided to your command definition, or an empty Arguments object if you didn't provide one.

val argStringType: String

The raw, unparsed command arguments as sent by the user on Discord.

val chatCommandType: ChatCommand<out T>

Reference to the object representing the current command.

val eventType: MessageCreateEvent

Reference to the event that triggered this command invocation.



open var channelType: MessageChannelBehavior

The channel this command invocation happened in.

open var guildType: GuildBehavior?

The guild this command invocation happened in, or null if it happened in a DM.

open var memberType: MemberBehavior?

The guild member that caused this command invocation, or null if:

  • This command invocation happened in a DM.
  • This command invocation was caused by a webhook.
open var messageType: Message

The Discord message that caused this command invocation.

open var userType: UserBehavior?

The Discord user that caused this command invocation, or null if it was a webhook.

Show/Hide Internal APIs
open val parserType: StringParser

String parser used to parse the arguments for this command invocation.