dingtalk_rs/client/message_notify/
message.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Deserialize, Serialize, Default)]
6pub struct Message {
7 pub msgtype: String,
10 #[serde(flatten)]
11 pub content: MessageBody,
12}
13
14impl From<MessageBody> for Message {
15 fn from(body: MessageBody) -> Self {
16 let msgtype = match &body {
17 MessageBody::Text { content: _ } => "text",
18 MessageBody::File { media_id: _ } => "file",
19 MessageBody::Image { media_id: _ } => "image",
20 MessageBody::Voice {
21 media_id: _,
22 duration: _,
23 } => "voice",
24 MessageBody::Link {
25 message_url: _,
26 pic_url: _,
27 title: _,
28 text: _,
29 } => "link",
30 MessageBody::Oa {
31 message_url: _,
32 pc_message_url: _,
33 head: _,
34 status_bar: _,
35 body: _,
36 } => "oa",
37 MessageBody::Markdown { title: _, text: _ } => "markdown",
38 MessageBody::ActionCard {
39 markdown: _,
40 title: _,
41 single_title: _,
42 single_url: _,
43 btn_orientation: _,
44 btn_json_list: _,
45 } => "action_card",
46 };
47
48 Self {
49 msgtype: msgtype.to_string(),
50 content: body,
51 }
52 }
53}
54
55#[derive(Debug, Deserialize, Serialize)]
57#[serde(rename_all = "snake_case")]
58pub enum MessageBody {
59 Text {
61 content: String,
63 },
64 Image {
66 media_id: String,
70 },
71 Voice {
73 media_id: String,
77 duration: i32,
79 },
80 File {
82 media_id: String,
86 },
87 Link {
89 #[serde(rename = "messageUrl")]
93 message_url: String,
94 #[serde(rename = "picUrl")]
97 pic_url: String,
98 title: String,
100 text: String,
102 },
103 Oa {
105 message_url: String,
109 #[serde(skip_serializing_if = "Option::is_none")]
111 pc_message_url: Option<String>,
112 head: OaHead,
114 #[serde(skip_serializing_if = "Option::is_none")]
117 status_bar: Option<OaStatusBar>,
118 body: OaBody,
120 },
121 Markdown {
123 title: String,
125 text: String,
127 },
128 ActionCard {
130 markdown: String,
132 #[serde(skip_serializing_if = "Option::is_none")]
134 title: Option<String>,
135 #[serde(skip_serializing_if = "Option::is_none")]
138 single_title: Option<String>,
139 #[serde(skip_serializing_if = "Option::is_none")]
143 single_url: Option<String>,
144 #[serde(skip_serializing_if = "Option::is_none")]
149 btn_orientation: Option<String>,
150 #[serde(skip_serializing_if = "Option::is_none")]
153 btn_json_list: Option<Vec<BtnJson>>,
154 },
155}
156
157#[derive(Debug, Deserialize, Serialize, Default)]
158pub struct OaHead {
159 pub bgcolor: String,
162 pub text: String,
170}
171
172#[derive(Debug, Deserialize, Serialize, Default)]
173pub struct OaStatusBar {
174 #[serde(skip_serializing_if = "Option::is_none")]
176 pub status_value: Option<String>,
177 #[serde(skip_serializing_if = "Option::is_none")]
179 pub status_bg: Option<String>,
180}
181
182#[derive(Debug, Deserialize, Serialize, Default)]
183pub struct OaBody {
184 #[serde(skip_serializing_if = "Option::is_none")]
186 pub title: Option<String>,
187 #[serde(skip_serializing_if = "Option::is_none")]
189 pub form: Option<Vec<KvPair>>,
190 #[serde(skip_serializing_if = "Option::is_none")]
192 pub rich: Option<Rich>,
193 #[serde(skip_serializing_if = "Option::is_none")]
195 pub content: Option<String>,
196 #[serde(skip_serializing_if = "Option::is_none")]
200 pub image: Option<String>,
201 #[serde(skip_serializing_if = "Option::is_none")]
203 pub file_count: Option<String>,
204 #[serde(skip_serializing_if = "Option::is_none")]
206 pub author: Option<String>,
207}
208
209#[derive(Debug, Deserialize, Serialize, Default)]
210pub struct KvPair {
211 #[serde(skip_serializing_if = "Option::is_none")]
213 pub key: Option<String>,
214 #[serde(skip_serializing_if = "Option::is_none")]
216 pub value: Option<String>,
217}
218
219#[derive(Debug, Deserialize, Serialize, Default)]
220pub struct Rich {
221 #[serde(skip_serializing_if = "Option::is_none")]
223 pub num: Option<String>,
224 #[serde(skip_serializing_if = "Option::is_none")]
226 pub unit: Option<String>,
227}
228
229#[derive(Debug, Deserialize, Serialize, Default)]
230pub struct BtnJson {
231 #[serde(skip_serializing_if = "Option::is_none")]
233 pub title: Option<String>,
234 #[serde(skip_serializing_if = "Option::is_none")]
236 pub action_url: Option<String>,
237}
238
239impl Default for MessageBody {
240 fn default() -> Self {
241 Self::Text {
242 content: String::from("默认消息"),
243 }
244 }
245}