Skip to main content

Crate composure

Crate composure 

Source
Expand description

Composure is a framework for Discord bots that only answer Interactions over HTTP: no gateway connection, so a bot runs on the edge (Cloudflare Workers, compiled to WASM) or on any hosted server (tokio), and scales to zero between requests.

use composure::{app, command};

/// Repeat some text
#[command]
fn echo(
    #[option("What to say", max_len = 200)] text: &str,
    #[option("How many times", min = 1, max = 5)] times: Option<u8>,
) -> String {
    text.repeat(times.unwrap_or(1).into())
}

/// Everything the bot serves
#[app(handlers(echo))]
pub struct Bot;

Each Command is written once, as a function: its parameters become the Command’s Options, its doc comment the description, its return value the answer. Bot is then handed to an Adapter to serve Interactions, and to composure_sync at deploy time to register the Commands with Discord.

§Where to start

The guide walks through everything a bot does, chapter by chapter:

Chapter
Getting startedCrates, features, a first bot, serving it, syncing it
Commands#[command], Options, Choices, Groups, context menus, autocomplete, Scopes
ResponsesWhat a handler can return; ephemeral messages, embeds, files, errors
Components and modalsButtons, selects and forms with #[component], #[modal], #[derive(Modal)]
Viewsrsx! markup and #[view]: every tag and attribute
REST and deferringctx.bot(), follow-ups, Deferred Responses, Background Work
Webhook EventsApp installs, entitlements, lobby messages
PlatformsAdapters, State, platform-specific Commands, logging
TestingRunning handlers without Discord

§Crates

Crate
composure (this one)Types, request validation, the handler runtime, the REST client, and (with macros) the attribute macros
composure_adapter_cloudflareServes a bot on Cloudflare Workers
composure_adapter_tokioServes a bot from a hosted server on tokio
composure_syncRegisters an App’s Commands with Discord at deploy time
composure_macrosThe macros; use them through composure’s macros feature
composure_commandsA builder for Command Definitions, for bots not using #[command]

§Modules

  • command: the handler runtime: Ctx, responses (Ephemeral, Update, …), View, errors, and the traits the macros implement
  • types: Discord’s objects (Interactions, messages, embeds, components, users, …), shared by Interactions, responses and REST
  • definition: Command Definitions, as Discord stores them
  • rest: the REST client over an Adapter’s Transport
  • adapter: the request pipeline every Adapter shares (validate, parse, dispatch)
  • auth: Ed25519 request signature validation
  • credentials: Credentials, what identifies the application, however the bot loads them
  • testing (testing feature): Interaction builders, a stand-in Platform and Transport, signing keys, for testing a bot without Discord

§Feature flags

No feature is on by default: the core stays small for WASM bundles.

Feature
macros#[app], #[command], #[group], #[component], #[modal], #[autocomplete], #[view], rsx!, #[derive(Choice)], #[derive(Modal)]
restThe REST client (rest) with the Interaction Endpoints, Platform, ctx.defer(..), and the adapter pipeline
rest-commands, rest-messages, rest-users, rest-channels, rest-guilds, rest-members, rest-rolesOne group of Endpoints each on BotClient
rest-bans, rest-threads, rest-invites, rest-emojis, rest-stickers, rest-scheduled-events, rest-automod, rest-audit-log, rest-webhooks, rest-monetization, rest-polls, rest-soundboard, rest-application, rest-role-connections, rest-onboarding, rest-stage-instances, rest-lobbiesThe rest of Discord’s Endpoints, one group each
tier1rest and the Endpoints most bots need (commands, messages, users, channels, guilds, members, roles)
fullEvery Endpoint
tracingSpans and events through tracing; see Platforms
web-cryptoValidate signatures with the host’s Web Crypto on wasm32-unknown-unknown instead of compiling ed25519-dalek in
reqwestA blocking ReqwestTransport for deploy-time tools (not for WASM)
testingrest and composure::testing, for a bot’s tests: Interaction builders, TestPlatform, MockTransport, TestKey; see Testing

Re-exports§

pub use command::Ctx;
pub use credentials::Credentials;
pub use credentials::CredentialsError;

Modules§

