From ae5b6ad34ce4aca94816e2147774616fb6b7e135 Mon Sep 17 00:00:00 2001
From: nea <nea@nea.moe>
Date: Tue, 19 Sep 2023 15:15:19 +0200
Subject: Add global user name to json info

---
 src/main.rs | 53 +++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 41 insertions(+), 12 deletions(-)

(limited to 'src')

diff --git a/src/main.rs b/src/main.rs
index bf20c95..e80c67d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,4 @@
 use std::env;
-use std::fmt::format;
 use std::net::SocketAddr;
 use std::sync::Arc;
 
@@ -8,7 +7,6 @@ use hyper::service::{make_service_fn, service_fn};
 use hyper::{Body, Method, Request, Response, Server};
 use hyper_tls::HttpsConnector;
 use serde::{Deserialize, Serialize};
-use serde_json::Value;
 
 macro_rules! unwrap_resp {
     ($x:expr) => {
@@ -30,6 +28,8 @@ struct DiscordUserFormat {
     bot: bool,
     banner: Option<String>,
     avatar: Option<String>,
+    #[serde(default)]
+    global_name: Option<String>,
 }
 
 async fn get_user_data(
@@ -46,21 +46,31 @@ async fn get_user_data(
     let mut x = client.request(request).await?;
     let body = hyper::body::to_bytes(x.body_mut()).await?;
     let json_data = String::from_utf8(Vec::from(body))?;
+    println!("{}", json_data);
     let json: DiscordUserFormat = serde_json::from_str(&json_data)?;
     Ok(json)
 }
 
-fn get_avatar_url(json: &DiscordUserFormat) -> anyhow::Result<String> {
+fn get_avatar_url(json: &DiscordUserFormat, allow_animated: bool) -> anyhow::Result<String> {
     println!(
         "Served request for {}: {}#{}",
         json.id, json.username, json.discriminator
     );
     let avatar_url = match &json.avatar {
         None => default_avatar_url(&json.id, &json.discriminator)?,
-        Some(avatar_hash) => format!(
-            "https://cdn.discordapp.com/avatars/{}/{}.png",
-            json.id, avatar_hash
-        ),
+        Some(avatar_hash) => {
+            if avatar_hash.starts_with("a_") && allow_animated {
+                format!(
+                    "https://cdn.discordapp.com/avatars/{}/{}.gif",
+                    json.id, avatar_hash
+                )
+            } else {
+                format!(
+                    "https://cdn.discordapp.com/avatars/{}/{}.png",
+                    json.id, avatar_hash
+                )
+            }
+        }
     };
     Ok(avatar_url)
 }
@@ -83,8 +93,11 @@ async fn resp(arc: Arc<Ctx>, req: Request<Body>) -> anyhow::Result<Response<Body
         None => return make_err(404, "Not found"),
         Some(request) => request,
     };
+    if let Some(userid) = request.strip_suffix(".gif") {
+        return respond_with_image(arc, userid, true).await;
+    }
     if let Some(userid) = request.strip_suffix(".png") {
-        return respond_with_image(arc, userid).await;
+        return respond_with_image(arc, userid, false).await;
     }
     if let Some(userid) = request.strip_suffix(".json") {
         return respond_with_json(arc, userid).await;
@@ -111,16 +124,21 @@ struct ResponseUserFormat {
     username: String,
     discriminator: String,
     avatar: String,
+    avatar_animated: String,
     banner: Option<String>,
+    display_name: Option<String>,
 }
 
 async fn respond_with_json(arc: Arc<Ctx>, userid: &str) -> anyhow::Result<Response<Body>> {
     let json = unwrap_resp!(get_discord_data_for(&arc, userid).await?);
-    let avatar_url = get_avatar_url(&json)?;
+    let avatar_url_animated = get_avatar_url(&json, true)?;
+    let avatar_url = get_avatar_url(&json, false)?;
     let response = ResponseUserFormat {
         username: json.username,
         discriminator: json.discriminator,
         avatar: avatar_url,
+        avatar_animated: avatar_url_animated,
+        display_name: json.global_name,
         banner: json.banner.map(|hash| {
             format!(
                 "https://cdn.discordapp.com/banners/{}/{}.png",
@@ -153,9 +171,13 @@ async fn get_discord_data_for(
     ))
 }
 
-async fn respond_with_image(arc: Arc<Ctx>, userid: &str) -> anyhow::Result<Response<Body>> {
+async fn respond_with_image(
+    arc: Arc<Ctx>,
+    userid: &str,
+    allow_animated: bool,
+) -> anyhow::Result<Response<Body>> {
     let json = unwrap_resp!(get_discord_data_for(&arc, userid).await?);
-    let avatar_url = match get_avatar_url(&json) {
+    let avatar_url = match get_avatar_url(&json, allow_animated) {
         Err(_) => return make_err(502, "Discord failed to respond"),
         Ok(avatar_url) => avatar_url,
     };
@@ -170,7 +192,14 @@ async fn respond_with_image(arc: Arc<Ctx>, userid: &str) -> anyhow::Result<Respo
     };
     Ok(Response::builder()
         .status(200)
-        .header("content-type", "image/png")
+        .header(
+            "content-type",
+            if avatar_url.ends_with(".gif") {
+                "image/gif"
+            } else {
+                "image/png"
+            },
+        )
         .body(resp.into_body())?)
 }
 
-- 
cgit