Skip to main content

Crate composure_sync

Crate composure_sync 

Source
Expand description

Sync: make Discord’s stored Command Definitions match an App’s Commands, at deploy time.

Discord only shows the Commands it has stored for an application. This crate reads the definitions of a Composure App (#[app] implements CommandSetDefinition) and makes Discord’s match them, from a binary that runs on the host, never in the deployed bot:

ⓘ
// src/bin/sync.rs
fn main() -> std::process::ExitCode {
    composure_sync::sync_from_env(&my_bot::Bot)
}
cargo run --bin sync             # show the plan, apply after confirming
cargo run --bin sync -- --check  # CI: exit 2 when Discord is out of date
cargo run --bin sync -- --yes    # CI deploys: apply without asking

§Configuration

Env var
DISCORD_TOKENThe bot token
DISCORD_APPLICATION_IDThe application id
COMPOSURE_SCOPE_<NAME>Comma-separated guild ids for Commands with scope = "name" (uppercased, - as _)

§How it works

Each target (global, or one guild) gets every Command whose Scope maps to it: Commands without a Scope are global, Scoped ones go to their Scope’s guilds. A SyncPlan is computed by comparing Definitions by name and type; targets with changes are overwritten with one bulk request each, targets without changes are left alone. Every guild listed for a Scope is synced, so a guild whose Commands were all removed is cleared; guilds not listed are never touched.

The command line (sync_from_env, clap and cliclack) is the default cli feature. Without it, SyncConfig, plan and apply remain, for other configuration sources or a custom front end:

use composure::command::CommandSetDefinition;

let config = composure_sync::SyncConfig::from_env()?;
let plan = composure_sync::plan(Bot::definitions(), &config)?;
println!("{plan}");
if plan.has_changes() {
    composure_sync::apply(&plan, &config)?;
}

Structs§

ChangeCounts
How many Commands a plan creates, updates and deletes
SyncConfig
Credentials and Scope mapping for a Sync
SyncPlan
The creates, updates, and deletes a Sync would perform, per target
TargetPlan
What a Sync would do to one target

Enums§

Change
One change to a target
SyncError
Why a Sync could not be planned or applied
Target
Where a set of Commands is stored on Discord

Functions§

apply
Overwrites every target in the plan that has changes
apply_target
Overwrites one target with its planned Commands, changed or not
client
Bot Client for config; waits out rate limits up to a minute, since Sync is not under a platform time limit
plan
Fetches what Discord has for each target and plans the changes
plan_target
Compares what a target should have with what Discord has
sync_from_envcli
Entry point for a Sync bin: parses the command line, reads SyncConfig::from_env, shows the Sync Plan, and applies it after confirmation.
targets
Splits Definitions into the Commands each target should end up with.