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), Voice(String), 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() }
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
190fn 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}