rs_pixel/util/
minecraft.rs

1use super::error::Error;
2use crate::RsPixel;
3use serde_json::Value;
4
5pub async fn username_to_uuid(rs_pixel: &RsPixel, username: &str) -> Result<Response, Error> {
6    if let Some(uuid_to_username_cache) = &rs_pixel.config.uuid_to_username_cache {
7        if let Some(cache_entry) = uuid_to_username_cache
8            .iter()
9            .find(|e| e.1.eq_ignore_ascii_case(username))
10        {
11            return Ok(Response {
12                username: cache_entry.1,
13                uuid: cache_entry.0.to_string(),
14            });
15        }
16    }
17
18    uuid_username(rs_pixel, username, false).await
19}
20
21pub async fn uuid_to_username(rs_pixel: &RsPixel, uuid: &str) -> Result<Response, Error> {
22    if let Some(uuid_to_username_cache) = &rs_pixel.config.uuid_to_username_cache {
23        if let Some(username) = uuid_to_username_cache.get(uuid) {
24            return Ok(Response {
25                username,
26                uuid: uuid.to_string(),
27            });
28        }
29    }
30
31    uuid_username(rs_pixel, uuid, true).await
32}
33
34async fn uuid_username(
35    rs_pixel: &RsPixel,
36    uuid_username: &str,
37    is_uuid: bool,
38) -> Result<Response, Error> {
39    match rs_pixel
40        .config
41        .client
42        .get(match rs_pixel.config.minecraft_api_type {
43            ApiType::Mojang => {
44                if is_uuid {
45                    format!("https://api.mojang.com/user/profiles/{uuid_username}/names")
46                } else {
47                    format!("https://api.mojang.com/users/profiles/minecraft/{uuid_username}")
48                }
49            }
50            ApiType::Ashcon => {
51                format!("https://api.ashcon.app/mojang/v2/user/{uuid_username}")
52            }
53            ApiType::PlayerDb => {
54                format!("https://playerdb.co/api/player/minecraft/{uuid_username}")
55            }
56        })
57        .send()
58        .await
59    {
60        Ok(mut res_unwrap) => {
61            let json = res_unwrap.body_json::<Value>().await.map_err(Error::from);
62
63            if res_unwrap.status() == 200 {
64                return match json {
65                    Ok(json_unwrap) => Ok(match rs_pixel.config.minecraft_api_type {
66                        ApiType::Mojang => Response {
67                            username: (if is_uuid {
68                                json_unwrap
69                                    .as_array()
70                                    .and_then(|v| v.last())
71                                    .and_then(|v| v.get("name"))
72                            } else {
73                                json_unwrap.get("name")
74                            })
75                            .and_then(serde_json::Value::as_str)
76                            .unwrap_or("")
77                            .to_string(),
78                            uuid: (if is_uuid {
79                                uuid_username
80                            } else {
81                                json_unwrap
82                                    .get("id")
83                                    .and_then(serde_json::Value::as_str)
84                                    .unwrap_or("")
85                            })
86                            .to_string(),
87                        },
88                        ApiType::Ashcon => Response {
89                            username: json_unwrap
90                                .get("username")
91                                .and_then(serde_json::Value::as_str)
92                                .unwrap_or("")
93                                .to_string(),
94                            uuid: json_unwrap
95                                .get("uuid")
96                                .and_then(serde_json::Value::as_str)
97                                .unwrap_or("")
98                                .to_string()
99                                .replace('-', ""),
100                        },
101                        ApiType::PlayerDb => Response {
102                            username: json_unwrap
103                                .get("data")
104                                .and_then(|v| v.get("player"))
105                                .and_then(|v| v.get("username"))
106                                .and_then(serde_json::Value::as_str)
107                                .unwrap_or("")
108                                .to_string(),
109                            uuid: json_unwrap
110                                .get("data")
111                                .and_then(|v| v.get("player"))
112                                .and_then(|v| v.get("id"))
113                                .and_then(serde_json::Value::as_str)
114                                .unwrap_or("")
115                                .to_string()
116                                .replace('-', ""),
117                        },
118                    }),
119                    Err(err) => Err(err),
120                };
121            }
122
123            Err(Error::from((
124                res_unwrap.status(),
125                json.ok()
126                    .as_ref()
127                    .and_then(|json_unwrap| {
128                        json_unwrap.get(match rs_pixel.config.minecraft_api_type {
129                            ApiType::Mojang => "errorMessage",
130                            ApiType::Ashcon => "reason",
131                            ApiType::PlayerDb => "code",
132                        })
133                    })
134                    .and_then(serde_json::Value::as_str)
135                    .unwrap_or("Unknown fail cause")
136                    .to_string(),
137            )))
138        }
139        Err(err) => Err(Error::from(err)),
140    }
141}
142
143#[derive(Debug)]
144pub struct Response {
145    pub username: String,
146    pub uuid: String,
147}
148
149#[derive(Default)]
150pub enum ApiType {
151    #[default]
152    Mojang,
153    Ashcon,
154    PlayerDb,
155}