znotify 0.2.0

Notify SDK for Rust
Documentation
use std::collections::HashMap;
use std::error::Error;

use reqwest::Client as ReqClient;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use crate::constant::ENDPOINT;
use crate::entity::{Channel, ClientResponse, Message, MessageOptions};


pub struct Client {
    endpoint: String,
    user_id: String,
    client: ReqClient,
}

impl Client {
    fn new(user_id: String, endpoint: Option<String>) -> Self {
        Self {
            endpoint: endpoint.unwrap_or_else(|| String::from(ENDPOINT)),
            user_id,
            client: ReqClient::builder()
                .user_agent(format!("znotify-rs-sdk/{}", env!("CARGO_PKG_VERSION")))
                .build()
                .unwrap(),
        }
    }

    pub async fn create(user_secret: String, endpoint: Option<String>) -> Result<Self, Box<dyn Error>> {
        let client = Self::new(user_secret, endpoint);
        let ret = client.check().await;
        if ret.is_ok() {
            Ok(client)
        } else {
            Err(ret.err().unwrap())
        }
    }

    pub async fn check(&self) -> Result<(), Box<dyn Error>> {
        let resp = self
            .client
            .get(format!("{}/check", self.endpoint))
            .query(&[("user_secret", self.user_id.clone())])
            .send()
            .await?;

        let resp: ClientResponse<bool> = resp.json().await?;
        if !resp.body {
            Err("User secret not valid")?
        }
        Ok(())
    }

    pub async fn send(&self, option: MessageOptions) -> Result<Message, Box<dyn Error>> {
        let content = option.content;
        let title = option.title;
        let long = option.long;
        let priority = option.priority.unwrap_or_default();

        if content.is_empty() {
            Err("Content is required")?
        }

        let mut data = HashMap::new();
        data.insert(
            "title",
            title.unwrap_or_else(|| String::from("Notification")),
        );
        data.insert("content", content);
        data.insert("long", long.unwrap_or_else(String::new));
        data.insert("priority", priority.to_string());

        let resp = self
            .client
            .post(format!("{}/{}/send", self.endpoint, self.user_id))
            .form(&data)
            .send()
            .await?;

        if resp.status().is_success() {
            let resp: ClientResponse<Message> = resp.json().await?;
            Ok(resp.body)
        } else {
            let resp: ClientResponse<String> = resp.json().await?;
            Err(resp.body)?
        }
    }

    pub async fn delete_message(&self, id: String) -> Result<bool, Box<dyn Error>> {
        let client = ReqClient::new();
        let resp = client
            .delete(format!("{}/{}/message/{}", self.endpoint, self.user_id, id))
            .send()
            .await?;

        if resp.status().is_success() {
            let resp: ClientResponse<bool> = resp.json().await?;
            Ok(resp.body)
        } else {
            let resp: ClientResponse<String> = resp.json().await?;
            Err(resp.body)?
        }
    }

    pub async fn create_device(
        &self,
        channel: Channel,
        device_id: String,
        token: Option<String>,
        device_name: Option<String>,
        device_meta: Option<String>,
    ) -> Result<bool, Box<dyn Error>> {
        if !Uuid::parse_str(&device_id).is_ok() {
            Err("Device ID not valid, should be a UUID")?
        }

        let mut data = HashMap::new();
        data.insert("channel", format!("{:?}", channel));
        data.insert("token", token.unwrap_or_default());
        data.insert("device_name", device_name.unwrap_or_default());
        data.insert("device_meta", device_meta.unwrap_or_default());

        let resp = self
            .client
            .put(format!(
                "{}/{}/device/{}",
                self.endpoint, self.user_id, device_id
            ))
            .form(&data)
            .send()
            .await?;

        if resp.status().is_success() {
            let resp: ClientResponse<bool> = resp.json().await?;
            Ok(resp.body)
        } else {
            let resp: ClientResponse<String> = resp.json().await?;
            Err(resp.body)?
        }
    }
}