Skip to content
RustAsync Library

diself

Async Rust library for Discord selfbot automation. Type-safe, event-driven, built on tokio.

The Problem

Automating Discord user accounts in Rust meant dealing with raw WebSocket connections, manually parsing gateway events, handling reconnection logic, and managing rate limits — all from scratch. Existing solutions were either outdated, incomplete, or tied to bot-only APIs that don't work with user tokens.

The Approach

diself provides a clean, strongly-typed async API that abstracts away the complexity of Discord's gateway and REST protocols. You implement an EventHandler trait, and the library handles the connection lifecycle — heartbeats, session resumption, exponential backoff, and caching — so you can focus on what your automation actually does.

Technical Choices

Async-first on tokio

Discord bots need to handle many concurrent events — messages, presence updates, guild changes — without blocking. Tokio's async runtime lets diself process all of this efficiently on a single thread, with zero-cost futures and cooperative scheduling.

Exhaustive type system

60+ gateway events are modeled as typed Rust enums. Every channel, message, guild, role, and permission has a dedicated struct. If your handler compiles, it handles the data correctly — no runtime surprises from untyped JSON.

Built-in resilience

Network drops happen. diself automatically reconnects, resumes sessions when possible, and backs off exponentially when the gateway pushes back. Rate limits on the REST API are tracked and retried transparently.

Key Features

60+ gateway events with typed handlers
Automatic reconnection & session resumption
Configurable caching (users, channels, guilds)
Builder patterns for messages & embeds
Rate-limit aware HTTP client
Graceful shutdown via Client::shutdown()

Usage Example

main.rs
1use diself::prelude::*;
2 
3struct Handler;
4 
5#[async_trait]
6impl EventHandler for Handler {
7 async fn message_create(&self, ctx: Context, msg: Message) {
8 if msg.content == "!ping" {
9 ctx.http
10 .create_message(msg.channel_id)
11 .content("Pong!")
12 .send()
13 .await
14 .ok();
15 }
16 }
17 
18 async fn ready(&self, _ctx: Context, user: User) {
19 println!("Connected as {}", user.username);
20 }
21}
22 
23#[tokio::main]
24async fn main() {
25 Client::builder("token")
26 .event_handler(Handler)
27 .build()
28 .await
29 .expect("Failed to start client")
30 .start()
31 .await;
32}
Source & Crate