mal_query/myanimelist/
mod.rs

1use std::{sync::Mutex, fs, error::Error};
2use lazy_static::lazy_static;
3use reqwest::Response;
4use serde_json::Value;
5use self::models::{MalAnimeData, MalAnimeSearch, ListStatus};
6
7pub use login::login;
8
9pub mod retrieval;
10pub mod login;
11pub mod builders;
12pub mod models;
13pub mod user;
14
15lazy_static! {
16    // CLIENT_ID recieve a string from a local file not uploaded here, only containing a MyAnimeList Client Id
17    pub static ref CLIENT_ID: String = String::from("f7e5c56ef3561bb0a290a13d35b02c0b");
18    pub static ref TOKEN: Mutex<String> = Mutex::new(fs::read_to_string("token.txt").unwrap_or(String::new()));
19}
20
21async fn client_call(url: &str) -> Result<Response, Box<dyn Error>> {
22    let token = TOKEN.lock().unwrap();
23    let header_key: &str;
24    let header_value: String;
25    if token.is_empty() {
26        header_key = "X-MAL-CLIENT-ID";
27        header_value = CLIENT_ID.clone();
28    } else {
29        header_key = "Authorization";
30        header_value = format!("Bearer {}", *token);
31    }
32
33    let client = reqwest::Client::new();
34    let res = client
35        .get(url)
36        .header(header_key, header_value)
37        .send()
38        .await?;
39    Ok(res)
40}
41
42// To get one anime
43async fn run_get(url: &str) -> Result<MalAnimeData, Box<dyn Error>> {
44    let res = client_call(url).await?;
45
46    if res.status().is_success() {
47        let test = res.text().await?;
48        let data: MalAnimeData = serde_json::from_str(&test).unwrap();
49
50        return Ok(data);
51    } else {
52        return Err(format!("Request failed with status {:?}", res.status()))?;
53    }
54}
55
56// To get Vec of anime (search)
57async fn run_search(url: &str) -> Result<MalAnimeSearch, Box<dyn Error>> {
58    let res = client_call(url).await?;
59
60    if res.status().is_success() {
61        let data: Value = res.json().await?;
62        // Takes the data, and throws it into a Vec of MalAnimeData
63        let mut result: Vec<MalAnimeData> = Vec::new();
64        data["data"]
65            .as_array()
66            .expect("Expected an array")
67            .iter()
68            .for_each(|v| {
69                let x = v.get("node").unwrap();
70                let mut to_push = serde_json::from_value::<MalAnimeData>(x.clone()).unwrap();
71                // get_anime_rankings has slightly different results
72                if let Some(r) = v.get("ranking") {
73                    to_push.rank = Some(r["rank"].as_u64().unwrap() as u32);
74                }
75                // get_user_animelist has slightly different results
76                if let Some(s) = v.get("list_status") {
77                    let status = serde_json::from_value::<ListStatus>(s.clone()).unwrap();
78                    to_push.list_status = Some(status);
79                }
80                result.push(to_push);
81            });
82
83        return Ok(MalAnimeSearch::new(result));
84    } else {
85        return Err(format!("Request failed with status {:?}", res.status()))?;
86    }
87}
88