70 releases
Uses new Rust 2024
| 0.17.0 | Nov 8, 2025 |
|---|---|
| 0.16.0 | Jan 12, 2025 |
| 0.16.0-rc.1 | Feb 21, 2024 |
| 0.15.4 | Sep 10, 2023 |
| 0.2.5 | Nov 29, 2020 |
#2 in #discord-api
9,319 downloads per month
Used in 13 crates
(12 directly)
2.5MB
60K
SLoC
twilight-gateway
twilight-gateway is an implementation of Discord's sharding gateway sessions.
This is responsible for receiving stateful events in real-time from Discord and
sending some stateful information.
The primary type is the Shard, a stateful interface to maintain a Websocket
connection to Discord's gateway. Much of its functionality can be configured,
and it's used to receive gateway events or raw Websocket messages, useful for
load balancing and microservices.
Multiple shards may easily be created at once, with a per shard config created
from a Fn(ShardId, ConfigBuilder) -> Config closure, with the help of the
create_ set of functions. These functions will reuse shards' TLS context and
[session queue][queue], something otherwise achieved by cloning an existing
Config.
Features
simd-json: usesimd-jsoninstead ofserde_jsonfor deserializing events- TLS (mutually exclusive)
native-tls: platform's native TLS implementation vianative-tlsrustls-native-roots:rustlsusing native root certificatesrustls-platform-verifier(default):rustlsusing operating system's certificate facilities viarustls-platform-verifierrustls-webpki-roots:rustlsusingwebpki-rootsfor root certificates, useful forscratchcontainers
twilight-http(default): enable thestream::create_recommendedfunction- Transport compression (mutually exclusive)
zlib: Zlib transport compression using [zlib-rs][^1]zstd(default): Zstandard transport compression usingzstd-sys
Example
Create the recommended number of shards and loop over their guild events in parallel
use std::{
env,
sync::atomic::{AtomicBool, Ordering},
};
use tokio::signal;
use twilight_gateway::{
error::ReceiveMessageErrorType, CloseFrame, Config, Event, EventTypeFlags, Intents, Shard,
StreamExt as _,
};
use twilight_http::Client;
static SHUTDOWN: AtomicBool = AtomicBool::new(false);
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt::init();
let token = env::var("DISCORD_TOKEN")?;
let client = Client::new(token.clone());
let config = Config::new(token, Intents::GUILDS);
let shards =
twilight_gateway::create_recommended(&client, config, |_, builder| builder.build()).await?;
let mut senders = Vec::with_capacity(shards.len());
let mut tasks = Vec::with_capacity(shards.len());
for shard in shards {
senders.push(shard.sender());
tasks.push(tokio::spawn(runner(shard)));
}
signal::ctrl_c().await?;
SHUTDOWN.store(true, Ordering::Relaxed);
for sender in senders {
// Ignore error if shard's already shutdown.
_ = sender.close(CloseFrame::NORMAL);
}
for jh in tasks {
_ = jh.await;
}
Ok(())
}
#[tracing::instrument(fields(shard = %shard.id()), skip_all)]
async fn runner(mut shard: Shard) {
while let Some(item) = shard.next_event(EventTypeFlags::all()).await {
let event = match item {
Ok(Event::GatewayClose(_)) if SHUTDOWN.load(Ordering::Relaxed) => break,
Ok(event) => event,
Err(source) => {
tracing::warn!(?source, "error receiving event");
continue;
}
};
// You'd normally want to spawn a new tokio task for each event and
// handle the event there to not block the shard.
tracing::debug!(?event, shard = ?shard.id(), "received event");
}
}
There are a few additional examples located in the repository.
[^1]: Except for the s390x arch, where zlib-ng-sys is used instead.
Dependencies
~9–27MB
~403K SLoC