diff --git a/queries/get_person.graphql b/queries/get_person.graphql new file mode 100644 index 0000000..81ee0b2 --- /dev/null +++ b/queries/get_person.graphql @@ -0,0 +1,137 @@ +# SPDX-License-Identifier: MIT +# Copyright (c) 2022 Andriel Ferreira + +query ($id: Int) { + Staff (id: $id) { + id + name { + first + middle + last + full + native + alternative + userPreferred + } + languageV2 + image { + large + medium + } + description(asHtml: true) + primaryOccupations + gender + dateOfBirth { + year + month + day + } + dateOfDeath { + year + month + day + } + age + yearsActive + homeTown + bloodType + isFavourite + isFavouriteBlocked + siteUrl + staffMedia(sort: POPULARITY) { + nodes { + id + idMal + title { + romaji + english + native + userPreferred + } + type + format + status(version: 2) + description(asHtml: true) + coverImage { + extraLarge + large + medium + color + } + bannerImage + averageScore + meanScore + } + } + characters(sort: RELEVANCE) { + nodes { + id + name { + first + middle + last + full + native + alternative + alternativeSpoiler + userPreferred + } + image { + large + medium + } + description(asHtml: true) + siteUrl + } + } + characterMedia(sort: POPULARITY) { + edges { + node { + id + idMal + title { + romaji + english + native + userPreferred + } + type + format + status(version: 2) + description(asHtml: true) + coverImage { + extraLarge + large + medium + color + } + bannerImage + averageScore + meanScore + } + id + characters { + id + name { + first + middle + last + full + native + alternative + alternativeSpoiler + userPreferred + } + image { + large + medium + } + description(asHtml: true) + siteUrl + } + } + } + favourites + modNotes + } +} diff --git a/src/client.rs b/src/client.rs index b17d0c7..7038b6c 100644 --- a/src/client.rs +++ b/src/client.rs @@ -68,10 +68,21 @@ impl Client { self.get_character(variables).await } + pub async fn get_person(&self, id: i64) -> Result { + let data = self + .request("person", "get", serde_json::json!({ "id": id })) + .await + .unwrap(); + let mut person = crate::models::Person::parse(&data["data"]["Staff"]); + person.is_full_loaded = true; + + Ok(person) + } + pub async fn mutate( &self, _media_type: &str, - _id: i32, + _id: i64, _variables: serde_json::Value, ) -> Result { todo!() diff --git a/src/models/anime.rs b/src/models/anime.rs index 6d75408..8ad01ae 100644 --- a/src/models/anime.rs +++ b/src/models/anime.rs @@ -346,7 +346,7 @@ impl Anime { let mut staff: Vec = Vec::with_capacity(nodes.len()); for node in nodes { - staff.push(Person::parse(node, None)); + staff.push(Person::parse(node)); } anime.staff = Some(staff); diff --git a/src/models/manga.rs b/src/models/manga.rs index 54db902..876b3fe 100644 --- a/src/models/manga.rs +++ b/src/models/manga.rs @@ -323,7 +323,7 @@ impl Manga { let mut staff: Vec = Vec::with_capacity(nodes.len()); for node in nodes { - staff.push(Person::parse(node, None)); + staff.push(Person::parse(node)); } manga.staff = Some(staff); diff --git a/src/models/person.rs b/src/models/person.rs index 652aa99..9e913cb 100644 --- a/src/models/person.rs +++ b/src/models/person.rs @@ -2,46 +2,41 @@ // Copyright (c) 2022 Andriel Ferreira use crate::models::Character; +use crate::models::Date; use crate::models::Gender; use crate::models::Image; use crate::models::Language; use crate::models::Name; -use crate::models::User; use crate::Result; #[derive(Debug, Default, Clone, PartialEq)] pub struct Person { - id: i64, - name: Name, - language: Language, - image: Option, - description: Option, - primary_occupations: Option>, - gender: Gender, - date_of_birth: Option, - date_of_death: Option, - age: Option, - years_active: Option<(i64, i64)>, - home_town: Option, - blood_type: Option, - is_favourite: Option, - is_favourite_blocked: Option, - url: String, - characters: Option>, - submitter: Option, - submitter_status: Option, - submitter_notes: Option, - favourites: i64, - mod_notes: Option, + pub id: i64, + pub name: Name, + pub language: Language, + pub image: Option, + pub description: Option, + pub primary_occupations: Option>, + pub gender: Gender, + pub date_of_birth: Option, + pub date_of_death: Option, + pub age: Option, + pub years_active: Option<(u64, u64)>, + pub home_town: Option, + pub blood_type: Option, + pub is_favourite: Option, + pub is_favourite_blocked: Option, + pub url: String, + pub characters: Option>, + pub favourites: i64, + pub mod_notes: Option, + pub(crate) is_full_loaded: bool, } impl Person { - pub(crate) fn parse(data: &serde_json::Value, person: Option) -> Self { - let mut person = match person { - Some(person) => person, - None => Person::default(), - }; + pub(crate) fn parse(data: &serde_json::Value) -> Self { + let mut person = Person::default(); person.id = data["id"].as_i64().unwrap(); @@ -81,14 +76,145 @@ impl Person { person.name = name; } + if let Some(language) = data["languageV2"].as_str() { + person.language = match language.to_uppercase().as_str() { + "ENGLISH" => Language::English, + "KOREAN" => Language::Korean, + "ITALIAN" => Language::Italian, + "SPANISH" => Language::Spanish, + "PORTUGUESE" => Language::Portuguese, + "FRENCH" => Language::French, + "GERMAN" => Language::German, + "HEBREW" => Language::Hebrew, + "HUNGARIAN" => Language::Hungarian, + "CHINESE" => Language::Chinese, + "ARABIC" => Language::Arabic, + "FILIPINO" => Language::Filipino, + "CATALAN" => Language::Catalan, + "FINNISH" => Language::Finnish, + "TURKISH" => Language::Turkish, + "DUTCH" => Language::Dutch, + "SWEDISH" => Language::Swedish, + "THAI" => Language::Thai, + "TAGALOG" => Language::Tagalog, + "MALAYSIAN" => Language::Malaysian, + "INDONESIAN" => Language::Indonesian, + "VIETNAMESE" => Language::Vietnamese, + "NEPALI" => Language::Nepali, + "HINDI" => Language::Hindi, + "URDU" => Language::Urdu, + _ => Language::default(), + }; + } + + if let Some(image_object) = data["image"].as_object() { + person.image = Some(Image { + large: image_object["large"].as_str().unwrap().to_string(), + medium: image_object["medium"].as_str().unwrap().to_string(), + }); + } + + if let Some(date_of_birth) = data["dateOfBirth"].as_object() { + let mut date = Date::default(); + + if let Some(year) = date_of_birth["year"].as_i64() { + date.year = Some(year); + } + if let Some(month) = date_of_birth["month"].as_i64() { + date.month = Some(month); + } + if let Some(day) = date_of_birth["day"].as_i64() { + date.day = Some(day); + } + + person.date_of_birth = Some(date); + } + + if let Some(date_of_death) = data["dateOfDeath"].as_object() { + let mut date = Date::default(); + + if let Some(year) = date_of_death["year"].as_i64() { + date.year = Some(year); + } + if let Some(month) = date_of_death["month"].as_i64() { + date.month = Some(month); + } + if let Some(day) = date_of_death["day"].as_i64() { + date.day = Some(day); + } + + person.date_of_death = Some(date); + } + + if let Some(age) = data["age"].as_i64() { + person.age = Some(age); + } + + if let Some(years_active) = data["yearsActive"].as_array() { + person.years_active = match years_active.len() { + 2 => Some(( + years_active[0].as_u64().unwrap(), + years_active[1].as_u64().unwrap(), + )), + 1 => Some((years_active[0].as_u64().unwrap(), 0)), + _ => None, + }; + } + + if let Some(home_town) = data["homeTown"].as_str() { + person.home_town = Some(home_town.to_string()); + } + + if let Some(blood_type) = data["bloodType"].as_str() { + person.blood_type = Some(blood_type.to_string()); + } + + if let Some(is_favourite) = data["isFavourite"].as_bool() { + person.is_favourite = Some(is_favourite); + } + + if let Some(is_favourite_blocked) = data["isFavouriteBlocked"].as_bool() { + person.is_favourite_blocked = Some(is_favourite_blocked); + } + + person.url = data["siteUrl"].as_str().unwrap().to_string(); + + if let Some(characters) = data["characters"].as_object() { + if let Some(nodes) = characters["nodes"].as_array() { + let mut characters: Vec = Vec::with_capacity(nodes.len()); + + for node in nodes { + characters.push(Character::parse(node)); + } + + person.characters = Some(characters); + } + } + + person.favourites = data["favourites"].as_i64().unwrap(); + + if let Some(mod_notes) = data["modNotes"].as_str() { + person.mod_notes = Some(mod_notes.to_string()); + } + person } + pub async fn load_full(self) -> crate::Result { + if !self.is_full_loaded { + let mut person = crate::Client::new().get_person(self.id).await.unwrap(); + person.is_full_loaded = true; + Ok(person) + } else { + panic!("This person is already full loaded") + } + } + pub async fn get_medias() -> Result { todo!() } - pub async fn get_character_medias() -> Result { + pub async fn get_character_medias(_character_id: i64) -> Result { todo!() } } diff --git a/src/models/relation.rs b/src/models/relation.rs index 6f89d00..2f67c2e 100644 --- a/src/models/relation.rs +++ b/src/models/relation.rs @@ -5,6 +5,7 @@ use crate::models::Anime; use crate::models::Manga; use crate::models::MediaType; +// TODO: Use generic type #[derive(Debug, Clone, PartialEq)] pub struct Relation { pub media_type: MediaType, diff --git a/tests/person.rs b/tests/person.rs new file mode 100644 index 0000000..970b4c8 --- /dev/null +++ b/tests/person.rs @@ -0,0 +1,7 @@ +use rust_anilist::Client; + +#[tokio::test] +async fn get_person() { + let person = Client::new().get_person(96879).await; + assert!(person.is_ok()) +}