adapterrest
What every Adapter does with a request, whatever the platform: verify the signature, parse, dispatch to the InteractionHandler (or hand a Webhook Event to the EventHandler as Background Work), and send responses with files through the callback endpoint. Adapters map the outcomes to their platform’s HTTP response, so every Adapter answers alike.
auth
Verifying that requests come from Discord: every Interaction and Webhook Event is signed with Ed25519 over timestamp || body, checked against the application’s public key. Adapters do this for you (adapter::verify, with the rest feature); use PublicKey directly when writing one.
command
Commands defined once with #[command], from which both their handler and their Command Definition derive, collected with the handlers for components, modals and Views into an App with #[app].
credentials
What identifies and authorizes the Discord application (ADR 0014). Composure never loads configuration itself: an Adapter (or the bot) builds Credentials from wherever it keeps them, by the conventional names with Credentials::from_lookup, or through serde with any loader (config, figment, envy, …).
definition
Application command definitions: what Discord stores for each command. Used when syncing commands, not when handling interactions.
restrest
Async Discord REST client over an Adapter-provided Transport (ADR 0004, 0005).
testingtesting
Testing bots without Discord or a platform (testing feature): build Interactions, run them through an App with a stand-in Platform, and check the response and the REST requests it made.
types
Discord’s data model, shared by Interactions, Responses and REST. Organized by resource; everything is re-exported flat as composure::types::X.

Macros§

rsxmacros
Markup for message and modal layouts. Every tag and attribute is listed in Views. Markup for a message or modal layout, as JSX: built-in tags are Discord’s components (<Container>, <Section>, <Text>, <Thumbnail>, <Gallery>/<Item>, <File>, <Separator>, <Row>, <Button>, <StringSelect>/<Option>, <UserSelect>, …; in a <Modal>: <Label>, <TextInput>, <RadioGroup>, <CheckboxGroup>, <Checkbox>, <FileUpload>), PascalCase tags are #[view]s. Evaluates to a View, or a ModalView for a <Modal> root.

Traits§

Mentionable
Something Discord renders as a mention in message content: <@id> for users, <#id> for channels, <@&id> for roles.

Attribute Macros§

appmacros
Collects Routes into an App, the handler an Adapter serves. See Getting started and Platforms. Makes a unit struct an App: the Interaction Handler routing to the Commands, Groups, Component and Modal Handlers, Views and other Apps listed in handlers(..), in any mix and order.
autocompletemacros
Suggests values for an Option while the user types. See Commands. Defines an Autocomplete Handler from a function taking an optional leading ctx: Ctx and what the user has typed so far as input: &str. Attach it to a string, integer, or number Option with #[option("...", autocomplete = name)].
commandmacros
Defines a Command from a function. See Commands. Defines a Command from a function. Parameters after an optional leading ctx: Ctx become Options; the doc comment becomes the description.
componentmacros
Answers a component by custom_id prefix. See Components and modals. Defines a Component Handler from a function: it answers components whose custom_id starts with the prefix. Parameters after an optional leading ctx: ComponentCtx are state carried in the custom_id (owned, serde-serializable), built with the generated name::custom_id(..).
groupmacros
Groups Commands as subcommands. See Commands. Makes a unit struct a Group that routes to its subcommands. Groups can contain Groups one level deep.
modalmacros
Answers a modal submit by custom_id prefix. See Components and modals. Defines a Modal Handler from a function: it answers submits of modals whose custom_id starts with the prefix. After an optional leading ctx: ModalCtx comes the form (a #[derive(Modal)] type), then state carried in the custom_id. name::show(..) is the modal response that opens the form.
viewmacros
A layout rendered from Props, with inline handlers. See Views. Defines a View: a layout rendered from its Props (the parameters, owned values), whose rsx!s may hold inline handlers.

Derive Macros§

Choicemacros
An enum of fixed Choices, for Options, selects and radio groups. See Commands. Makes a fieldless enum (1-25 variants) usable as an Option restricted to its variants, and as the options of selects, radio groups and checkbox groups.
Modalmacros
A form shown as a modal. See Components and modals. A form shown as a modal: each named field is one input inside a Label.