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!

Simple Config, Powerful Commands!

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

Screenshot 2025-07-07 202824

How it Works

  1. On startup the config file is read and command definitions are parsed

  2. The bot script generates Python functions and dynamically creates/registers the discord.app_commands.

  3. When a user invokes a custom command, their input can be optionally pre-processed via steps (e.g. saving files, parsing text).

  4. 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.)


Context Injection

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 steps block as context.

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


Slash Commands

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.

Configuration

Note: There are a few subtle differences here compared to the Context Commands Configuration block.

Screenshot 2025-07-07 211803

Top-Level Slash Command Fields

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.)

Options – Input Parameters

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

Context Commands

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.

Configuration

Note: There are a few subtle differences here compared to the Slash Commands Configuration block.

Screenshot 2025-11-12 205733

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.)

Target Types for Context Commands

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

Accessing Message and User objects

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)
}
⚠️ **GitHub.com Fallback** ⚠️