wx_sdk/mp/
reply.rs

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}