Skip to main content

simple_oauth/common/
discord.rs

1use serde::Deserialize;
2
3use crate::{SimpleOAuthProvider, UserInfoProvider, types::UserInfo};
4
5#[derive(Debug, Clone)]
6pub struct Discord;
7
8/// User info returned from Discord API
9#[derive(Debug, Deserialize)]
10struct DiscordUserInfo {
11    id: String,
12    username: String,
13    global_name: Option<String>,
14    email: Option<String>,
15    verified: Option<bool>,
16    avatar: Option<String>,
17}
18
19impl SimpleOAuthProvider for Discord {
20    fn authorize_url(&self) -> &str {
21        "https://discord.com/oauth2/authorize"
22    }
23
24    fn token_url(&self) -> &str {
25        "https://discord.com/api/oauth2/token"
26    }
27
28    fn default_scopes(&self) -> &'static [&'static str] {
29        &["identify"]
30    }
31}
32
33impl UserInfoProvider for Discord {
34    fn user_info_url(&self) -> &str {
35        "https://discord.com/api/v9/users/@me"
36    }
37
38    fn extract_user_info(&self, val: serde_json::Value) -> Result<UserInfo, serde_json::Error> {
39        let user_info: DiscordUserInfo = serde_json::from_value(val)?;
40        let avatar_url = user_info.avatar.as_ref().map(|avatar| {
41            format!(
42                "https://cdn.discordapp.com/avatars/{}/{}.png",
43                user_info.id, avatar
44            )
45        });
46
47        Ok(UserInfo {
48            id: user_info.id,
49            email: user_info.email,
50            email_verified: user_info.verified,
51            name: user_info.global_name,
52            username: Some(user_info.username),
53            avatar_url,
54            ..Default::default()
55        })
56    }
57}