Custom Commands - altoiddealer/ad_discordbot GitHub Wiki
NEW - Both Slash Commands (/my_command) AND Context Commands (right click a discord message > my_command) types are now supported!
The Custom Commands allows you to create your own slash and context commands via a simple config file, without having to write complex code.
-
Designed with the APIs System in mind
-
Discord input types (string, int, float, attachment, required, description, etc.)
-
User input for each Option can be pre-processed via StepExecutor
-
After all input is gathered, a main task can be executed via StepExecutor
-
"{variable_syntax}"automatically resolves into settings fields and payload fields - see Payload Injection System
-
On startup the config file is read and command definitions are parsed
-
The bot script generates Python functions and dynamically creates/registers the
discord.app_commands. -
When a user invokes a custom command, their input can be optionally pre-processed via steps (e.g. saving files, parsing text).
-
Finally, the main steps block is run to perform the core function of the command (e.g. running a generation pipeline, sending a file, etc.)
Each option defined in a custom command becomes a key in a context dictionary, where its value is the user-provided input (during/after optional preprocessing via steps).
-
Each Option being pre-processed has access to the current context dictionary (the value of Option 1 can be accessed in later Options pre-processing)
-
The context dictionary is automatically passed to the main
stepsblock ascontext.
For example, if your options are:
- name: prompt
type: string
...
- name: ref_image
type: attachment
...
... then inside your main steps, you can access them such as:
input_data: "{prompt}" β resolves to the user's entered prompt
file: "{ref_image}" β resolves to the discord attachment (or any processed results, such as file_name returned from a "save" step)
These context key values will also automatically resolve into payloads which utilize the Payload Injection System
These commands are invoked by typing /command_name in the text box in Discord's UI.
You can define many options to include in these commands, supporting innumerable use cases, and really it's just awesome to say the least.
Note: There are a few subtle differences here compared to the Context Commands Configuration block.
The top-level fields for your slash_commands: list:
| Field | Type | Required | Description |
|---|---|---|---|
| command_name | string | β Yes | The name of the slash command (without the leading /) |
| description | string | β No | A brief description shown in Discordβs UI |
| options | list | β No | A list of input options (parameters) the user will fill out |
| steps | list | β No | Main execution steps to run after all inputs are collected |
| allow_dm | bool | β No | Allows the command to be used via DM (default: false) |
| queue_to | string | β No | Queue name to send the task to (gen_queue, normal_queue, etc.) |
Each custom slash command can define input options, defined inside the options: list.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | β Yes | Parameter name. This will also serve as the "key" for the key value pair which will be retained into "context" dict. |
| description | string | β No | Description shown to the user in Discord |
| type | string | β Yes | Discord input type (Valid: string, int, float, bool, attachment) Also valid but may not have practical use (yet): user, channel, role
|
| required | bool | β No | Whether the user must provide this input |
| choices | list/dict | β No | Optional list of fixed choices (Can be a simple list of values, or a dictionary where key's serve as display names, or a list of {"name": value} pairs) |
| default | Any | β No | Optional default value for options where required: false and user does not provide input.) |
| steps | list | β No | Optional preprocessing steps to perform on the user's input before main steps execution (See StepExecutor |
These commands are invoked by right-clicking a Message or User in Discord's UI.
The discord.Message or discord.User object is passed into the Steps processing. Any components (attachments, text, ID's, etc) can be accessed and used.
Note: There are a few subtle differences here compared to the Slash Commands Configuration block.
Here are all the fields available to define commands in the context_commands: list:
| Field | Type | Required | Description |
|---|---|---|---|
| command_name | string | β Yes | The name of the context command |
| description | string | β No | A brief description shown in Discordβs UI |
| target_type | string | β No | Valid options are message (default) or user. See important details in section below this chart
|
| steps | list | β No | Main execution steps to run after all inputs are collected |
| allow_dm | bool | β No | Allows the command to be used via DM (default: false) |
| queue_to | string | β No | Queue name to send the task to (gen_queue, normal_queue, etc.) |
You can create Message and User types.
-
Message type is invoked by right-clicking a Message. This is very useful since Text, Attachments, and all other elements of the Message will be passed into the processing Steps execution.
-
User type is invoked by clicking on a User in the Users list. This option is available but has not been thoroughly tested.
-
Discord has a strict limit for bots, which is merely 5 of each type.
-
You may have to disable some of the bot's native commands in config.yaml
When the Context Command is invoked, it will proceed to the defined steps which are handled by StepExecutor
StepExecutor will initialize with the Message / User object as the "input data" - meaning you can immediately fetch value(s) using extract_key, extract_values, etc.
StepExecutor will also initialize with a reference to the Message / User object in it's Context Dictionary - so you can easily access values in later Steps via something like {message.content} (this will resolve into the raw text in the Message), or {user.id}, etc.
Message type commands include extra conveniences:
-
A "cleaned" version of the main text (@mentions resolved to actual names instead of IDs, etc) from the Message will be included in the Context dictionary, and can be accessed such as
{text} -
All attachments will be included in the Context dictionary, under keys such as
attachment_0(the first attachment),attachment_1, and so on.
Each of these attachment dictionaries will have identical structure as what the prompt_user step collects. This makes it easy to use attachments for a variety of use cases without having to perform extra preprocessing steps - its already handled!
attachment_0 =
{
"file_dict": { # "file_dict" is a value ready to for a "files" payload, to upload to an API
"image": { # 'image' is example value - will be dynamic (string)
"file": file_obj, # io.BytesIO object
"filename": filename, # filename without extension (string)
"content_type": mime_type} # mime type ex: 'image/png' (string)
},
"bytes": <bytes>, # raw bytes
"file_format": "png" # file format
"filename": "my_image" # filename without extension (string)
}