wx_work/server/
send_message.rs

1use xmltree::{Element, XMLNode};
2
3use super::crypto::{Crypto, Payload};
4use super::error::Result;
5
6#[derive(Debug, Clone)]
7pub struct SendMessage {
8    pub to_user_name: String,
9    pub from_user_name: String,
10    pub msg_ty: SendMessageType,
11}
12
13#[derive(Debug, Clone)]
14#[non_exhaustive]
15pub enum SendMessageType {
16    Text(String),
17    Picture(String), // media_id
18    Voice(String),   // media_id
19    Video(SendVideo),
20    PictureText(Vec<PictureText>),
21}
22
23#[derive(Debug, Clone)]
24pub struct SendVideo {
25    pub media_id: String,
26    pub title: String,
27    pub description: String,
28}
29
30#[derive(Debug, Clone)]
31pub struct PictureText {
32    pub pic_url: String,
33    pub url: String,
34    pub title: String,
35    pub description: String,
36}
37
38impl SendMessage {
39    pub fn new_text(content: String, to_user_name: String, from_user_name: String) -> SendMessage {
40        let msg_ty = SendMessageType::Text(content);
41        SendMessage {
42            to_user_name,
43            from_user_name,
44            msg_ty,
45        }
46    }
47
48    pub fn new_pic(media_id: String, to_user_name: String, from_user_name: String) -> SendMessage {
49        let msg_ty = SendMessageType::Picture(media_id);
50        SendMessage {
51            to_user_name,
52            from_user_name,
53            msg_ty,
54        }
55    }
56
57    pub fn new_voice(
58        media_id: String,
59        to_user_name: String,
60        from_user_name: String,
61    ) -> SendMessage {
62        let msg_ty = SendMessageType::Voice(media_id);
63        SendMessage {
64            to_user_name,
65            from_user_name,
66            msg_ty,
67        }
68    }
69
70    pub fn new_video(
71        video: SendVideo,
72        to_user_name: String,
73        from_user_name: String,
74    ) -> SendMessage {
75        let msg_ty = SendMessageType::Video(video);
76        SendMessage {
77            to_user_name,
78            from_user_name,
79            msg_ty,
80        }
81    }
82
83    pub fn new_pic_text(
84        pt: PictureText,
85        to_user_name: String,
86        from_user_name: String,
87    ) -> SendMessage {
88        Self::new_pic_texts(vec![pt], to_user_name, from_user_name)
89    }
90
91    pub fn new_pic_texts(
92        pts: Vec<PictureText>,
93        to_user_name: String,
94        from_user_name: String,
95    ) -> SendMessage {
96        let msg_ty = SendMessageType::PictureText(pts);
97        SendMessage {
98            to_user_name,
99            from_user_name,
100            msg_ty,
101        }
102    }
103
104    pub(crate) fn serialize(self, timestamp: u64, nonce: u64, crypto: &Crypto) -> Result<String> {
105        let SendMessage {
106            to_user_name,
107            from_user_name,
108            msg_ty,
109        } = self;
110
111        let mut receiver = to_user_name.clone().into_bytes();
112
113        let to = new_node("ToUserName", to_user_name);
114        let from = new_node("FromUserName", from_user_name);
115        let create_time = new_node("CreateTime", format!("{}", timestamp));
116        let mut nodes = vec![to, from, create_time];
117
118        match msg_ty {
119            SendMessageType::Text(content) => {
120                let msg_type = new_node("MsgType", "text".to_string());
121                let content = new_node("Content", content);
122                nodes.push(msg_type);
123                nodes.push(content);
124            }
125            SendMessageType::Picture(media_id) => {
126                let msg_type = new_node("MsgType", "image".to_string());
127                let pic = new_node("MediaId", media_id);
128                let pic_node = XMLNode::Element(new_xml("Image", vec![pic]));
129                nodes.push(msg_type);
130                nodes.push(pic_node);
131                receiver.clear() // TODO: 遗失微信 bug
132            }
133            SendMessageType::Voice(media_id) => {
134                let msg_type = new_node("MsgType", "voice".to_string());
135                let voice = new_node("MediaId", media_id);
136                let voice_node = XMLNode::Element(new_xml("Voice", vec![voice]));
137                nodes.push(msg_type);
138                nodes.push(voice_node);
139            }
140            SendMessageType::Video(v) => {
141                let msg_type = new_node("MsgType", "video".to_string());
142                let media_id = new_node("MediaId", v.media_id);
143                let title = new_node("Title", v.title);
144                let desc = new_node("Description", v.description);
145                let video_node = XMLNode::Element(new_xml("Video", vec![media_id, title, desc]));
146                nodes.push(msg_type);
147                nodes.push(video_node);
148            }
149            SendMessageType::PictureText(pts) => {
150                let msg_type = new_node("MsgType", "news".to_string());
151                let count = new_node("ArticleCount", pts.len().to_string());
152
153                let items = pts
154                    .into_iter()
155                    .map(|pt| {
156                        let title = new_node("Title", pt.title);
157                        let desc = new_node("Description", pt.description);
158                        let pic_url = new_node("PicUrl", pt.pic_url);
159                        let url = new_node("Url", pt.url);
160                        XMLNode::Element(new_xml("item", vec![title, desc, pic_url, url]))
161                    })
162                    .collect();
163                let articles = XMLNode::Element(new_xml("Articles", items));
164                nodes.push(msg_type);
165                nodes.push(count);
166                nodes.push(articles);
167                receiver.clear();
168            }
169        };
170        let xml = new_xml("xml", nodes);
171        let inner = serialize_xml(xml);
172        let payload = Payload {
173            data: inner.into_bytes(),
174            receiver_id: receiver,
175        };
176        let encrypt = crypto.encrypt(&payload);
177        let sign = crypto.sign(encrypt.clone(), timestamp, nonce);
178
179        let encrypt = new_node("Encrypt", encrypt);
180        let msg_sig = new_node("MsgSignature", sign);
181        let timestamp = new_node("TimeStamp", format!("{}", timestamp));
182        let nonce = new_node("Nonce", format!("{}", nonce));
183
184        let xml = new_xml("xml", vec![encrypt, msg_sig, timestamp, nonce]);
185        let ret = serialize_xml(xml);
186        Ok(ret)
187    }
188}
189
190///////////////////////////// helper functions ///////////////////////////////////////////////
191
192fn new_node(name: &str, data: String) -> XMLNode {
193    let node = XMLNode::Text(data);
194    let ret = Element {
195        prefix: None,
196        namespace: None,
197        namespaces: None,
198        name: name.to_string(),
199        attributes: Default::default(),
200        children: vec![node],
201    };
202    XMLNode::Element(ret)
203}
204
205fn new_xml(name: &str, nodes: Vec<XMLNode>) -> Element {
206    Element {
207        prefix: None,
208        namespace: None,
209        namespaces: None,
210        name: name.to_string(),
211        attributes: Default::default(),
212        children: nodes,
213    }
214}
215
216fn serialize_xml(e: Element) -> String {
217    let mut ret = vec![];
218    e.write(&mut ret).unwrap();
219    String::from_utf8(ret).unwrap()
220}