minecraft_uuid/
lib.rs

1mod endpoints;
2pub mod error;
3mod models;
4
5use anyhow::Result;
6use error::APIError;
7use models::{ErrorResponse, UUIDResponse};
8use serde::de::DeserializeOwned;
9
10/// Get a UUID from the given Minecraft username
11/// from the Mojang API.
12///
13/// # Example
14/// ```
15/// # use minecraft_uuid::*;
16/// # async fn run() -> anyhow::Result<()> {
17/// let uuid = get_uuid_by_username("zekrotja").await?;
18/// assert_eq!(uuid, "c3371e36f2884eaeb9d5b90e47258444");
19/// # Ok(())
20/// # }
21/// ```
22pub async fn get_uuid_by_username(username: &str) -> Result<String> {
23    let res: UUIDResponse = get(&endpoints::usernames(username)).await?;
24    Ok(res.id)
25}
26
27/// Get a Minecraft username from the given account UUID
28/// from the Mojang API.
29///
30/// # Example
31/// ```
32/// # use minecraft_uuid::*;
33/// # async fn run() -> anyhow::Result<()> {
34/// let username = get_username_by_uuid("c3371e36f2884eaeb9d5b90e47258444").await?;
35/// assert_eq!(username, "zekroTJA");
36/// # Ok(())
37/// # }
38/// ```
39pub async fn get_username_by_uuid(uuid: &str) -> Result<String> {
40    let res: UUIDResponse = get(&endpoints::uids(uuid)).await?;
41    Ok(res.name)
42}
43
44async fn get<T: DeserializeOwned>(url: &str) -> Result<T> {
45    let resp = reqwest::get(url).await?;
46
47    let status = u16::from(resp.status());
48    if status == 204 {
49        let err = APIError::new(404, "NotFound", "This user does not exist.");
50        return Err(err.into());
51    } else if status > 399 {
52        let body: ErrorResponse = resp.json().await?;
53        let mut err: APIError = body.into();
54        err.set_status_code(status);
55        return Err(err.into());
56    }
57
58    let body = resp.json().await?;
59    Ok(body)
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[tokio::test]
67    async fn test_get_uuid_by_username() {
68        let res = get_uuid_by_username("zekrotja").await;
69        assert_eq!(res.unwrap(), "c3371e36f2884eaeb9d5b90e47258444");
70
71        let res = get_uuid_by_username("shit").await;
72        let err = res.unwrap_err();
73        let err = err.downcast_ref::<APIError>().unwrap();
74        assert_eq!(err.status_code(), 404);
75
76        let res = get_uuid_by_username("this should return a bad request i suppose").await;
77        let err = res.unwrap_err();
78        let err = err.downcast_ref::<APIError>().unwrap();
79        assert_eq!(err.status_code(), 400);
80    }
81
82    #[tokio::test]
83    async fn test_get_username_by_uuid() {
84        let res = get_username_by_uuid("c3371e36f2884eaeb9d5b90e47258444").await;
85        assert_eq!(res.unwrap(), "zekroTJA");
86
87        let res = get_username_by_uuid("invaliduuid").await;
88        let err = res.unwrap_err();
89        let err = err.downcast_ref::<APIError>().unwrap();
90        assert_eq!(err.status_code(), 400);
91
92        let res = get_username_by_uuid("79fc2caa329a4769bf47aaf351684d71").await;
93        let err = res.unwrap_err();
94        let err = err.downcast_ref::<APIError>().unwrap();
95        assert_eq!(err.status_code(), 404);
96    }
97}