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 started | Crates, features, a first bot, serving it, syncing it |
| Commands | #[command], Options, Choices, Groups, context menus, autocomplete, Scopes |
| Responses | What a handler can return; ephemeral messages, embeds, files, errors |
| Components and modals | Buttons, selects and forms with #[component], #[modal], #[derive(Modal)] |
| Views | rsx! markup and #[view]: every tag and attribute |
| Themes | Consistent colors and branding on embeds and containers |
| REST and deferring | ctx.bot(), follow-ups, Deferred Responses, Background Work |
| Webhook Events | App installs, entitlements, lobby messages |
| Platforms | Adapters, State, platform-specific Commands, logging |
| Testing | Running 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_cloudflare | Serves a bot on Cloudflare Workers |
composure_adapter_tokio | Serves a bot from a hosted server on tokio |
composure_sync | Registers an App’s Commands with Discord at deploy time |
composure_macros | The macros; use them through composure’s macros feature |
composure_commands | A builder for Command Definitions, for bots not using #[command] |
§Modules
command: the handler runtime:Ctx, responses (Ephemeral,Update, …),Theme,View, errors, and the traits the macros implementtypes: Discord’s objects (Interactions, messages, embeds, components, users, …), shared by Interactions, responses and RESTdefinition: Command Definitions, as Discord stores themrest: the REST client over an Adapter’sTransportadapter: the request pipeline every Adapter shares (validate, parse, dispatch)auth: Ed25519 request signature validationcredentials:Credentials, what identifies the application, however the bot loads them
§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)] |
rest | The 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-roles | One 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 | The rest of Discord’s Endpoints, one group each |
tier1 | rest and the Endpoints most bots need (commands, messages, users, channels, guilds, members, roles) |
full | Every Endpoint |
tracing | Spans and events through tracing; see Platforms |
web-crypto | Validate signatures with the host’s Web Crypto on wasm32-unknown-unknown instead of compiling ed25519-dalek in |
reqwest | A blocking ReqwestTransport for deploy-time tools (not for WASM) |
Re-exports§
pub use command::Ctx;pub use credentials::Credentials;pub use credentials::CredentialsError;
Modules§
- adapter
rest - What every Adapter does with a request, whatever the platform: verify the signature, parse,
dispatch to the
InteractionHandler(or hand a Webhook Event to theEventHandleras 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 therestfeature); usePublicKeydirectly 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
Credentialsfrom wherever it keeps them, by the conventional names withCredentials::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.
- rest
rest - Async Discord REST client over an Adapter-provided
Transport(ADR 0004, 0005). - types
- Discord’s data model, shared by Interactions, Responses and REST. Organized by resource;
everything is re-exported flat as
composure::types::X.
Macros§
- rsx
macros - 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 aView, or aModalViewfor 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§
- app
macros - 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. - autocomplete
macros - Suggests values for an Option while the user types. See
Commands.
Defines an Autocomplete Handler from a function taking an optional leading
ctx: Ctxand what the user has typed so far asinput: &str. Attach it to a string, integer, or number Option with#[option("...", autocomplete = name)]. - command
macros - Defines a Command from a function. See Commands.
Defines a Command from a function. Parameters after an optional leading
ctx: Ctxbecome Options; the doc comment becomes the description. - component
macros - Answers a component by
custom_idprefix. See Components and modals. Defines a Component Handler from a function: it answers components whosecustom_idstarts with the prefix. Parameters after an optional leadingctx: ComponentCtxare state carried in thecustom_id(owned, serde-serializable), built with the generatedname::custom_id(..). - group
macros - Groups Commands as subcommands. See Commands. Makes a unit struct a Group that routes to its subcommands. Groups can contain Groups one level deep.
- modal
macros - Answers a modal submit by
custom_idprefix. See Components and modals. Defines a Modal Handler from a function: it answers submits of modals whosecustom_idstarts with the prefix. After an optional leadingctx: ModalCtxcomes the form (a#[derive(Modal)]type), then state carried in thecustom_id.name::show(..)is the modal response that opens the form. - view
macros - 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§
- Choice
macros - 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.
- Modal
macros - 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.