1use crate::frames::down_message::callback_message::CallbackMessage;
6use crate::frames::down_message::event_message::EventMessage;
7use crate::frames::down_message::system_message::SystemMessage;
8use crate::frames::down_message::MessageTopic;
9use crate::frames::up_message::callback_message::WebhookMessage;
10use crate::DingTalkStream;
11use async_trait::async_trait;
12use std::fmt::{Display, Formatter};
13use std::sync::Arc;
14use tokio::sync::mpsc::Sender;
15use tokio_tungstenite::tungstenite::Message;
16
17#[async_trait]
19pub trait CallbackHandler: Send + Sync {
20 async fn process(
22 &self,
23 client: Arc<DingTalkStream>,
24 message: &CallbackMessage,
25 cb_webhook_msg_sender: Option<Sender<WebhookMessage>>,
26 ) -> Result<Resp, Error>;
27
28 fn pre_start(&self) {}
30
31 fn topic(&self) -> &MessageTopic;
33}
34
35#[async_trait]
37pub trait EventHandler: Send + Sync {
38 async fn process(
40 &self,
41 client: Arc<DingTalkStream>,
42 message: &EventMessage,
43 ) -> Result<Resp, Error>;
44
45 fn pre_start(&self) {}
47}
48
49#[async_trait]
51pub trait SystemHandler: Send + Sync {
52 async fn process(
54 &self,
55 client: Arc<DingTalkStream>,
56 message: &SystemMessage,
57 ) -> Result<Resp, Error>;
58
59 fn pre_start(&self) {}
61}
62
63#[derive(Debug, Clone)]
64pub enum Resp {
65 Text(String),
66 Json(serde_json::Value),
67}
68
69impl Display for Resp {
70 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
71 match self {
72 Resp::Text(text) => write!(f, "Text: {}", text),
73 Resp::Json(json) => write!(f, "JSON: {}", json),
74 }
75 }
76}
77
78#[derive(Debug, Clone)]
79pub struct Error {
80 pub msg: String,
81 pub code: ErrorCode,
82}
83
84impl Display for Error {
85 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
86 f.write_str(&format!("Error: {} (Code: {})", self.msg, self.code))
87 }
88}
89
90impl std::error::Error for Error {}
91
92#[derive(Debug, Clone, Copy)]
93#[repr(i32)]
94pub enum ErrorCode {
95 BadRequest = 400i32,
96 Unauthorized = 401,
97 Forbidden = 403,
98 NotFound = 404,
99 MethodNotAllowed = 405,
100 TooManyRequests = 429,
101 InternalServerError = 500,
102 BadGateway = 502,
103 ServiceUnavailable = 503,
104 GatewayTimeout = 504,
105}
106
107impl Display for ErrorCode {
108 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
109 f.write_str(&format!("{}", *self as i32))
110 }
111}
112
113pub struct DefaultCallbackHandler {
115 pub topic: MessageTopic,
116}
117
118impl DefaultCallbackHandler {
119 pub fn new(topic: &str) -> Self {
120 Self {
121 topic: MessageTopic::Callback(topic.to_string()),
122 }
123 }
124}
125
126#[derive(Debug, Copy, Clone)]
127pub enum LifecycleEvent<'a> {
128 Start,
129 Connecting {
130 websocket_url: &'a str,
131 },
132 Connected {
133 websocket_url: &'a str,
134 },
135 WebsocketWrite {
136 payload: &'a str,
137 result: &'a crate::Result<()>,
138 },
139 WebsocketWriteWithRetry {
140 payload: &'a str,
141 cnt: u8,
142 result: &'a crate::Result<()>,
143 },
144 WebsocketRead {
145 result: &'a crate::Result<Message>,
146 },
147 Keepalive {
148 payload: &'a str,
149 result: &'a crate::Result<()>,
150 },
151 Disconnected {
152 result: &'a crate::Result<()>,
153 },
154 Stopped,
155}
156#[allow(unused)]
157#[async_trait]
158pub trait LifecycleListener: Send + Sync {
159 async fn on_event<'a>(&self, client: Arc<DingTalkStream>, event: LifecycleEvent<'a>) {}
160
161 async fn on_start(&self, client: Arc<DingTalkStream>) {
162 let _ = self.on_event(client, LifecycleEvent::Start).await;
163 }
164
165 async fn on_connecting(&self, client: Arc<DingTalkStream>, websocket_url: &str) {
166 let _ = self
167 .on_event(client, LifecycleEvent::Connecting { websocket_url })
168 .await;
169 }
170
171 async fn on_connected(&self, client: Arc<DingTalkStream>, websocket_url: &str) {
172 let _ = self
173 .on_event(client, LifecycleEvent::Connected { websocket_url })
174 .await;
175 }
176
177 async fn on_websocket_write(
178 &self,
179 client: Arc<DingTalkStream>,
180 payload: &str,
181 result: &crate::Result<()>,
182 ) {
183 let _ = self
184 .on_event(client, LifecycleEvent::WebsocketWrite { payload, result })
185 .await;
186 }
187
188 async fn on_websocket_write_with_retry(
189 &self,
190 client: Arc<DingTalkStream>,
191 payload: &str,
192 cnt: u8,
193 result: &crate::Result<()>,
194 ) {
195 let _ = self
196 .on_event(
197 client,
198 LifecycleEvent::WebsocketWriteWithRetry {
199 payload,
200 cnt,
201 result,
202 },
203 )
204 .await;
205 }
206
207 async fn on_websocket_read(
208 &self,
209 client: Arc<DingTalkStream>,
210 result: &crate::Result<Message>,
211 ) {
212 let _ = self
213 .on_event(client, LifecycleEvent::WebsocketRead { result })
214 .await;
215 }
216
217 async fn on_keepalive(
218 &self,
219 client: Arc<DingTalkStream>,
220 payload: &str,
221 result: &crate::Result<()>,
222 ) {
223 let _ = self
224 .on_event(client, LifecycleEvent::Keepalive { payload, result })
225 .await;
226 }
227
228 async fn on_disconnected(&self, client: Arc<DingTalkStream>, result: &crate::Result<()>) {
229 let _ = self
230 .on_event(client, LifecycleEvent::Disconnected { result })
231 .await;
232 }
233
234 async fn on_stopped(&self, client: Arc<DingTalkStream>) {
235 let _ = self.on_event(client, LifecycleEvent::Stopped).await;
236 }
237}
238
239#[derive(Debug, Clone, Copy, Default)]
240pub(crate) struct DefaultLifecycleListener;
241
242impl LifecycleListener for DefaultLifecycleListener {}