Configuration
botrs deliberately keeps its configuration surface tiny: a Token, an Intents set, a sandbox flag, and an HTTP timeout. Everything else is library-agnostic and stays in your own application.
Token
Token::new(app_id, secret) is the basic constructor. Token::from_env() reads QQ_BOT_APP_ID and QQ_BOT_SECRET from the process environment, validates them, and returns BotError::Config for missing variables or BotError::Auth for empty values.
let token = Token::from_env()?;
token.validate()?; // optional; from_env already calls thisToken::validate() returns BotError::Auth when app_id or secret is empty. There are no other format checks — the gateway and REST endpoints reject bad credentials at runtime.
For logging, prefer token.safe_display() over Debug/Display of the raw token: it masks the secret with first4****last4.
tracing::info!("loaded {}", token.safe_display());Intents
Intents is described in detail in intents. The relevant configuration shape is:
let intents = Intents::new()
.with_public_guild_messages()
.with_direct_message();This starts from an empty set and adds only the event categories your handler consumes. Use Intents::default() when you want the public preset instead.
Sandbox vs production
Client::new(token, intents, handler, is_sandbox: bool) — pass true to use QQ's sandbox OpenAPI endpoint. The REST endpoint constants are exported for reference:
botrs::DEFAULT_API_URL // "https://api.sgroup.qq.com"
botrs::SANDBOX_API_URL // "https://sandbox.api.sgroup.qq.com"Internally, the client builds an HttpClient with HttpClient::new(timeout_secs, is_sandbox), then asks get_gateway for the actual WebSocket URL before connecting. If you construct a BotApi outside of Client (for one-off REST calls), use the same constructor to pick the environment.
HTTP timeout
Client::new uses the constant botrs::DEFAULT_TIMEOUT (30 seconds). Override it with Client::with_config(token, intents, handler, timeout_secs, is_sandbox). The timeout applies to each HTTP request individually; long-polling style operations are not used by the framework.
let client = Client::with_config(token, intents, MyBot, 60, false)?;If you build your own HttpClient, the same timeout argument applies:
let http = botrs::http::HttpClient::new(60, false)?;
let api = botrs::BotApi::new(http, token);Logging
The framework uses tracing and emits no logs unless you initialize a subscriber:
tracing_subscriber::fmt()
.with_env_filter("botrs=info")
.init();Bumping the filter to botrs=debug enables gateway-frame and HTTP-debug traces.
What botrs does not configure
The framework reads no config files of its own. It does not require, set, or interpret variables beyond the two Token::from_env() looks for. Application-level concerns — config file format, secrets management, runtime tuning, observability stacks — stay in your code, not in the framework.