1use roxmltree::{Document, Node};
2
3use crate::{error::SdkError, SdkResult};
4
5use msg_image::ImageMessage;
6use msg_text::TextMessage;
7
8use self::{
9 msg_event::EventMessage, msg_link::LinkMessage, msg_location::LocationMessage,
10 msg_video::VideoMessage, msg_voice::VoiceMessage,
11};
12
13pub mod crypto;
14pub mod msg_event;
15pub mod msg_image;
16pub mod msg_link;
17pub mod msg_location;
18pub mod msg_text;
19pub mod msg_video;
20pub mod msg_voice;
21pub mod signature;
22pub mod xmlutil;
23
24const MSG_TEXT: &'static str = "text";
25const MSG_IMAGE: &'static str = "image";
26const MSG_VOICE: &'static str = "voice";
27const MSG_VIDEO: &'static str = "video";
28const MSG_SHORTVIDEO: &'static str = "shortvideo";
29const MSG_LOCATION: &'static str = "location"; const MSG_LINK: &'static str = "link";
31const MSG_EVENT: &'static str = "event";
32
33pub trait ReceivedMessageParser {
34 type ReceivedMessage;
35 fn from_xml(node: &Node) -> SdkResult<Self::ReceivedMessage>;
36}
37
38pub struct ReceivedEvent {
39 pub from: String,
40
41 pub to: String,
42
43 pub create_time: u64,
44
45 pub msg_type: String,
46
47 pub body: ReceivedMessage,
48}
49
50pub enum ReceivedMessage {
51 UnhandledMessage(String),
52 Text(TextMessage),
53 Image(ImageMessage),
54 Voice(VoiceMessage),
55 Video(VideoMessage),
56 ShortVideo(VideoMessage),
57 Location(LocationMessage),
58 Link(LinkMessage),
59 Event(EventMessage),
60}
61
62impl ReceivedEvent {
63 pub fn parse(input: &str) -> SdkResult<Self> {
64 let xml = Document::parse(input)?;
65 let root = xml.root();
66 let msg_type = root
67 .descendants()
68 .find(|n| n.has_tag_name("MsgType"))
69 .map(|n| n.text())
70 .flatten()
71 .ok_or_else(|| SdkError::InvalidParams("parse xml need `MsgType` params".to_owned()))?;
72 let from = root
73 .descendants()
74 .find(|n| n.has_tag_name("FromUserName"))
75 .map(|n| n.text())
76 .flatten()
77 .ok_or_else(|| {
78 SdkError::InvalidParams("parse xml need `FromUserName` params".to_owned())
79 })?;
80 let to = root
81 .descendants()
82 .find(|n| n.has_tag_name("ToUserName"))
83 .map(|n| n.text())
84 .flatten()
85 .ok_or_else(|| {
86 SdkError::InvalidParams("parse xml need `ToUserName` params".to_owned())
87 })?;
88 let create_time = root
89 .descendants()
90 .find(|n| n.has_tag_name("CreateTime"))
91 .map(|n| n.text())
92 .flatten()
93 .ok_or_else(|| {
94 SdkError::InvalidParams("parse xml need CreateTime params".to_owned())
95 })?;
96 let create_time = create_time.parse::<u64>().map_err(|_e| {
97 SdkError::InvalidParams(
98 "Parse XML msg from wechat error: tag `CreateTime` should be number".to_string(),
99 )
100 })?;
101
102 let body = match msg_type {
103 MSG_TEXT => ReceivedMessage::Text(TextMessage::from_xml(&root)?),
104 MSG_IMAGE => ReceivedMessage::Image(ImageMessage::from_xml(&root)?),
105 MSG_VOICE => ReceivedMessage::Voice(VoiceMessage::from_xml(&root)?),
106 MSG_VIDEO | MSG_SHORTVIDEO => {
107 if msg_type == MSG_VIDEO {
108 ReceivedMessage::Video(VideoMessage::from_xml(&root)?)
109 } else {
110 ReceivedMessage::ShortVideo(VideoMessage::from_xml(&root)?)
111 }
112 }
113 MSG_LOCATION => ReceivedMessage::Location(LocationMessage::from_xml(&root)?),
114 MSG_LINK => ReceivedMessage::Link(LinkMessage::from_xml(&root)?),
115 MSG_EVENT => ReceivedMessage::Event(EventMessage::from_xml(&root)?),
116 _ => ReceivedMessage::UnhandledMessage(format!(
117 "Havent' handle for this message type `{}`",
118 msg_type
119 )),
120 };
121 Ok(ReceivedEvent {
122 from: from.to_owned(),
123 to: to.to_owned(),
124 msg_type: msg_type.to_owned(),
125 create_time,
126 body,
127 })
128 }
129}