106 lines
3.3 KiB
Rust
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)
|
|
}
|
|
}
|
|
}
|