mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-08 14:57:54 +00:00
feat(api): port discord/callback to rust
This commit is contained in:
parent
3e194d7c8a
commit
882e9b66f2
9 changed files with 327 additions and 43 deletions
|
|
@ -55,3 +55,149 @@ pub async fn meta(State(ctx): State<ApiContext>) -> Json<Value> {
|
|||
"channel_count": channel_count,
|
||||
}))
|
||||
}
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::util::json_err;
|
||||
use axum::{
|
||||
extract,
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use hyper::StatusCode;
|
||||
use libpk::config;
|
||||
use pluralkit_models::{PKSystem, PKSystemConfig};
|
||||
use reqwest::ClientBuilder;
|
||||
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
pub struct CallbackRequestData {
|
||||
redirect_domain: String,
|
||||
code: String,
|
||||
// state: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct CallbackDiscordData {
|
||||
client_id: String,
|
||||
client_secret: String,
|
||||
grant_type: String,
|
||||
redirect_uri: String,
|
||||
code: String,
|
||||
}
|
||||
|
||||
pub async fn discord_callback(
|
||||
State(ctx): State<ApiContext>,
|
||||
extract::Json(request_data): extract::Json<CallbackRequestData>,
|
||||
) -> Response {
|
||||
let client = ClientBuilder::new()
|
||||
.connect_timeout(Duration::from_secs(3))
|
||||
.timeout(Duration::from_secs(3))
|
||||
.build()
|
||||
.expect("error making client");
|
||||
|
||||
let reqbody = serde_urlencoded::to_string(&CallbackDiscordData {
|
||||
client_id: config.discord.as_ref().unwrap().client_id.get().to_string(),
|
||||
client_secret: config.discord.as_ref().unwrap().client_secret.clone(),
|
||||
grant_type: "authorization_code".to_string(),
|
||||
redirect_uri: request_data.redirect_domain, // change this!
|
||||
code: request_data.code,
|
||||
})
|
||||
.expect("could not serialize");
|
||||
|
||||
let discord_resp = client
|
||||
.post("https://discord.com/api/v10/oauth2/token")
|
||||
.header("content-type", "application/x-www-form-urlencoded")
|
||||
.body(reqbody)
|
||||
.send()
|
||||
.await
|
||||
.expect("failed to request discord");
|
||||
|
||||
let Value::Object(discord_data) = discord_resp
|
||||
.json::<Value>()
|
||||
.await
|
||||
.expect("failed to deserialize discord response as json")
|
||||
else {
|
||||
panic!("discord response is not an object")
|
||||
};
|
||||
|
||||
if !discord_data.contains_key("access_token") {
|
||||
return json_err(
|
||||
StatusCode::BAD_REQUEST,
|
||||
format!(
|
||||
"{{\"error\":\"{}\"\"}}",
|
||||
discord_data
|
||||
.get("error_description")
|
||||
.expect("missing error_description from discord")
|
||||
.to_string()
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
let token = format!(
|
||||
"Bearer {}",
|
||||
discord_data
|
||||
.get("access_token")
|
||||
.expect("missing access_token")
|
||||
.as_str()
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
let discord_client = twilight_http::Client::new(token);
|
||||
|
||||
let user = discord_client
|
||||
.current_user()
|
||||
.await
|
||||
.expect("failed to get current user from discord")
|
||||
.model()
|
||||
.await
|
||||
.expect("failed to parse user model from discord");
|
||||
|
||||
let system: Option<PKSystem> = sqlx::query_as(
|
||||
r#"
|
||||
select systems.*
|
||||
from accounts
|
||||
left join systems on accounts.system = systems.id
|
||||
where accounts.uid = $1
|
||||
"#,
|
||||
)
|
||||
.bind(user.id.get() as i64)
|
||||
.fetch_optional(&ctx.db)
|
||||
.await
|
||||
.expect("failed to query");
|
||||
|
||||
if system.is_none() {
|
||||
return json_err(
|
||||
StatusCode::BAD_REQUEST,
|
||||
"user does not have a system registered".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
let system = system.unwrap();
|
||||
|
||||
let system_config: Option<PKSystemConfig> = sqlx::query_as(
|
||||
r#"
|
||||
select * from system_config where system = $1
|
||||
"#,
|
||||
)
|
||||
.bind(system.id)
|
||||
.fetch_optional(&ctx.db)
|
||||
.await
|
||||
.expect("failed to query");
|
||||
|
||||
let system_config = system_config.unwrap();
|
||||
|
||||
// create dashboard token for system
|
||||
|
||||
let token = system.clone().token;
|
||||
|
||||
(
|
||||
StatusCode::OK,
|
||||
serde_json::to_string(&serde_json::json!({
|
||||
"system": system.to_json(),
|
||||
"config": system_config.to_json(),
|
||||
"user": user,
|
||||
"token": token,
|
||||
}))
|
||||
.expect("should not error"),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ fn router(ctx: ApiContext) -> Router {
|
|||
.route("/private/bulk_privacy/member", post(rproxy))
|
||||
.route("/private/bulk_privacy/group", post(rproxy))
|
||||
.route("/private/discord/callback", post(rproxy))
|
||||
.route("/private/discord/callback2", post(endpoints::private::discord_callback))
|
||||
.route("/private/discord/shard_state", get(endpoints::private::discord_state))
|
||||
.route("/private/stats", get(endpoints::private::meta))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue