diff options
author | nea <romangraef@gmail.com> | 2022-11-26 19:08:14 +0100 |
---|---|---|
committer | nea <romangraef@gmail.com> | 2022-11-26 19:08:14 +0100 |
commit | 10f3ac6b18cbfcf74b41019ba2071b402310b245 (patch) | |
tree | c3244e1479875246d5cc32ab0130d5024b221825 | |
parent | 0ed508b4ae5ba79d12cff1314438e79f322df9de (diff) | |
download | discordavatarproxy-10f3ac6b18cbfcf74b41019ba2071b402310b245.tar.gz discordavatarproxy-10f3ac6b18cbfcf74b41019ba2071b402310b245.tar.bz2 discordavatarproxy-10f3ac6b18cbfcf74b41019ba2071b402310b245.zip |
Introducing .json and .png extensions as well as default avatars
-rw-r--r-- | README | 3 | ||||
-rw-r--r-- | src/main.rs | 64 |
2 files changed, 56 insertions, 11 deletions
@@ -8,7 +8,8 @@ Run: Listens to localhost:<port> -Requests to localhost:<port>/avatar/<userid> instead reply with a png of the users avatar. +Requests to localhost:<port>/avatar/<userid>.png reply with a png of the users avatar. +Requests to localhost:<port>/avatar/<userid>.json reply with a json of the users data. A publicly hosted version is available at https://dp.nea.moe/avatar/310702108997320705 diff --git a/src/main.rs b/src/main.rs index b30447e..ce2150d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use hyper::client::{Client, HttpConnector}; use hyper::service::{make_service_fn, service_fn}; use hyper_tls::HttpsConnector; -async fn get_avatar_url(client: &Client<HttpsConnector<HttpConnector>>, token: &str, user_id: u64) -> anyhow::Result<String> { +async fn get_user_data(client: &Client<HttpsConnector<HttpConnector>>, token: &str, user_id: u64) -> anyhow::Result<serde_json::Value> { let request = Request::builder() .method(Method::GET) .uri(format!("https://discord.com/api/v10/users/{}", user_id)) @@ -18,20 +18,29 @@ async fn get_avatar_url(client: &Client<HttpsConnector<HttpConnector>>, token: & let body = hyper::body::to_bytes(x.body_mut()).await?; let json_data = String::from_utf8(Vec::from(body))?; let json: serde_json::Value = serde_json::from_str(&json_data)?; - let avatar = json["avatar"].as_str().ok_or(anyhow::anyhow!("Missing avatar"))?; + Ok(json) +} + +async fn get_avatar_url(client: &Client<HttpsConnector<HttpConnector>>, token: &str, user_id: u64) -> anyhow::Result<String> { + let json = get_user_data(client, token, user_id).await?; let id = json["id"].as_str().ok_or(anyhow::anyhow!("Missing avatar"))?; - let avatar_url = format!("https://cdn.discordapp.com/avatars/{}/{}.png", id, avatar); - println!("Served request for {}: {}#{}", id, json["username"], json["discriminator"]); + let discrim = json["discriminator"].as_str().ok_or(anyhow::anyhow!("Missing discriminator"))?; + println!("Served request for {}: {}#{}", id, json["username"], discrim); + let avatar_url = match json["avatar"].as_str() { + None => default_avatar_url(discrim)?, + Some(avatar_hash) => format!("https://cdn.discordapp.com/avatars/{}/{}.png", id, avatar_hash) + }; Ok(avatar_url) } +fn make_err(err: u16, text: &str) -> anyhow::Result<Response<Body>> { + return Ok(Response::builder() + .status(err) + .body(format!("{} {}", err, text).into())?); +} + async fn resp(arc: Arc<Ctx>, req: Request<Body>) -> anyhow::Result<Response<Body>> { - fn make_err(err: u16, text: &str) -> anyhow::Result<Response<Body>> { - return Ok(Response::builder() - .status(err) - .body(format!("{} {}", err, text).into())?); - } let x = req.uri().path(); if x == "/" { return Ok(Response::builder() @@ -43,7 +52,41 @@ async fn resp(arc: Arc<Ctx>, req: Request<Body>) -> anyhow::Result<Response<Body None => return make_err(404, "Not found"), Some(request) => request, }; - let num_id = match request.parse::<u64>() { + if let Some(userid) = request.strip_suffix(".png") { + return respond_with_image(arc, userid).await; + } + if let Some(userid) = request.strip_suffix(".json") { + return respond_with_json(arc, userid).await; + } + return make_err(404, "Invalid format"); +} + +fn default_avatar_url(discrim: &str) -> anyhow::Result<String> { + let d = discrim.parse::<u16>()?; + let bare = d % 5; + Ok(format!("https://cdn.discordapp.com/embed/avatars/{}.png", bare)) +} + +struct ResponseUserFormat { + username: String, + discriminator: String, + avatar: String, + banner: Option<String>, +} + +async fn respond_with_json(arc: Arc<Ctx>, userid: &str) -> anyhow::Result<Response<Body>> { + let num_id = match userid.parse::<u64>() { + Err(_) => return make_err(404, "Not found"), + Ok(num) => num, + }; + Ok(Response::builder() + .status(200) + .header("content-type", "application/json") + .body(serde_json::to_string("{\"todo\": true}")?.into())?) +} + +async fn respond_with_image(arc: Arc<Ctx>, userid: &str) -> anyhow::Result<Response<Body>> { + let num_id = match userid.parse::<u64>() { Err(_) => return make_err(404, "Not found"), Ok(num) => num, }; @@ -61,6 +104,7 @@ async fn resp(arc: Arc<Ctx>, req: Request<Body>) -> anyhow::Result<Response<Body .body(resp.into_body())?) } + struct Ctx { client: Client<HttpsConnector<HttpConnector>>, token: String, |