mob_push 0.2.1

notify pusher using Mob Push
Documentation
use std::borrow::Cow;

use serde::{ser::SerializeStruct, Serialize};

use crate::{
    config::get_config,
    push_notify::{
        android::AndroidNotify, ios::IosNotify, Notify, NotifySerialize, SerializeInformation,
    },
    user_subscribe::UserMobId,
    PushEntity, PushForward,
};

pub struct PushTarget {
    pub target_user: Vec<String>,
}

impl PushTarget {
    pub fn new(user_iter: &mut impl Iterator<Item = impl UserMobId>) -> Option<Self> {
        let vec = user_iter.take(1000)
        .map(|user|user.get_mob_id().to_string())
        .collect::<Vec<_>>();
    
        if vec.is_empty() {
            None
        } else {
            Some(Self { target_user: vec })
        }
    }
}

impl Serialize for PushTarget {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut push_target = serializer.serialize_struct("pushTarget", 2)?;

        push_target.serialize_field("target", &4)?;
        push_target.serialize_field("rids", &self.target_user)?;

        push_target.end()
    }
}

pub struct Forward(PushForward);

impl Forward {
    pub fn new<T: PushEntity>(data: &T) -> Self {
        let mut push_forward = PushForward::HomePage;
        data.push_forward(&mut push_forward);

        Self(push_forward)
    }
}

impl Serialize for Forward {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut s = serializer.serialize_struct("pushForward", self.0.serialize_field())?;
        NotifySerialize::serialize::<S>(&self.0, &mut s)?;
        s.end()
    }
}

pub struct PushNotify<'p, A = Notify<AndroidNotify>, I = Notify<IosNotify>>
where
    A: Serialize + 'static,
    I: Serialize + 'static,
{
    body: &'p str,
    title: Cow<'p, str>,
    android_notify: A,
    ios_notify: I,
}

impl<'p> PushNotify<'p> {
    pub fn new_with_builder<T: PushEntity>(data: &'p T) -> Self {
        let mut android_notify = AndroidNotify::default().into_notify();
        data.android_notify(&mut android_notify);
        let mut ios_notify = IosNotify::default().into_notify();
        data.ios_notify(&mut ios_notify);

        Self {
            body: data.get_send_content().as_ref(),
            title: data.get_title(),
            android_notify,
            ios_notify,
        }
    }
}

impl<'p> Serialize for PushNotify<'p> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut len = 4;
        if self.android_notify.need_serialize() {
            len += 1;
        }
        if self.ios_notify.need_serialize() {
            len += 1;
        }

        let mut notify = serializer.serialize_struct("PushNotify", len)?;

        notify.serialize_field("plats", &[1, 2])?;
        notify.serialize_field("content", &self.body)?;
        notify.serialize_field("type", &1)?;
        notify.serialize_field("title", &self.title)?;

        if self.android_notify.need_serialize() {
            notify.serialize_field("androidNotify", &self.android_notify)?;
        }
        if self.ios_notify.need_serialize() {
            notify.serialize_field("iosNotify", &self.ios_notify)?;
        }

        notify.end()
    }
}

pub(crate) struct CreatePush<'p> {
    pub push_target: PushTarget,
    pub push_notify: PushNotify<'p>,
    pub push_forward: Forward,
}

impl<'p> Serialize for CreatePush<'p> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut push_body = serializer.serialize_struct("CreatePush", 4)?;

        push_body.serialize_field("source", &"webapi")?;
        push_body.serialize_field("appkey", &get_config().key)?;
        push_body.serialize_field("pushTarget", &self.push_target)?;
        push_body.serialize_field("pushNotify", &self.push_notify)?;
        push_body.serialize_field("pushForward", &self.push_forward)?;

        push_body.end()
    }
}

#[derive(Debug, serde::Deserialize)]
pub(crate) struct Respond {
    pub(crate) status: u16,
    #[serde(rename = "res")]
    pub(crate) _res: Option<ResBody>,
    pub(crate) error: Option<String>,
}
#[derive(Debug, serde::Deserialize)]
pub(crate) struct ResBody {
    #[serde(rename = "batchId")]
    pub(crate) _batch_id: String,
}

#[cfg(test)]
mod test_serde {
    use std::borrow::Cow;

    use crate::{
        config::load_from_test,
        push_notify::{android::AndroidNotify, ios::IosNotify, SerializeInformation},
    };

    use super::CreatePush;

    #[test]
    fn test_serde() {
        load_from_test();

        let c = CreatePush {
            push_target: super::PushTarget {
                target_user: vec!["abc".to_string(), "cdde".to_string()],
            },
            push_notify: super::PushNotify {
                body: &String::from(r#"{"aab":11}"#),
                android_notify: AndroidNotify::default().into_notify(),
                ios_notify: IosNotify::default().into_notify(),
                title: Cow::Borrowed("12345"),
            },
            push_forward: super::Forward(crate::PushForward::HomePage),
        };

        let string = serde_json::to_string_pretty(&c).unwrap();

        println!("{string}")
    }
}