use async_trait::async_trait;
use crate::client::context::Context;
use crate::client::models::*;
use crate::gateway::events::*;
#[derive(Debug, Clone)]
pub struct ErrorEvent {
pub kind: String,
pub message: String,
}
macro_rules! event_handler {
(
$(
$(#[$meta:meta])*
fn $name:ident(&self $(, $arg:ident : $arg_ty:ty )* );
)*
) => {
#[async_trait]
pub trait EventHandler: Send + Sync + 'static {
$(
$(#[$meta])*
async fn $name(&self $(, $arg: $arg_ty)*) {}
)*
}
};
}
macro_rules! emit_event {
($handler:expr, $method:ident, $ctx:expr) => {
$handler.$method($ctx.clone()).await;
};
($handler:expr, $method:ident, $ctx:expr, $value:expr) => {
$handler.$method($ctx.clone(), $value).await;
};
}
event_handler! {
fn ready(&self, _ctx: Context, _user: User);
fn message(&self, _ctx: Context, _msg: Message);
fn typing(&self, _ctx: Context, _typing: Typing);
fn presence(&self, _ctx: Context, _presence: Presence);
fn disconnect(&self, _ctx: Context);
fn error(&self, _ctx: Context, _error: ErrorEvent);
}
pub(crate) async fn dispatch_event(
handler: &dyn EventHandler,
ctx: Context,
ready_user: &User,
event: Event,
) {
match event {
Event::Listening => {
emit_event!(handler, ready, ctx, ready_user.clone());
}
Event::Disconnect => {
emit_event!(handler, disconnect, ctx);
}
Event::Message(message) => {
emit_event!(handler, message, ctx, (&message).into());
}
Event::Typing(typing) => {
emit_event!(
handler,
typing,
ctx,
Typing {
user_id: typing.user_id,
thread_id: typing.thread_id,
is_typing: typing.is_typing,
}
);
}
Event::Presence(presence) => {
emit_event!(
handler,
presence,
ctx,
Presence {
user_id: presence.user_id,
is_active: presence.is_active,
last_active_ms: presence.last_active_ms,
}
);
}
Event::Error(error) => {
emit_event!(
handler,
error,
ctx,
ErrorEvent {
kind: format!("{:?}", error.kind),
message: error.message,
}
);
}
}
}