wx-sdk 0.0.9

A Wechat SDK written in Rust
Documentation
use exile::{Document, Element};
use serde_derive::{Deserialize, Serialize};

use crate::SdkResult;

#[derive(Debug, Serialize, Deserialize)]
pub enum Reply {
    Text(Text),
    Image(Image),
    Voice(Voice),
    Video(Video),
    Music(Music),
    News(News),
    Unknow,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Text {
    pub content: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Image {
    pub media_id: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Voice {
    pub media_id: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Video {
    pub media_id: String,
    pub title: Option<String>,
    pub description: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Music {
    pub thumb_media_id: String,
    pub title: Option<String>,
    pub description: Option<String>,
    pub music_url: Option<String>,
    pub hq_music_url: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct News {
    pub article_count: i32,
    pub articles: Vec<Articles>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Articles {
    pub item: ArticleItem,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ArticleItem {
    #[serde(alias = "Title")]
    pub title: String,

    #[serde(alias = "Description")]
    pub description: String,

    #[serde(alias = "PicUrl")]
    pub pic_url: String,

    #[serde(alias = "Url")]
    pub url: String,
}

pub fn reply_to_xml<S: Into<String>>(reply: Reply, from: S, to: S) -> SdkResult<String> {
    let mut root = Element::from_name("xml");

    let mut to_user_name = Element::from_name("ToUserName");
    to_user_name
        .add_cdata(to)
        .map_err(exile::error::Error::from)?;
    root.add_child(to_user_name);

    let mut from_uesr_name = Element::from_name("FromUserName");
    from_uesr_name
        .add_cdata(from)
        .map_err(exile::error::Error::from)?;
    root.add_child(from_uesr_name);

    let timestamp = std::time::SystemTime::now()
        .duration_since(std::time::SystemTime::UNIX_EPOCH)
        .unwrap_or_default();
    let secs = timestamp.as_secs();
    let mut create_time = Element::from_name("CreateTime");
    create_time.add_text(secs.to_string());
    root.add_child(create_time);

    let mut msg_type = Element::from_name("MsgType");
    let body = match reply {
        Reply::Text(t) => {
            msg_type
                .add_cdata("text")
                .map_err(exile::error::Error::from)?;
            root.add_child(msg_type);
            let mut content = Element::from_name("Content");
            content
                .add_cdata(t.content)
                .map_err(exile::error::Error::from)?;
            content
        }
        Reply::Image(i) => {
            msg_type
                .add_cdata("image")
                .map_err(exile::error::Error::from)?;
            root.add_child(msg_type);
            let mut image = Element::from_name("Iamge");
            let mut media_id = Element::from_name("MediaId");
            media_id
                .add_cdata(i.media_id)
                .map_err(exile::error::Error::from)?;
            image.add_child(media_id);
            image
        }
        Reply::Voice(v) => {
            msg_type
                .add_cdata("voice")
                .map_err(exile::error::Error::from)?;
            root.add_child(msg_type);
            let mut voice = Element::from_name("Voice");
            let mut media_id = Element::from_name("MediaId");
            media_id
                .add_cdata(v.media_id)
                .map_err(exile::error::Error::from)?;
            voice.add_child(media_id);
            voice
        }
        Reply::Video(v) => {
            msg_type
                .add_cdata("video")
                .map_err(exile::error::Error::from)?;
            root.add_child(msg_type);
            let mut video = Element::from_name("Video");
            let mut media_id = Element::from_name("MediaId");
            media_id
                .add_cdata(v.media_id)
                .map_err(exile::error::Error::from)?;
            video.add_child(media_id);
            if let Some(t) = v.title {
                let mut title = Element::from_name("Title");
                title.add_cdata(t).map_err(exile::error::Error::from)?;
                video.add_child(title);
            }
            if let Some(t) = v.description {
                let mut des = Element::from_name("Description");
                des.add_cdata(t).map_err(exile::error::Error::from)?;
                video.add_child(des);
            }
            video
        }
        Reply::Music(m) => {
            msg_type
                .add_cdata("music")
                .map_err(exile::error::Error::from)?;
            root.add_child(msg_type);
            let mut music = Element::from_name("Music");
            let mut thumb_media_id = Element::from_name("ThumbMediaId");
            thumb_media_id
                .add_cdata(m.thumb_media_id)
                .map_err(exile::error::Error::from)?;
            if let Some(t) = m.title {
                let mut title = Element::from_name("Title");
                title.add_cdata(t).map_err(exile::error::Error::from)?;
                music.add_child(title);
            }
            if let Some(t) = m.description {
                let mut des = Element::from_name("Description");
                des.add_cdata(t).map_err(exile::error::Error::from)?;
                music.add_child(des);
            }
            if let Some(t) = m.music_url {
                let mut music_url = Element::from_name("MusicUrl");
                music_url.add_cdata(t).map_err(exile::error::Error::from)?;
                music.add_child(music_url);
            }
            if let Some(t) = m.hq_music_url {
                let mut hq = Element::from_name("HQMusicUrl");
                hq.add_cdata(t).map_err(exile::error::Error::from)?;
                music.add_child(hq);
            }
            music.add_child(thumb_media_id);
            music
        }
        Reply::News(n) => {
            msg_type
                .add_cdata("news")
                .map_err(exile::error::Error::from)?;
            root.add_child(msg_type);

            let mut article_count = Element::from_name("ArticleCount");
            article_count.add_text(n.article_count.to_string());
            root.add_child(article_count);

            let mut articles = Element::from_name("Articles");
            for i in n.articles {
                let mut item = Element::from_name("item");
                let mut title = Element::from_name("Title");
                title
                    .add_cdata(i.item.title)
                    .map_err(exile::error::Error::from)?;
                item.add_child(title);
                let mut des = Element::from_name("Description");
                des.add_cdata(i.item.description)
                    .map_err(exile::error::Error::from)?;
                item.add_child(des);
                let mut pic_url = Element::from_name("PicUrl");
                pic_url
                    .add_cdata(i.item.pic_url)
                    .map_err(exile::error::Error::from)?;
                item.add_child(pic_url);
                let mut url = Element::from_name("Url");
                url.add_cdata(i.item.url)
                    .map_err(exile::error::Error::from)?;
                item.add_child(url);
                articles.add_child(item);
            }
            articles
        }
        Reply::Unknow => unreachable!(),
    };
    root.add_child(body);

    let doc = Document::from_root(root);
    Ok(doc.to_string())
}