1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Deserialize, Serialize)]
4#[serde(tag = "type", content = "data")]
5pub enum MessageElement {
6 #[serde(rename = "text")]
8 Text {
9 #[serde(rename = "content")]
11 text: String,
12 },
13 #[serde(rename = "at")]
15 At {
16 id: String,
18 name: Option<String>,
20 role: Option<String>,
22 #[serde(rename = "type")]
23 at_type: Option<String>, },
25
26 #[serde(rename = "sharp")]
28 Sharp {
29 id: String,
31 name: Option<String>,
33 },
34
35 #[serde(rename = "img")]
37 Image {
38 src: String,
40 title: Option<String>,
42 width: Option<u32>,
44 height: Option<u32>,
46 cache: Option<bool>,
48 timeout: Option<String>,
50 },
51 #[serde(rename = "audio")]
52 Audio {
54 src: String,
56 title: Option<String>,
58 duration: Option<u64>,
60 poster: Option<String>,
62 cache: Option<bool>,
64 timeout: Option<String>,
66 },
67 #[serde(rename = "video")]
69 Video {
70 src: String,
72 title: Option<String>,
74 duration: Option<u64>,
76 poster: Option<String>,
78 width: Option<u32>,
80 height: Option<u32>,
82 cache: Option<bool>,
84 timeout: Option<String>,
86 },
87 #[serde(rename = "file")]
89 File {
90 src: String,
92 name: Option<String>,
94 poster: Option<String>,
96 cache: Option<bool>,
98 timeout: Option<String>,
100 },
101 #[serde(rename = "quote")]
103 Quote {
104 id: String,
106 forward: Option<bool>,
108 children: Vec<MessageElement>,
110 },
111 #[serde(rename = "author")]
113 Author {
114 id: String,
116 name: Option<String>,
118 avatar: Option<String>,
120 },
121 #[serde(rename = "message")]
123 Message {
124 id: Option<String>,
126 forward: Option<bool>,
128 children: Vec<MessageElement>,
130 },
131
132 #[serde(rename = "strong")]
135 Bold { children: Vec<MessageElement> },
136 #[serde(rename = "em")]
138 Italic { children: Vec<MessageElement> },
139 #[serde(rename = "u")]
141 Underline { children: Vec<MessageElement> },
142 #[serde(rename = "s")]
144 Strikethrough { children: Vec<MessageElement> },
145 #[serde(rename = "spl")]
147 Spoiler { children: Vec<MessageElement> },
148 #[serde(rename = "code")]
150 Code { children: Vec<MessageElement> },
151 #[serde(rename = "sup")]
153 Superscript { children: Vec<MessageElement> },
154 #[serde(rename = "sub")]
156 Subscript { children: Vec<MessageElement> },
157
158 #[serde(rename = "br")]
161 LineBreak,
162 #[serde(rename = "p")]
164 Paragraph { children: Vec<MessageElement> },
165 #[serde(rename = "a")]
167 Link {
168 href: String,
170 children: Vec<MessageElement>,
171 },
172 #[serde(rename = "li")]
177 ListItem { children: Vec<MessageElement> },
178 #[serde(rename = "ul")]
179 UnorderedList { children: Vec<MessageElement> },
180 #[serde(rename = "ol")]
181 OrderedList {
182 start: Option<u64>,
183 reversed: Option<bool>,
184 #[serde(rename = "type")]
185 list_type: Option<String>, children: Vec<MessageElement>,
187 },
188
189 #[serde(rename = "table")]
191 Table { children: Vec<MessageElement> }, #[serde(rename = "thead")]
193 TableHead { children: Vec<MessageElement> }, #[serde(rename = "tbody")]
195 TableBody { children: Vec<MessageElement> }, #[serde(rename = "tfoot")]
197 TableFoot { children: Vec<MessageElement> }, #[serde(rename = "tr")]
199 TableRow { children: Vec<MessageElement> }, #[serde(rename = "th")]
201 TableHeader { children: Vec<MessageElement> },
202 #[serde(rename = "td")]
203 TableCell { children: Vec<MessageElement> },
204
205 #[serde(rename = "button")]
207 Button {
208 id: Option<String>,
210 theme: Option<String>, href: Option<String>,
214 text: Option<String>,
216 disabled: Option<bool>,
218 children: Vec<MessageElement>,
219 },
220
221 #[serde(rename = "span")]
223 Span {
224 style: Option<String>,
225 children: Vec<MessageElement>,
226 },
227 #[serde(rename = "div")]
228 Div {
229 style: Option<String>,
230 children: Vec<MessageElement>,
231 },
232}
233
234#[cfg(test)]
235mod tests {
236 use super::*;
237
238 #[test]
239 fn test_serialize_complex_message() {
240 let msg = vec![
241 MessageElement::Author {
242 id: "user123".to_string(),
243 name: Some("Alice".to_string()),
244 avatar: Some("http://example.com/alice.png".to_string()),
245 },
246 MessageElement::Text {
247 text: "Hello, ".to_string(),
248 },
249 MessageElement::Bold {
250 children: vec![MessageElement::Text {
251 text: "world".to_string(),
252 }],
253 },
254 MessageElement::Image {
255 src: "http://example.com/image.png".to_string(),
256 title: None,
257 width: Some(100),
258 height: Some(100),
259 cache: None,
260 timeout: None,
261 },
262 ];
263
264 let serialized = serde_json::to_string_pretty(&msg).unwrap();
265 println!("{}", serialized);
266 }
267
268 #[test]
269 fn test_serialize_quote_message() {
270 let quote_content = MessageElement::Quote {
271 id: "prev_msg_id_123".to_string(),
272 forward: None,
273 children: vec![
274 MessageElement::Author {
275 id: "user456".to_string(),
276 name: Some("Bob".to_string()),
277 avatar: None,
278 },
279 MessageElement::Text {
280 text: "This was the original message.".to_string(),
281 },
282 ],
283 };
284
285 let main_message = vec![
286 MessageElement::Text {
287 text: "Replying to Bob: ".to_string(),
288 },
289 quote_content,
290 MessageElement::Text {
291 text: "What do you think?".to_string(),
292 },
293 ];
294
295 let serialized = serde_json::to_string_pretty(&main_message).unwrap();
296 println!("{}", serialized);
297 }
298}