pnwkit 3.0.0-alpha.15

pnwkit bindings for Rust.
Documentation
use pnwkit_core::{async_trait, Method};
#[cfg(any(feature = "sync", feature = "async", feature = "subscriptions"))]
use pnwkit_core::{Request, Response, ResponseResult};

#[derive(Clone, Debug)]
pub struct Client {
    #[cfg(any(feature = "async", feature = "subscriptions"))]
    client: reqwest::Client,
    #[cfg(feature = "sync")]
    sync_client: reqwest::blocking::Client,
}

impl Client {
    pub fn new() -> Self {
        Client {
            #[cfg(any(feature = "async", feature = "subscriptions"))]
            client: reqwest::Client::new(),
            #[cfg(feature = "sync")]
            sync_client: reqwest::blocking::Client::new(),
        }
    }
}

trait ToReqwestMethod {
    fn to_reqwest_method(&self) -> reqwest::Method;
}

impl ToReqwestMethod for pnwkit_core::Method {
    fn to_reqwest_method(&self) -> reqwest::Method {
        match self {
            Method::Delete => reqwest::Method::DELETE,
            Method::Get => reqwest::Method::GET,
            Method::Patch => reqwest::Method::PATCH,
            Method::Post => reqwest::Method::POST,
            Method::Put => reqwest::Method::PUT,
        }
    }
}

#[cfg(any(feature = "sync", feature = "async", feature = "subscriptions"))]
macro_rules! setup_request {
    ($client:ident, $request:ident) => {{
        let req = $client.request($request.method.to_reqwest_method(), $request.url.clone());
        let req = if let Some(body) = &$request.body {
            req.body(body.clone())
        } else {
            req
        };
        let req = if let Some(headers) = &$request.headers {
            let mut req = req;
            if !headers.authorization.is_empty() {
                req = req.header("Authorization", headers.authorization.clone());
            }
            if let Some(x_api_key) = &headers.x_api_key {
                req = req.header("X-API-Key", x_api_key.clone());
            }
            if let Some(x_bot_key) = &headers.x_bot_key {
                req = req.header("X-Bot-Key", x_bot_key.clone());
            }
            req = req.header("User-Agent", headers.user_agent.clone());
            req
        } else {
            req
        };
        let req = if let Some(content_type) = &$request.content_type {
            req.header("Content-Type", content_type.to_string())
        } else {
            req
        };
        req
    }};
}

#[async_trait]
impl pnwkit_core::Client for Client {
    #[cfg(any(feature = "async", feature = "subscriptions"))]
    async fn request(&self, request: &Request) -> ResponseResult {
        let client = &self.client;
        let req = setup_request!(client, request);
        let res = req.send().await;
        match res {
            Ok(res) => {
                let status = res.status().as_u16();
                let x_ratelimit_reset = res
                    .headers()
                    .get("X-Ratelimit-Reset")
                    .and_then(|v| v.to_str().ok())
                    .and_then(|v| v.parse::<u64>().ok());
                let body = res.text().await;
                match body {
                    Ok(body) => Ok(Response::new(status, body, x_ratelimit_reset)),
                    Err(err) => Err(err.to_string()),
                }
            },
            Err(err) => Err(err.to_string()),
        }
    }

    #[cfg(feature = "sync")]
    fn request_sync(&self, request: &Request) -> ResponseResult {
        let client = &self.sync_client;
        let req = setup_request!(client, request);
        let res = req.send();
        match res {
            Ok(res) => {
                let status = res.status().as_u16();
                let x_ratelimit_reset = res
                    .headers()
                    .get("X-Ratelimit-Reset")
                    .and_then(|v| v.to_str().ok())
                    .and_then(|v| v.parse::<u64>().ok());
                let body = res.text();
                match body {
                    Ok(body) => Ok(Response::new(status, body, x_ratelimit_reset)),
                    Err(err) => Err(err.to_string()),
                }
            },
            Err(err) => Err(err.to_string()),
        }
    }
}