Skip to main content

simple_oauth/common/
twitch.rs

1use serde::{Deserialize, de::Error};
2
3use crate::{
4    SimpleOAuthProvider, UserInfoProvider,
5    types::{OAuthCredentials, TokenAuthMethod, UserInfo},
6};
7
8#[derive(Debug, Clone)]
9pub struct Twitch;
10
11/// User info returned from Twitch Helix API
12#[derive(Debug, Deserialize)]
13struct TwitchUsers {
14    data: Vec<TwitchUserInfo>,
15}
16
17#[derive(Debug, Deserialize)]
18struct TwitchUserInfo {
19    id: String,
20    login: String,
21    display_name: Option<String>,
22    email: Option<String>,
23    profile_image_url: Option<String>,
24}
25
26impl SimpleOAuthProvider for Twitch {
27    fn authorize_url(&self) -> &str {
28        "https://id.twitch.tv/oauth2/authorize"
29    }
30
31    fn token_url(&self) -> &str {
32        "https://id.twitch.tv/oauth2/token"
33    }
34
35    fn token_auth_method(&self) -> TokenAuthMethod {
36        TokenAuthMethod::RequestBody
37    }
38}
39
40impl UserInfoProvider for Twitch {
41    fn user_info_url(&self) -> &str {
42        "https://api.twitch.tv/helix/users"
43    }
44
45    fn user_info_headers(&self, credentials: &OAuthCredentials) -> Vec<(String, String)> {
46        vec![("Client-Id".into(), credentials.client_id.clone())]
47    }
48
49    fn extract_user_info(&self, val: serde_json::Value) -> Result<UserInfo, serde_json::Error> {
50        let users: TwitchUsers = serde_json::from_value(val)?;
51        let user_info = users
52            .data
53            .into_iter()
54            .next()
55            .ok_or_else(|| serde_json::Error::custom("missing Twitch user info"))?;
56
57        Ok(UserInfo {
58            id: user_info.id,
59            name: user_info.display_name,
60            username: Some(user_info.login),
61            email: user_info.email,
62            avatar_url: user_info.profile_image_url,
63            ..Default::default()
64        })
65    }
66}