1use exile::{Document, Element};
2use serde_derive::{Deserialize, Serialize};
3
4use crate::SdkResult;
5
6#[derive(Debug, Serialize, Deserialize)]
7pub enum Reply {
8 Text(Text),
9 Image(Image),
10 Voice(Voice),
11 Video(Video),
12 Music(Music),
13 News(News),
14 Unknow,
15}
16#[derive(Debug, Serialize, Deserialize)]
17pub struct Text {
18 pub content: String,
19}
20#[derive(Debug, Serialize, Deserialize)]
21pub struct Image {
22 pub media_id: String,
23}
24
25#[derive(Debug, Serialize, Deserialize)]
26pub struct Voice {
27 pub media_id: String,
28}
29
30#[derive(Debug, Serialize, Deserialize)]
31pub struct Video {
32 pub media_id: String,
33 pub title: Option<String>,
34 pub description: Option<String>,
35}
36
37#[derive(Debug, Serialize, Deserialize)]
38pub struct Music {
39 pub thumb_media_id: String,
40 pub title: Option<String>,
41 pub description: Option<String>,
42 pub music_url: Option<String>,
43 pub hq_music_url: Option<String>,
44}
45
46#[derive(Debug, Serialize, Deserialize)]
47pub struct News {
48 pub article_count: i32,
49 pub articles: Vec<Articles>,
50}
51
52#[derive(Debug, Serialize, Deserialize)]
53pub struct Articles {
54 pub item: ArticleItem,
55}
56
57#[derive(Debug, Serialize, Deserialize)]
58pub struct ArticleItem {
59 #[serde(alias = "Title")]
60 pub title: String,
61
62 #[serde(alias = "Description")]
63 pub description: String,
64
65 #[serde(alias = "PicUrl")]
66 pub pic_url: String,
67
68 #[serde(alias = "Url")]
69 pub url: String,
70}
71
72pub fn reply_to_xml<S: Into<String>>(reply: Reply, from: S, to: S) -> SdkResult<String> {
73 let mut root = Element::from_name("xml");
74
75 let mut to_user_name = Element::from_name("ToUserName");
76 to_user_name
77 .add_cdata(to)
78 .map_err(exile::error::Error::from)?;
79 root.add_child(to_user_name);
80
81 let mut from_uesr_name = Element::from_name("FromUserName");
82 from_uesr_name
83 .add_cdata(from)
84 .map_err(exile::error::Error::from)?;
85 root.add_child(from_uesr_name);
86
87 let timestamp = std::time::SystemTime::now()
88 .duration_since(std::time::SystemTime::UNIX_EPOCH)
89 .unwrap_or_default();
90 let secs = timestamp.as_secs();
91 let mut create_time = Element::from_name("CreateTime");
92 create_time.add_text(secs.to_string());
93 root.add_child(create_time);
94
95 let mut msg_type = Element::from_name("MsgType");
96 let body = match reply {
97 Reply::Text(t) => {
98 msg_type
99 .add_cdata("text")
100 .map_err(exile::error::Error::from)?;
101 root.add_child(msg_type);
102 let mut content = Element::from_name("Content");
103 content
104 .add_cdata(t.content)
105 .map_err(exile::error::Error::from)?;
106 content
107 }
108 Reply::Image(i) => {
109 msg_type
110 .add_cdata("image")
111 .map_err(exile::error::Error::from)?;
112 root.add_child(msg_type);
113 let mut image = Element::from_name("Iamge");
114 let mut media_id = Element::from_name("MediaId");
115 media_id
116 .add_cdata(i.media_id)
117 .map_err(exile::error::Error::from)?;
118 image.add_child(media_id);
119 image
120 }
121 Reply::Voice(v) => {
122 msg_type
123 .add_cdata("voice")
124 .map_err(exile::error::Error::from)?;
125 root.add_child(msg_type);
126 let mut voice = Element::from_name("Voice");
127 let mut media_id = Element::from_name("MediaId");
128 media_id
129 .add_cdata(v.media_id)
130 .map_err(exile::error::Error::from)?;
131 voice.add_child(media_id);
132 voice
133 }
134 Reply::Video(v) => {
135 msg_type
136 .add_cdata("video")
137 .map_err(exile::error::Error::from)?;
138 root.add_child(msg_type);
139 let mut video = Element::from_name("Video");
140 let mut media_id = Element::from_name("MediaId");
141 media_id
142 .add_cdata(v.media_id)
143 .map_err(exile::error::Error::from)?;
144 video.add_child(media_id);
145 if let Some(t) = v.title {
146 let mut title = Element::from_name("Title");
147 title.add_cdata(t).map_err(exile::error::Error::from)?;
148 video.add_child(title);
149 }
150 if let Some(t) = v.description {
151 let mut des = Element::from_name("Description");
152 des.add_cdata(t).map_err(exile::error::Error::from)?;
153 video.add_child(des);
154 }
155 video
156 }
157 Reply::Music(m) => {
158 msg_type
159 .add_cdata("music")
160 .map_err(exile::error::Error::from)?;
161 root.add_child(msg_type);
162 let mut music = Element::from_name("Music");
163 let mut thumb_media_id = Element::from_name("ThumbMediaId");
164 thumb_media_id
165 .add_cdata(m.thumb_media_id)
166 .map_err(exile::error::Error::from)?;
167 if let Some(t) = m.title {
168 let mut title = Element::from_name("Title");
169 title.add_cdata(t).map_err(exile::error::Error::from)?;
170 music.add_child(title);
171 }
172 if let Some(t) = m.description {
173 let mut des = Element::from_name("Description");
174 des.add_cdata(t).map_err(exile::error::Error::from)?;
175 music.add_child(des);
176 }
177 if let Some(t) = m.music_url {
178 let mut music_url = Element::from_name("MusicUrl");
179 music_url.add_cdata(t).map_err(exile::error::Error::from)?;
180 music.add_child(music_url);
181 }
182 if let Some(t) = m.hq_music_url {
183 let mut hq = Element::from_name("HQMusicUrl");
184 hq.add_cdata(t).map_err(exile::error::Error::from)?;
185 music.add_child(hq);
186 }
187 music.add_child(thumb_media_id);
188 music
189 }
190 Reply::News(n) => {
191 msg_type
192 .add_cdata("news")
193 .map_err(exile::error::Error::from)?;
194 root.add_child(msg_type);
195
196 let mut article_count = Element::from_name("ArticleCount");
197 article_count.add_text(n.article_count.to_string());
198 root.add_child(article_count);
199
200 let mut articles = Element::from_name("Articles");
201 for i in n.articles {
202 let mut item = Element::from_name("item");
203 let mut title = Element::from_name("Title");
204 title
205 .add_cdata(i.item.title)
206 .map_err(exile::error::Error::from)?;
207 item.add_child(title);
208 let mut des = Element::from_name("Description");
209 des.add_cdata(i.item.description)
210 .map_err(exile::error::Error::from)?;
211 item.add_child(des);
212 let mut pic_url = Element::from_name("PicUrl");
213 pic_url
214 .add_cdata(i.item.pic_url)
215 .map_err(exile::error::Error::from)?;
216 item.add_child(pic_url);
217 let mut url = Element::from_name("Url");
218 url.add_cdata(i.item.url)
219 .map_err(exile::error::Error::from)?;
220 item.add_child(url);
221 articles.add_child(item);
222 }
223 articles
224 }
225 Reply::Unknow => unreachable!(),
226 };
227 root.add_child(body);
228
229 let doc = Document::from_root(root);
230 Ok(doc.to_string())
231}