use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct TextMessage {
pub to_user_name: String,
pub from_user_name: String,
pub create_time: i64,
pub msg_id: Option<i64>,
pub content: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct ImageMessage {
pub to_user_name: String,
pub from_user_name: String,
pub create_time: i64,
pub msg_id: Option<i64>,
pub pic_url: String,
pub media_id: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VoiceMessage {
pub to_user_name: String,
pub from_user_name: String,
pub create_time: i64,
pub msg_id: Option<i64>,
pub media_id: String,
pub format: String,
pub recognition: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VideoMessage {
pub to_user_name: String,
pub from_user_name: String,
pub create_time: i64,
pub msg_id: Option<i64>,
pub media_id: String,
pub thumb_media_id: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct ShortVideoMessage {
pub to_user_name: String,
pub from_user_name: String,
pub create_time: i64,
pub msg_id: Option<i64>,
pub media_id: String,
pub thumb_media_id: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct LocationMessage {
pub to_user_name: String,
pub from_user_name: String,
pub create_time: i64,
pub msg_id: Option<i64>,
#[serde(rename = "Location_X")]
pub location_x: f64,
#[serde(rename = "Location_Y")]
pub location_y: f64,
pub scale: i32,
pub label: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct LinkMessage {
pub to_user_name: String,
pub from_user_name: String,
pub create_time: i64,
pub msg_id: Option<i64>,
pub title: String,
pub description: String,
pub url: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MsgType {
Text,
Image,
Voice,
Video,
ShortVideo,
Location,
Link,
Event,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub(crate) struct MsgTypePeek {
pub msg_type: String,
}
#[cfg(test)]
mod tests {
use super::*;
use quick_xml::de::from_str;
#[test]
fn test_parse_text_message() {
let xml = r#"<xml>
<ToUserName><![CDATA[gh_test]]></ToUserName>
<FromUserName><![CDATA[oUser123]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[Hello World]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>"#;
let msg: TextMessage = from_str(xml).unwrap();
assert_eq!(msg.to_user_name, "gh_test");
assert_eq!(msg.from_user_name, "oUser123");
assert_eq!(msg.create_time, 1348831860);
assert_eq!(msg.content, "Hello World");
assert_eq!(msg.msg_id, Some(1234567890123456));
}
#[test]
fn test_parse_image_message() {
let xml = r#"<xml>
<ToUserName><![CDATA[gh_test]]></ToUserName>
<FromUserName><![CDATA[oUser123]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<PicUrl><![CDATA[http://example.com/pic.jpg]]></PicUrl>
<MediaId><![CDATA[media_id_123]]></MediaId>
<MsgId>1234567890123456</MsgId>
</xml>"#;
let msg: ImageMessage = from_str(xml).unwrap();
assert_eq!(msg.to_user_name, "gh_test");
assert_eq!(msg.pic_url, "http://example.com/pic.jpg");
assert_eq!(msg.media_id, "media_id_123");
}
#[test]
fn test_parse_location_message() {
let xml = r#"<xml>
<ToUserName><![CDATA[gh_test]]></ToUserName>
<FromUserName><![CDATA[oUser123]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>23.134521</Location_X>
<Location_Y>113.358803</Location_Y>
<Scale>20</Scale>
<Label><![CDATA[Some location]]></Label>
<MsgId>1234567890123456</MsgId>
</xml>"#;
let msg: LocationMessage = from_str(xml).unwrap();
assert!((msg.location_x - 23.134521).abs() < 0.0001);
assert!((msg.location_y - 113.358803).abs() < 0.0001);
assert_eq!(msg.scale, 20);
assert_eq!(msg.label, "Some location");
}
#[test]
fn test_peek_msg_type() {
let xml = r#"<xml>
<ToUserName><![CDATA[gh_test]]></ToUserName>
<FromUserName><![CDATA[oUser123]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[test]]></Content>
</xml>"#;
let peek: MsgTypePeek = from_str(xml).unwrap();
assert_eq!(peek.msg_type, "text");
}
}