rdiscord/src/discord.rs
2024-08-13 14:43:43 +02:00

106 lines
3.3 KiB
Rust

extern crate reqwest;
extern crate rocket;
pub mod discord {
static API: &str = "https://discord.com/api/v10";
use rocket::serde::{Deserialize, Serialize};
use std::error::Error;
use urlencoding::encode;
#[derive(Deserialize, Serialize)]
pub struct TokenResponse {
pub access_token: String,
pub token_type: String,
pub expires_in: usize,
pub refresh_token: String,
pub scope: String,
}
#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct AvatarDecorationData {
asset: String,
sku_id: String,
}
#[derive(Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "rocket::serde")]
pub struct User {
pub id: String,
pub username: String,
pub discriminator: String,
pub global_name: Option<String>,
pub avatar: Option<String>,
pub bot: Option<bool>,
pub system: Option<bool>,
pub mfa_enabled: Option<bool>,
pub banner: Option<String>,
pub accent_color: Option<usize>,
pub locale: Option<String>,
pub verified: Option<bool>,
pub email: Option<String>,
pub flags: Option<usize>,
pub premium_type: Option<usize>,
pub public_flags: Option<usize>,
pub avatar_decoration_data: Option<AvatarDecorationData>,
}
pub struct Client {
redirect_uri: String,
client_secret: String,
client_id: String,
}
impl Client {
pub fn new(redirect_uri: String, client_id: String, client_secret: String) -> Self {
Client {
redirect_uri,
client_id,
client_secret,
}
}
pub fn generate_authorize_url(&self, scope: &str, response_type: &str) -> String {
let AUTHORIZE_ENDPOINT = "https://discord.com/oauth2/authorize";
format!(
"{}?client_id={}&response_type={}&redirect_uri={}&scope={}",
AUTHORIZE_ENDPOINT,
self.client_id,
response_type,
&encode(&self.redirect_uri),
scope
)
}
pub async fn get_user(
&self,
token_response: &TokenResponse,
) -> Result<User, Box<dyn Error>> {
let http_client = reqwest::Client::new();
let user_request = http_client
.get(format!("{}/{}", API, "users/@me"))
.bearer_auth(&token_response.access_token)
.send()
.await?;
let res: User = user_request.json().await?;
Ok(res)
}
pub async fn exchange_code(&self, code: &String) -> Result<TokenResponse, Box<dyn Error>> {
let http_client = reqwest::Client::new();
let exchange_request = http_client
.post(format!("{}/{}", API, "/oauth2/token"))
.header("content-type", "application/x-www-form-urlencoded")
.basic_auth(&self.client_id, Some(&self.client_secret))
.form(&[
("grant_type", "authorization_code"),
("code", code),
("redirect_uri", &self.redirect_uri),
])
.send()
.await?;
let res: TokenResponse = exchange_request.json().await?;
Ok(res)
}
}
}