twitch_highway 0.4.1

Twitch API
Documentation
use chrono::{DateTime, SecondsFormat, Utc};

use crate::{
    clips::{ClipsInfoResponse, CreateClipsResponse},
    request::TwitchAPIRequest,
    types::{
        constants::{
            AFTER, BROADCASTER_ID, CLIPS, ENDED_AT, FIRST, GAME_ID, ID, IS_FEATURED, STARTED_AT,
        },
        BroadcasterId, ClipId, GameId,
    },
    TwitchAPI,
};

define_request_builder! {
    #[derive(Debug)]
    CreateClipBuilder<'a> {
        req: {broadcaster_id: &'a BroadcasterId [key = BROADCASTER_ID]},
        opts: {
            title: &'a str,
            duration: f64 [convert = precision1]
        }
    } -> CreateClipsResponse;
    endpoint: CreateClip,
    method: POST,
    path: [CLIPS],

}

#[derive(Debug)]
pub enum ClipsQuery<'a> {
    Broadcaster(&'a BroadcasterId),
    Game(&'a GameId),
    Ids(&'a [ClipId]),
}

#[derive(Debug)]
pub struct GetClipsBuilder<'a> {
    api: &'a TwitchAPI,
    query: ClipsQuery<'a>,
    started_at: Option<&'a DateTime<Utc>>,
    ended_at: Option<&'a DateTime<Utc>>,
    is_featured: Option<bool>,
    first: Option<u8>,
    after: Option<&'a str>,
}

impl<'a> GetClipsBuilder<'a> {
    pub fn by_broadcaster_id(api: &'a TwitchAPI, broadcaster_id: &'a BroadcasterId) -> Self {
        Self {
            api,
            query: ClipsQuery::Broadcaster(broadcaster_id),
            started_at: None,
            ended_at: None,
            is_featured: None,
            first: None,
            after: None,
        }
    }

    pub fn by_game_id(api: &'a TwitchAPI, game_id: &'a GameId) -> Self {
        Self {
            api,
            query: ClipsQuery::Game(game_id),
            started_at: None,
            ended_at: None,
            is_featured: None,
            first: None,
            after: None,
        }
    }

    pub fn by_ids(api: &'a TwitchAPI, ids: &'a [ClipId]) -> Self {
        Self {
            api,
            query: ClipsQuery::Ids(ids),
            started_at: None,
            ended_at: None,
            is_featured: None,
            first: None,
            after: None,
        }
    }

    pub fn started_at(mut self, value: &'a DateTime<Utc>) -> Self {
        self.started_at = Some(value);
        self
    }
    pub fn ended_at(mut self, value: &'a DateTime<Utc>) -> Self {
        self.ended_at = Some(value);
        self
    }
    pub fn is_featured(mut self, value: bool) -> Self {
        self.is_featured = Some(value);
        self
    }
    pub fn first(mut self, value: u8) -> Self {
        self.first = Some(value);
        self
    }
    pub fn after(mut self, value: &'a str) -> Self {
        self.after = Some(value);
        self
    }

    pub fn build(self) -> TwitchAPIRequest<ClipsInfoResponse> {
        let mut url = self.api.build_url();

        url.path_segments_mut().unwrap().extend(&[CLIPS]);

        let mut query = url.query_pairs_mut();

        match self.query {
            ClipsQuery::Broadcaster(id) => {
                query.append_pair(BROADCASTER_ID, id);
            }
            ClipsQuery::Game(id) => {
                query.append_pair(GAME_ID, id);
            }
            ClipsQuery::Ids(ids) => {
                query.extend_pairs(ids.iter().map(|id| (ID, id)));
            }
        }

        if let Some(started_at) = self.started_at {
            query.append_pair(
                STARTED_AT,
                &started_at.to_rfc3339_opts(SecondsFormat::Secs, true),
            );
        }

        if let Some(ended_at) = self.ended_at {
            query.append_pair(
                ENDED_AT,
                &ended_at.to_rfc3339_opts(SecondsFormat::Secs, true),
            );
        }

        if let Some(is_featured) = self.is_featured {
            query.append_pair(IS_FEATURED, &is_featured.to_string());
        }

        if let Some(first) = self.first {
            query.append_pair(FIRST, &first.to_string());
        }

        if let Some(after) = self.after {
            query.append_pair(AFTER, after);
        }

        drop(query);

        TwitchAPIRequest::new(
            crate::request::EndpointType::GetClips,
            url,
            reqwest::Method::GET,
            self.api.default_headers(),
            None,
            self.api.client.clone(),
        )
    }

    pub async fn send(self) -> Result<reqwest::Response, crate::Error> {
        self.build().send().await
    }

    pub async fn json(self) -> Result<ClipsInfoResponse, crate::Error> {
        self.build().json().await
    }
}