#[cfg(feature = "messenger")]
use crate::Rustybook;
#[cfg(all(feature = "messenger", feature = "cache"))]
use crate::{
Cache,
CacheUpdate,
};
#[cfg(feature = "messenger")]
use std::sync::Arc;
#[cfg(feature = "messenger")]
#[derive(Clone)]
pub struct Context {
client: Rustybook,
}
#[cfg(feature = "messenger")]
impl Context {
pub(crate) fn new(client: Rustybook) -> Self {
Self { client }
}
pub fn client(&self) -> &Rustybook {
&self.client
}
}
#[cfg(feature = "messenger")]
#[derive(Debug, Clone)]
pub struct User {
pub id: String,
pub name: Option<String>,
}
#[cfg(feature = "messenger")]
#[derive(Debug, Clone)]
pub struct Message {
pub message_id: Option<String>,
pub thread_id: String,
pub sender_id: String,
pub text: Option<String>,
pub timestamp_ms: Option<i64>,
}
#[cfg(feature = "messenger")]
pub(crate) fn message_from_raw(message: &rustybook_messenger::MessageEvent) -> Message {
Message {
message_id: message.message_id.clone(),
thread_id: message.thread_id.clone(),
sender_id: message.sender_id.clone(),
text: message.text.clone(),
timestamp_ms: message.timestamp_ms,
}
}
#[cfg(all(feature = "messenger", feature = "cache"))]
impl CacheUpdate for rustybook_messenger::MessageEvent {
type Output = Message;
fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
let mapped = message_from_raw(self);
cache.push_message(mapped.clone());
Some(mapped)
}
}
#[cfg(all(feature = "messenger", feature = "cache"))]
impl CacheUpdate for rustybook_messenger::TypingEvent {
type Output = ();
fn update(&mut self, _cache: &Cache) -> Option<Self::Output> {
None
}
}
#[cfg(all(feature = "messenger", feature = "cache"))]
impl CacheUpdate for rustybook_messenger::PresenceEvent {
type Output = ();
fn update(&mut self, _cache: &Cache) -> Option<Self::Output> {
None
}
}
#[cfg(all(feature = "messenger", feature = "cache"))]
impl CacheUpdate for rustybook_messenger::EventError {
type Output = ();
fn update(&mut self, _cache: &Cache) -> Option<Self::Output> {
None
}
}
#[cfg(all(feature = "messenger", feature = "cache"))]
impl CacheUpdate for rustybook_messenger::Event {
type Output = ();
fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
match self {
rustybook_messenger::Event::Message(event) => {
let _ = event.update(cache);
Some(())
}
rustybook_messenger::Event::Typing(event) => {
let _ = event.update(cache);
Some(())
}
rustybook_messenger::Event::Presence(event) => {
let _ = event.update(cache);
Some(())
}
rustybook_messenger::Event::Error(event) => {
let _ = event.update(cache);
Some(())
}
rustybook_messenger::Event::Listening | rustybook_messenger::Event::Disconnect => None,
}
}
}
#[cfg(feature = "messenger")]
#[derive(Debug, Clone)]
pub struct Typing {
pub user_id: String,
pub thread_id: Option<String>,
pub is_typing: bool,
}
#[cfg(feature = "messenger")]
#[derive(Debug, Clone)]
pub struct Presence {
pub user_id: String,
pub is_active: bool,
pub last_active_ms: Option<i64>,
}
#[cfg(feature = "messenger")]
#[derive(Debug, Clone)]
pub struct ErrorEvent {
pub kind: String,
pub message: String,
}
#[cfg(feature = "messenger")]
pub trait EventHandler: Send + Sync + 'static {
fn ready(&self, _ctx: Context, _user: User) -> impl std::future::Future<Output = ()> + Send {
async {}
}
fn message(
&self,
_ctx: Context,
_msg: Message,
) -> impl std::future::Future<Output = ()> + Send {
async {}
}
fn typing(
&self,
_ctx: Context,
_typing: Typing,
) -> impl std::future::Future<Output = ()> + Send {
async {}
}
fn presence(
&self,
_ctx: Context,
_presence: Presence,
) -> impl std::future::Future<Output = ()> + Send {
async {}
}
fn disconnect(&self, _ctx: Context) -> impl std::future::Future<Output = ()> + Send {
async {}
}
fn error(
&self,
_ctx: Context,
_error: ErrorEvent,
) -> impl std::future::Future<Output = ()> + Send {
async {}
}
}
#[cfg(feature = "messenger")]
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;
};
}
#[cfg(feature = "messenger")]
pub(crate) async fn dispatch_event(
handler: &Arc<impl EventHandler>,
ctx: Context,
ready_user: &User,
event: rustybook_messenger::Event,
) {
match event {
rustybook_messenger::Event::Listening => {
emit_event!(handler, ready, ctx, ready_user.clone());
}
rustybook_messenger::Event::Disconnect => {
emit_event!(handler, disconnect, ctx);
}
rustybook_messenger::Event::Message(message) => {
emit_event!(handler, message, ctx, message_from_raw(&message));
}
rustybook_messenger::Event::Typing(typing) => {
emit_event!(
handler,
typing,
ctx,
Typing {
user_id: typing.user_id,
thread_id: typing.thread_id,
is_typing: typing.is_typing,
}
);
}
rustybook_messenger::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,
}
);
}
rustybook_messenger::Event::Error(error) => {
emit_event!(
handler,
error,
ctx,
ErrorEvent {
kind: format!("{:?}", error.kind),
message: error.message,
}
);
}
}
}