From be68a7da226743edbce5b52e506d9083e2859578 Mon Sep 17 00:00:00 2001 From: David Blajda Date: Sun, 16 Dec 2018 19:31:45 +0000 Subject: Prototype of a trait based client --- src/helix/endpoints.rs | 68 +++++++++++++++-------- src/helix/mod.rs | 146 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 185 insertions(+), 29 deletions(-) (limited to 'src/helix') diff --git a/src/helix/endpoints.rs b/src/helix/endpoints.rs index bb61ae9..80b4ebb 100644 --- a/src/helix/endpoints.rs +++ b/src/helix/endpoints.rs @@ -2,6 +2,7 @@ use futures::future::Future; use reqwest::header; use reqwest::r#async::{RequestBuilder}; use reqwest::r#async::Client as ReqwestClient; +use std::sync::Arc; use super::models::{DataContainer, PaginationContainer, User, Video, Clip}; use super::Client; @@ -13,15 +14,51 @@ const API_DOMAIN: &'static str = "api.twitch.tv"; * connections. */ -impl Client { +use super::super::GetRequest; +use super::super::GetRequestRef; +use std::marker::PhantomData; + +use super::HelixClient; - fn apply_standard_headers(&self, request: RequestBuilder) - -> RequestBuilder - { - let client_header = header::HeaderValue::from_str(&self.inner.id).unwrap(); +fn apply_standard_headers(client: &Box, request: RequestBuilder) + -> RequestBuilder +{ + let client_header = header::HeaderValue::from_str(client.id()).unwrap(); + + request.header("Client-ID", client_header) +} - request.header("Client-ID", client_header) +pub fn clip(client: &Box, id: &str) + -> impl Future, Error=reqwest::Error> +{ + let url = + String::from("https://") + + API_DOMAIN + "/helix/clips" + "?id=" + id; + + + let request = client.client().get(&url); + let request = apply_standard_headers(client, request); + + request + .send() + .map(|mut res| { + println!("{:?}", res); + res.json::>() + }) + .and_then(|json| json) + /* + GetRequest { + inner: Arc::new(GetRequestRef { + url: url.to_owned(), + returns: PhantomData, + }) } + */ +} + +impl Client { + + /* pub fn users( @@ -90,22 +127,5 @@ impl Client { } */ - pub fn clip(&self, id: &str) - -> impl Future, Error=reqwest::Error> - { - let url = - String::from("https://") + - API_DOMAIN + "/helix/clips" + "?id=" + id; - - let request = self.inner.client.get(&url); - let request = self.apply_standard_headers(request); - - request - .send() - .map(|mut res| { - println!("{:?}", res); - res.json::>() - }) - .and_then(|json| json) - } } + diff --git a/src/helix/mod.rs b/src/helix/mod.rs index d8c9952..50412fb 100644 --- a/src/helix/mod.rs +++ b/src/helix/mod.rs @@ -1,15 +1,155 @@ -use std::sync::Arc; +use futures::future::Future; +use std::sync::{Arc, Mutex}; use reqwest::r#async::Client as ReqwestClient; pub use super::types; pub mod endpoints; pub mod models; +use std::collections::HashSet; + #[derive(Clone)] pub struct Client { inner: Arc } +struct ClientRef { + id: String, + client: ReqwestClient, +} + +use self::models::{DataContainer, PaginationContainer, Clip}; + +pub trait UsersEndpoint {} +pub trait VideosEndpoint {} + +pub trait ClipsEndpointTrait { + fn clip(&self, id: &str) -> Box, Error=reqwest::Error> + Send>; +} + +pub trait AuthEndpoint {} + +pub struct ClipsEndpoint { + client: Box +} + +impl ClipsEndpointTrait for ClipsEndpoint { + fn clip(&self, id: &str) -> Box, Error=reqwest::Error> + Send> { + use self::endpoints::clip; + Box::new(clip(&self.client, id)) + } + +} + +pub trait HelixClient { + //fn users(&self) -> Box; + //fn videos(&self) -> Box; + fn clips(&self) -> Box; + //fn auth(&self) -> Box; + + fn id(&self) -> &str; + fn authenticated(&self) -> bool; + fn with_auth(self, secret: &str) -> AuthClientBuilder; + fn unauth(self) -> Box; + + /* I don't want to expose this. Temp work around*/ + fn client(&self) -> &ReqwestClient; +} + +impl HelixClient for Client { + + fn clips(&self) -> Box { + Box::new(ClipsEndpoint { + client: Box::new(self.clone()) + }) + } + + fn id(&self) -> &str { + &self.inner.id + } + + fn authenticated(&self) -> bool { + false + } + + fn with_auth(self, secret: &str) -> AuthClientBuilder { + AuthClientBuilder::new(Box::new(self), secret) + } + + fn unauth(self) -> Box { + Box::new(self) + } + + fn client(&self) -> &ReqwestClient { + &self.inner.client + } +} + + +#[derive(Clone)] +pub struct AuthClient { + +} + +pub struct AuthClientBuilder { + scopes: HashSet, + secret: String, + client: Box, + /*If the user supplies a token, + * then we can skip fetching it from the server and are authenticated + */ + token: Option, +} + +impl AuthClientBuilder { + pub fn new(client: Box, secret: &str) -> AuthClientBuilder { + AuthClientBuilder { + scopes: HashSet::new(), + secret: secret.to_owned(), + client: client, + token: None, + } + } + + /* + pub fn build(self) -> Box { + AuthClient { + } + } + */ + + pub fn scope(mut self, scope: Scope) -> AuthClientBuilder { + let scopes = &mut self.scopes; + scopes.insert(scope); + self + } + + pub fn scopes(mut self, scopes: Vec) -> AuthClientBuilder { + let _scopes = &mut self.scopes; + for scope in scopes { + _scopes.insert(scope); + } + self + } + + pub fn token(self, token: &str) -> AuthClientBuilder { + self + } +} + + +#[derive(PartialEq, Hash, Eq)] +pub enum Scope { + AnalyticsReadExtensions, + AnalyticsReadGames, + BitsRead, + ClipsEdit, + UserEdit, + UserEditBroadcast, + UserReadBroadcast, + UserReadEmail, +} + impl Client { pub fn new(id: &str) -> Client { Client { @@ -31,10 +171,6 @@ impl Client { } } -struct ClientRef { - id: String, - client: ReqwestClient, -} /* -- cgit v1.2.3