use crate::frames::down_message::callback_message::CallbackMessage;
use crate::frames::down_message::event_message::EventMessage;
use crate::frames::down_message::system_message::SystemMessage;
use crate::frames::down_message::MessageTopic;
use crate::frames::up_message::callback_message::WebhookMessage;
use crate::DingTalkStream;
use async_trait::async_trait;
use std::fmt::{Display, Formatter};
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tokio_tungstenite::tungstenite::Message;
#[async_trait]
pub trait CallbackHandler: Send + Sync {
async fn process(
&self,
client: Arc<DingTalkStream>,
message: &CallbackMessage,
cb_webhook_msg_sender: Option<Sender<WebhookMessage>>,
) -> Result<Resp, Error>;
fn pre_start(&self) {}
fn topic(&self) -> &MessageTopic;
}
#[async_trait]
pub trait EventHandler: Send + Sync {
async fn process(
&self,
client: Arc<DingTalkStream>,
message: &EventMessage,
) -> Result<Resp, Error>;
fn pre_start(&self) {}
}
#[async_trait]
pub trait SystemHandler: Send + Sync {
async fn process(
&self,
client: Arc<DingTalkStream>,
message: &SystemMessage,
) -> Result<Resp, Error>;
fn pre_start(&self) {}
}
#[derive(Debug, Clone)]
pub enum Resp {
Text(String),
Json(serde_json::Value),
}
impl Display for Resp {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Resp::Text(text) => write!(f, "Text: {}", text),
Resp::Json(json) => write!(f, "JSON: {}", json),
}
}
}
#[derive(Debug, Clone)]
pub struct Error {
pub msg: String,
pub code: ErrorCode,
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!("Error: {} (Code: {})", self.msg, self.code))
}
}
impl std::error::Error for Error {}
#[derive(Debug, Clone, Copy)]
#[repr(i32)]
pub enum ErrorCode {
BadRequest = 400i32,
Unauthorized = 401,
Forbidden = 403,
NotFound = 404,
MethodNotAllowed = 405,
TooManyRequests = 429,
InternalServerError = 500,
BadGateway = 502,
ServiceUnavailable = 503,
GatewayTimeout = 504,
}
impl Display for ErrorCode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!("{}", *self as i32))
}
}
pub struct DefaultCallbackHandler {
pub topic: MessageTopic,
}
impl DefaultCallbackHandler {
pub fn new(topic: &str) -> Self {
Self {
topic: MessageTopic::Callback(topic.to_string()),
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum LifecycleEvent<'a> {
Start,
Connecting {
websocket_url: &'a str,
},
Connected {
websocket_url: &'a str,
},
WebsocketWrite {
payload: &'a str,
result: &'a crate::Result<()>,
},
WebsocketWriteWithRetry {
payload: &'a str,
cnt: u8,
result: &'a crate::Result<()>,
},
WebsocketRead {
result: &'a crate::Result<Message>,
},
Keepalive {
payload: &'a str,
result: &'a crate::Result<()>,
},
Disconnected {
result: &'a crate::Result<()>,
},
Stopped,
}
#[allow(unused)]
#[async_trait]
pub trait LifecycleListener: Send + Sync {
async fn on_event<'a>(&self, client: Arc<DingTalkStream>, event: LifecycleEvent<'a>) {}
async fn on_start(&self, client: Arc<DingTalkStream>) {
let _ = self.on_event(client, LifecycleEvent::Start).await;
}
async fn on_connecting(&self, client: Arc<DingTalkStream>, websocket_url: &str) {
let _ = self
.on_event(client, LifecycleEvent::Connecting { websocket_url })
.await;
}
async fn on_connected(&self, client: Arc<DingTalkStream>, websocket_url: &str) {
let _ = self
.on_event(client, LifecycleEvent::Connected { websocket_url })
.await;
}
async fn on_websocket_write(
&self,
client: Arc<DingTalkStream>,
payload: &str,
result: &crate::Result<()>,
) {
let _ = self
.on_event(client, LifecycleEvent::WebsocketWrite { payload, result })
.await;
}
async fn on_websocket_write_with_retry(
&self,
client: Arc<DingTalkStream>,
payload: &str,
cnt: u8,
result: &crate::Result<()>,
) {
let _ = self
.on_event(
client,
LifecycleEvent::WebsocketWriteWithRetry {
payload,
cnt,
result,
},
)
.await;
}
async fn on_websocket_read(
&self,
client: Arc<DingTalkStream>,
result: &crate::Result<Message>,
) {
let _ = self
.on_event(client, LifecycleEvent::WebsocketRead { result })
.await;
}
async fn on_keepalive(
&self,
client: Arc<DingTalkStream>,
payload: &str,
result: &crate::Result<()>,
) {
let _ = self
.on_event(client, LifecycleEvent::Keepalive { payload, result })
.await;
}
async fn on_disconnected(&self, client: Arc<DingTalkStream>, result: &crate::Result<()>) {
let _ = self
.on_event(client, LifecycleEvent::Disconnected { result })
.await;
}
async fn on_stopped(&self, client: Arc<DingTalkStream>) {
let _ = self.on_event(client, LifecycleEvent::Stopped).await;
}
}
#[derive(Debug, Clone, Copy, Default)]
pub(crate) struct DefaultLifecycleListener;
impl LifecycleListener for DefaultLifecycleListener {}