Skip to content

EventHandler

EventHandler is the async trait you implement to react to gateway events. Every method has an empty default body, so you only override what you care about — even an empty struct will compile.

rust
#[async_trait::async_trait]
pub trait EventHandler: Send + Sync {
    async fn ready(&self, _session: ReadySession) {}
    async fn message_create(&self, _session: ChannelReplySession) {}
    /* … */
}

The framework dispatches whichever method matches the gateway event type. Every public callback receives a session object. Reply-capable message callbacks use specialized reply sessions, while lifecycle and non-reply callbacks use event sessions whose payload is available through session.event(). Every method returns (); if you need to surface an error, log it locally — gateway-event errors do not interrupt the connection.

Method catalogue

Methods are grouped by the gateway category that produces them.

Lifecycle

  • ready(ReadySession) — called once after a successful identify handshake; bot info is available through session.bot_info().
  • resumed(ResumeSession) — called after a successful resume.
  • unknown_event(UnknownEventSession) — catch-all for event types without a first-class callback.

Channel messages

  • message_create(ChannelReplySession) — guild channel messages and @mentions.
  • message_delete(MessageDeleteSession) — guild message delete event.
  • public_message_delete(MessageDeleteSession) — public-domain delete.

Direct messages

  • direct_message_create(DirectReplySession)
  • direct_message_delete(MessageDeleteSession)

Group / C2C

  • group_message_create(GroupReplySession)
  • c2c_message_create(C2CReplySession)
  • friend_add(C2CManageSession) / friend_del(C2CManageSession)
  • c2c_msg_reject(C2CManageSession) / c2c_msg_receive(C2CManageSession)
  • subscribe_message_status(SubscribeMessageStatusSession)
  • enter_aio(EnterAioSession)

Group management

  • group_add_robot / group_del_robot
  • group_msg_reject / group_msg_receive

Reactions

  • message_reaction_add(ReactionSession) / message_reaction_remove(ReactionSession)

Interaction

  • interaction_create(InteractionSession) — buttons and application interaction payloads.

Audio / voice

  • audio_start / audio_finish / on_mic / off_micAudio payloads.
  • audio_or_live_channel_member_enter / audio_or_live_channel_member_exitPublicAudio payloads.

Guild / channel

  • guild_create / guild_update / guild_delete
  • channel_create / channel_update / channel_delete
  • guild_member_add / guild_member_update / guild_member_remove

Audit

  • message_audit_pass / message_audit_reject

Forum

  • forum_thread_create / forum_thread_update / forum_thread_delete
  • forum_post_create / forum_post_delete
  • forum_reply_create / forum_reply_delete
  • forum_publish_audit_result(ForumAuditSession)
  • Open-forum equivalents: open_forum_thread_*, open_forum_post_*, open_forum_reply_*.

Skeleton implementation

rust
use botrs::{ChannelReplySession, Client, EventHandler, Intents, ReadySession, Token};

struct MyBot;

#[async_trait::async_trait]
impl EventHandler for MyBot {
    async fn ready(&self, session: ReadySession) {
        info!("logged in as {}", session.event().user.username);
    }

    async fn message_create(&self, mut session: ChannelReplySession) {
        let message = session.message().clone();
        if message.author.bot {
            return;
        }

        if message.content.trim() == "!ping" {
            let _ = session.reply("Pong!").await;
        }
    }
}

MyBot only handles two events; every other gateway event silently lands in the empty defaults.

Concurrency

Each handler invocation runs on the runtime task that dispatched the event. Long-running work should be spawned to avoid blocking subsequent dispatches:

rust
let api = session.api_handle();
tokio::spawn(async move {
    if let Err(e) = run_long_task(&api).await {
        warn!("background task failed: {e}");
    }
});

Sessions expose the shared API through session.api() and Deref<Target = BotApi>. Use session.api_handle() when a background task needs to own the API client.

See also

  • Client — how a Client<H: EventHandler> is constructed and started.
  • Bot API — the REST API available through sessions.
  • Intents — controls which of these methods can ever be called.

Released under the MIT License.