twitch_highway 0.0.4

Twitch Api reqest Http
Documentation
use std::sync::Arc;

use asknothingx2_util::{
    api::{APIRequest, HeaderBuilder, HeaderMap, Method},
    oauth::{AccessToken, ClientId},
};
use serde::{Deserialize, Serialize};
use url::Url;

use crate::{Error, GetUsersError, Result};

#[derive(Debug)]
pub struct GetUsers {
    access_token: Arc<AccessToken>,
    client_id: Arc<ClientId>,
    url: Arc<Url>,
    id: Vec<String>,
    login: Vec<String>,
}

impl GetUsers {
    pub fn new(access_token: Arc<AccessToken>, client_id: Arc<ClientId>, url: Arc<Url>) -> Self {
        Self {
            access_token,
            client_id,
            url,
            id: Vec::new(),
            login: Vec::new(),
        }
    }
    fn specify_check(&self) -> usize {
        self.id.len() + self.login.len()
    }
    pub fn add_id<S>(mut self, id: S) -> Result<Self>
    where
        S: Into<String>,
    {
        if self.specify_check() == 100 {
            Err(Error::UserError(GetUsersError::AddIdError(format!(
                "error add id curret len: {}",
                self.id.len() + self.login.len()
            ))))
        } else {
            self.id.push(id.into());

            Ok(self)
        }
    }
    pub fn add_ids<S>(mut self, ids: Vec<S>) -> Result<Self>
    where
        S: Into<String>,
    {
        if self.specify_check() + ids.len() > 100 {
            Err(Error::UserError(GetUsersError::AddIdError(format!(
                "error add id curret len: {}",
                self.specify_check() + ids.len()
            ))))
        } else {
            self.id
                .extend(ids.into_iter().map(|x| x.into()).collect::<Vec<String>>());
            Ok(self)
        }
    }
    pub fn add_login<S>(mut self, login: S) -> Result<Self>
    where
        S: Into<String>,
    {
        if self.specify_check() == 100 {
            Err(Error::UserError(GetUsersError::AddIdError(format!(
                "error add id curret len: {}",
                self.specify_check()
            ))))
        } else {
            self.login.push(login.into());
            Ok(self)
        }
    }

    pub fn add_logins<S>(mut self, logins: Vec<S>) -> Result<Self>
    where
        S: Into<String>,
    {
        if self.specify_check() + logins.len() > 100 {
            Err(Error::UserError(GetUsersError::AddIdError(format!(
                "error add id curret len: {}",
                self.specify_check() + logins.len()
            ))))
        } else {
            self.login.extend(
                logins
                    .into_iter()
                    .map(|x| x.into())
                    .collect::<Vec<String>>(),
            );
            Ok(self)
        }
    }
}

impl APIRequest for GetUsers {
    fn method(&self) -> Method {
        Method::GET
    }

    fn headers(&self) -> HeaderMap {
        HeaderBuilder::new()
            .authorization("Bearer", self.access_token.secret().as_str())
            .client_id(self.client_id.as_str())
            .build()
    }

    fn url(&self) -> Url {
        let mut url = Url::parse(self.url.as_str()).unwrap();
        if !self.id.is_empty() {
            let ids = self
                .id
                .clone()
                .into_iter()
                .map(|x| ("id".to_string(), x.to_string()))
                .collect::<Vec<(String, String)>>();

            url.query_pairs_mut().extend_pairs(ids);
        }

        if !self.login.is_empty() {
            let logins = self
                .login
                .clone()
                .into_iter()
                .map(|x| ("login".to_string(), x.to_string()))
                .collect::<Vec<(String, String)>>();

            url.query_pairs_mut().extend_pairs(logins);
        }

        url
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct GetUsersResponse {
    pub data: Vec<User>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct User {
    pub id: String,
    pub login: String,
    pub display_name: String,
    #[serde(rename = "type")]
    pub kind: String,
    pub broadcaster_type: String,
    pub description: String,
    pub profile_image_url: String,
    pub view_count: u64,
    pub created_at: String,
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;

    use asknothingx2_util::{
        api::{APIRequest, HeaderBuilder, Method},
        oauth::{AccessToken, ClientId},
    };
    use url::Url;

    use crate::{api_general, expect_APIRequest, expect_headers};

    use super::GetUsers;

    #[test]
    fn get_users_id() {
        let get_user = api_general!(GetUsers, "https://api.twitch.tv/helix/users");

        let get_user = get_user.add_id("141981764".to_string()).unwrap();

        let expected_headers = expect_headers!();

        expect_APIRequest!(
            GET,
            expected_headers,
            "https://api.twitch.tv/helix/users?id=141981764",
            json = None,
            text = None,
            urlencoded = None,
            get_user
        );
    }

    #[test]
    fn get_users_login() {
        let get_user = api_general!(GetUsers, "https://api.twitch.tv/helix/users");

        let get_user = get_user.add_login("twitchdev".to_string()).unwrap();

        let expected_headers = expect_headers!();

        expect_APIRequest!(
            GET,
            expected_headers,
            "https://api.twitch.tv/helix/users?login=twitchdev",
            json = None,
            text = None,
            urlencoded = None,
            get_user
        );
    }

    #[test]
    fn get_users_id_login() {
        let get_user = api_general!(GetUsers, "https://api.twitch.tv/helix/users");

        let get_user = get_user
            .add_login("twitchdev".to_string())
            .unwrap()
            .add_id("141981764".to_string())
            .unwrap();

        let expected_headers = expect_headers!();

        expect_APIRequest!(
            GET,
            expected_headers,
            "https://api.twitch.tv/helix/users?id=141981764&login=twitchdev",
            json = None,
            text = None,
            urlencoded = None,
            get_user
        );
    }
    #[test]
    fn get_users_login_max() {
        let get_user = api_general!(GetUsers, "https://api.twitch.tv/helix/users");

        let get_user = get_user.add_login("twitchdev".to_string()).unwrap();
        let over_logins = vec!["twitchdev"; 100];
        let get_user = get_user.add_logins(over_logins);

        assert!(get_user.is_err());
    }
}