Skip to content

Commit b0d219d

Browse files
Merge #78
78: add some convenience functions r=Emilgardis a=Emilgardis Co-authored-by: Emil Gardström <emil.gardstrom@gmail.com>
2 parents cd46986 + 29f2547 commit b0d219d

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

src/helix/client_ext.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Convenience functions for [HelixClient]
2+
3+
use crate::helix::{self, ClientRequestError, HelixClient};
4+
use crate::types;
5+
use twitch_oauth2::TwitchToken;
6+
7+
type ClientError<'a, C> = ClientRequestError<<C as crate::HttpClient<'a>>::Error>;
8+
9+
// TODO: Consider moving these into the specific modules where the request is defined. Preferably backed by a macro
10+
11+
impl<'a, C: crate::HttpClient<'a>> HelixClient<'a, C> {
12+
/// Get [User](helix::users::User) from user login
13+
pub async fn get_user_from_login<T>(
14+
&'a self,
15+
login: types::UserName,
16+
token: &T,
17+
) -> Result<Option<helix::users::User>, ClientError<'a, C>>
18+
where
19+
T: TwitchToken + ?Sized,
20+
{
21+
self.req_get(
22+
helix::users::GetUsersRequest::builder()
23+
.login(vec![login])
24+
.build(),
25+
token,
26+
)
27+
.await
28+
.map(|response| response.first())
29+
}
30+
31+
/// Get [User](helix::users::User) from user id
32+
pub async fn get_user_from_id<T>(
33+
&'a self,
34+
id: types::UserId,
35+
token: &T,
36+
) -> Result<Option<helix::users::User>, ClientError<'a, C>>
37+
where
38+
T: TwitchToken + ?Sized,
39+
{
40+
self.req_get(
41+
helix::users::GetUsersRequest::builder()
42+
.id(vec![id])
43+
.build(),
44+
token,
45+
)
46+
.await
47+
.map(|response| response.first())
48+
}
49+
50+
/// Get [ChannelInformation](helix::channels::ChannelInformation) from a broadcasters login
51+
pub async fn get_channel_from_login<T>(
52+
&'a self,
53+
login: types::UserName,
54+
token: &T,
55+
) -> Result<Option<helix::channels::ChannelInformation>, ClientError<'a, C>>
56+
where
57+
T: TwitchToken + ?Sized,
58+
{
59+
if let Some(user) = self.get_user_from_login(login, token).await? {
60+
self.get_channel_from_id(user.id, token).await
61+
} else {
62+
Ok(None)
63+
}
64+
}
65+
66+
/// Get [ChannelInformation](helix::channels::ChannelInformation) from a broadcasters id
67+
pub async fn get_channel_from_id<T>(
68+
&'a self,
69+
id: types::UserId,
70+
token: &T,
71+
) -> Result<Option<helix::channels::ChannelInformation>, ClientError<'a, C>>
72+
where
73+
T: TwitchToken + ?Sized,
74+
{
75+
self.req_get(
76+
helix::channels::GetChannelInformationRequest::builder()
77+
.broadcaster_id(id)
78+
.build(),
79+
token,
80+
)
81+
.await
82+
.map(|response| response.first())
83+
}
84+
}
85+
86+
/*
87+
pub async fn get_xxxx<T>(&'a self, _:_, token: &T) -> Result<_, ClientError<'a, C>> where T: TwitchToken + ?Sized {todo!()}
88+
*/

src/helix/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ use serde::Deserialize;
3131
use std::{convert::TryInto, str::FromStr};
3232
#[cfg(feature = "twitch_oauth2")]
3333
use twitch_oauth2::TwitchToken;
34+
#[cfg(all(feature = "client"))]
35+
#[cfg_attr(nightly, doc(cfg(all(feature = "client", feature = "helix"))))]
36+
pub mod client_ext;
3437

3538
pub mod bits;
3639
pub mod channels;
@@ -74,6 +77,23 @@ pub use twitch_oauth2::Scope;
7477
/// ```
7578
///
7679
/// See [`HttpClient`][crate::HttpClient] for implemented http clients, you can also define your own if needed.
80+
///
81+
/// # Examples
82+
///
83+
/// Get a [user](users::User) from their login name.
84+
///
85+
/// ```rust,no_run
86+
/// # #[tokio::main]
87+
/// # async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
88+
/// # pub mod reqwest {pub type Client = twitch_api2::client::DummyHttpClient;}
89+
/// # let token = twitch_oauth2::AccessToken::new("validtoken".to_string());
90+
/// # let token = twitch_oauth2::UserToken::from_existing(twitch_oauth2::dummy_http_client, token, None, None).await?;
91+
/// use twitch_api2::helix::{HelixClient, users::User};
92+
/// let helix: HelixClient<'static, reqwest::Client> = HelixClient::default();
93+
/// let user: Option<User> = helix
94+
/// .get_user_from_login("justintv".to_string(), &token).await.unwrap();
95+
/// # Ok(()) }
96+
/// ```
7797
#[cfg(all(feature = "client"))]
7898
#[cfg_attr(nightly, doc(cfg(all(feature = "client", feature = "helix"))))]
7999
#[derive(Clone)]
@@ -659,6 +679,15 @@ where
659679
pub request: Option<R>,
660680
}
661681

682+
impl<R, D, T> Response<R, D>
683+
where
684+
R: Request<Response = D>,
685+
D: IntoIterator<Item = T> + PartialEq + serde::de::DeserializeOwned,
686+
{
687+
/// Get first result of this response.
688+
pub fn first(self) -> Option<T> { self.data.into_iter().next() }
689+
}
690+
662691
#[cfg(feature = "client")]
663692
impl<R, D> Response<R, D>
664693
where

src/lib.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,31 @@
4444
//! # }
4545
//! ```
4646
//!
47+
//! There is also a convenience function for accesssing channel information with a specified login name
48+
//!
49+
//! ```rust,no_run
50+
//! # use twitch_api2::{TwitchClient, helix::channels::GetChannelInformationRequest};
51+
//! # use twitch_oauth2::{AppAccessToken, Scope, TwitchToken, tokens::errors::TokenError};
52+
//!
53+
//! # #[tokio::main]
54+
//! # async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
55+
//! # let surf_http_client = twitch_oauth2::dummy_http_client; // This is only here to fool doc tests
56+
//! # let client_id = twitch_oauth2::ClientId::new("validclientid".to_string());
57+
//! # let client_secret = twitch_oauth2::ClientSecret::new("validclientsecret".to_string());
58+
//! # let token =
59+
//! # match AppAccessToken::get_app_access_token(surf_http_client, client_id, client_secret, Scope::all()).await {
60+
//! # Ok(t) => t,
61+
//! # Err(TokenError::Request(e)) => panic!("got error: {:?}", e),
62+
//! # Err(e) => panic!(e),
63+
//! # };
64+
//! let client = TwitchClient::new();
65+
//! # let _: &TwitchClient<twitch_api2::DummyHttpClient> = &client;
66+
//!
67+
//! println!("{:?}", &client.helix.get_channel_from_login("twitch".to_string(), &token).await?.unwrap().title);
68+
//! # Ok(())
69+
//! # }
70+
//! ```
71+
//!
4772
//! # Features
4873
//!
4974
//! This crate provides almost no functionality by default, only exposing [`types`]. To enable more features, refer to below table.

0 commit comments

Comments
 (0)