dingtalk_stream/frames/down_message/
mod.rs1use serde::{Deserialize, Deserializer, Serialize};
2use std::collections::HashMap;
3
4pub mod callback_message;
5pub mod event_message;
6pub mod system_message;
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct DownStreamMessage {
10 #[serde(rename = "specVersion")]
11 pub spec_version: Option<String>,
12 pub headers: MessageHeaders,
13 #[serde(rename = "type")]
14 pub r#type: MessageType,
15 pub data: Option<String>,
16 #[serde(flatten)]
17 pub extensions: HashMap<String, serde_json::Value>,
18}
19
20#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
21pub enum MessageType {
22 #[serde(rename = "SYSTEM")]
23 System,
24 #[serde(rename = "EVENT")]
25 Event,
26 #[serde(rename = "CALLBACK")]
27 Callback,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub enum Data {
32 System(callback_message::MessageData),
33 Event(event_message::EventMessage),
34 Callback(callback_message::CallbackMessage),
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, Default)]
39pub struct MessageHeaders {
40 #[serde(rename = "appId", skip_serializing_if = "Option::is_none")]
41 pub app_id: Option<String>,
42 #[serde(rename = "connectionId", skip_serializing_if = "Option::is_none")]
43 pub connection_id: Option<String>,
44 #[serde(rename = "contentType", skip_serializing_if = "Option::is_none")]
45 pub content_type: Option<String>,
46 #[serde(rename = "messageId", skip_serializing_if = "Option::is_none")]
47 pub message_id: Option<String>,
48 #[serde(rename = "time", skip_serializing_if = "Option::is_none")]
49 pub time: Option<String>,
50 #[serde(rename = "topic", skip_serializing_if = "Option::is_none")]
51 pub topic: Option<MessageTopic>,
52 #[serde(rename = "eventBornTime", skip_serializing_if = "Option::is_none")]
54 pub event_born_time: Option<i64>,
55 #[serde(rename = "eventCorpId", skip_serializing_if = "Option::is_none")]
56 pub event_corp_id: Option<String>,
57 #[serde(rename = "eventId", skip_serializing_if = "Option::is_none")]
58 pub event_id: Option<String>,
59 #[serde(rename = "eventType", skip_serializing_if = "Option::is_none")]
60 pub event_type: Option<String>,
61 #[serde(rename = "eventUnifiedAppId", skip_serializing_if = "Option::is_none")]
62 pub event_unified_app_id: Option<String>,
63 #[serde(flatten)]
65 pub extensions: HashMap<String, serde_json::Value>,
66}
67
68impl MessageHeaders {
69 pub fn new() -> Self {
70 Self::default()
71 }
72
73 pub fn with_message_id(mut self, message_id: String) -> Self {
74 self.message_id = Some(message_id);
75 self
76 }
77
78 pub fn with_content_type(mut self, content_type: &str) -> Self {
79 self.content_type = Some(content_type.to_string());
80 self
81 }
82}
83
84#[derive(Debug, Clone, PartialEq, Eq, Serialize, Hash)]
86#[serde(untagged)]
87pub enum MessageTopic {
88 #[serde(rename = "CONNECTED")]
89 Connected,
90 #[serde(rename = "REGISTERED")]
91 Registered,
92 #[serde(rename = "disconnect")]
93 Disconnect,
94 #[serde(rename = "KEEPALIVE")]
95 KeepAlive,
96 #[serde(rename = "ping")]
97 Ping,
98 Callback(String),
99}
100
101impl From<String> for MessageTopic {
102 fn from(s: String) -> Self {
103 let uppercase = s.to_uppercase();
104 match uppercase.as_str() {
105 "CONNECTED" => MessageTopic::Connected,
106 "REGISTERED" => MessageTopic::Registered,
107 "DISCONNECT" => MessageTopic::Disconnect,
108 "KEEPALIVE" => MessageTopic::KeepAlive,
109 "PING" => MessageTopic::Ping,
110 _ => MessageTopic::Callback(s),
111 }
112 }
113}
114
115impl<'de> Deserialize<'de> for MessageTopic {
116 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
117 where
118 D: Deserializer<'de>,
119 {
120 let str = String::deserialize(deserializer)?;
121 Ok(Self::from(str))
122 }
123}
124
125impl std::fmt::Display for MessageTopic {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 let str = match self {
128 MessageTopic::Connected => "CONNECTED",
129 MessageTopic::Registered => "REGISTERED",
130 MessageTopic::Disconnect => "disconnect",
131 MessageTopic::KeepAlive => "KEEPALIVE",
132 MessageTopic::Ping => "ping",
133 MessageTopic::Callback(s) => s,
134 };
135 write!(f, "{str}")
136 }
137}