Skip to content

Commit

Permalink
feat: add get_user & get_user_by_name
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrielFR committed Jan 2, 2025
1 parent 9f4e7a8 commit 25629f8
Show file tree
Hide file tree
Showing 4 changed files with 297 additions and 10 deletions.
188 changes: 188 additions & 0 deletions queries/get_user.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2022-2025 Andriel Ferreira <https://github.com/AndrielFR>

query ($id: Int, $name: String) {
User(id: $id, name: $name) {
id
name
about
avatar {
large
medium
}
bannerImage
favourites {
anime {
nodes {
id
title {
romaji
english
native
}
siteUrl
genres
isAdult
coverImage {
medium
large
extraLarge
}
bannerImage
source
hashtag
synonyms
averageScore
meanScore
}
}
manga {
nodes {
id
title {
romaji
english
native
userPreferred
}
siteUrl
genres
isAdult
coverImage {
medium
large
extraLarge
}
bannerImage
source
hashtag
synonyms
averageScore
meanScore
}
}
characters {
nodes {
id
name {
first
middle
last
full
native
userPreferred
}
image {
large
medium
}
description
gender
dateOfBirth {
year
month
day
}
age
siteUrl
favourites
}
}
staff {
nodes {
id
name {
first
middle
last
full
native
userPreferred
}
languageV2
image {
large
medium
}
description
primaryOccupations
gender
dateOfBirth {
year
month
day
}
dateOfDeath {
year
month
day
}
age
yearsActive
homeTown
siteUrl
favourites
}
}
studios {
nodes {
id
name
isAnimationStudio
siteUrl
favourites
}
}
}
statistics {
anime {
count
meanScore
minutesWatched
episodesWatched
statuses {
status
count
}
genres(sort: COUNT_DESC) {
genre
count
}
tags(sort: COUNT_DESC) {
tag {
name
}
count
}
}
manga {
count
meanScore
chaptersRead
volumesRead
statuses {
status
count
}
genres(sort: COUNT_DESC) {
genre
count
}
tags(sort: COUNT_DESC) {
tag {
name
}
count
}
}
}
siteUrl
donatorTier
donatorBadge
createdAt
updatedAt
options {
profileColor
}
}
}
81 changes: 79 additions & 2 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022-2025 Andriel Ferreira <https://github.com/AndrielFR>

use std::io::Write;
use std::time::Duration;

use crate::models::{Anime, Character, Manga, Person};
use crate::models::{Anime, Character, Manga, Person, User};
use crate::Result;

#[derive(Clone)]
Expand Down Expand Up @@ -177,6 +178,82 @@ impl Client {
self.get_character(id).await
}

/// Get a user by its ID.
///
/// # Arguments
///
/// * `id` - The ID of the user.
///
/// # Errors
///
/// Returns an error if the request fails.
///
/// # Example
///
/// ```
/// # async fn f(client: rust_anilist::Client) -> rust_anilist::Result<()> {
/// let user = client.get_user(1).await?;
///
/// # Ok(())
/// # }
/// ```
pub async fn get_user(&self, id: i64) -> Result<crate::models::User> {
let data = self
.request(
MediaType::User,
Action::Get,
serde_json::json!({ "id": id }),
)
.await
.unwrap();

std::fs::File::create("user.json")
.unwrap()
.write_all(data["data"]["User"].to_string().as_bytes())
.unwrap();
match serde_json::from_str::<User>(&data["data"]["User"].to_string()) {
Ok(user) => Ok(user),
Err(e) => Err(crate::Error::ApiError(e.to_string())),
}
}

/// Get a user by its name.
///
/// # Arguments
///
/// * `name` - The name of the user.
///
/// # Errors
///
/// Returns an error if the request fails.
///
/// # Example
///
/// ```
/// # async fn f(client: rust_anilist::Client) -> rust_anilist::Result<()> {
/// let user = client.get_user_by_name("andrielfr").await?;
///
/// # Ok(())
/// # }
/// ```
pub async fn get_user_by_name<N: ToString>(&self, name: N) -> Result<crate::models::User> {
let name = name.to_string();

let data = self
.request(
MediaType::User,
Action::Get,
serde_json::json!({ "name": name }),
)
.await
.unwrap();

match serde_json::from_str::<User>(&data["data"]["User"].to_string()) {
Ok(user) => Ok(user),
Err(e) => Err(crate::Error::ApiError(e.to_string())),
}
}

/// Get a person by its ID.
///
/// # Arguments
Expand Down Expand Up @@ -286,7 +363,7 @@ impl Client {
MediaType::Character => {
include_str!("../queries/get_character.graphql").to_string()
}
// MediaType::User => include_str!("../queries/get_user.graphql").to_string(),
MediaType::User => include_str!("../queries/get_user.graphql").to_string(),
MediaType::Person => include_str!("../queries/get_person.graphql").to_string(),
// MediaType::Studio => include_str!("../queries/get_studio.graphql").to_string(),
_ => unimplemented!(),
Expand Down
24 changes: 16 additions & 8 deletions src/models/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,36 @@ pub struct User {
name: String,
about: Option<String>,
avatar: Option<Image>,
#[serde(rename = "bannerImage")]
banner: Option<String>,
is_following: Option<bool>,
is_follower: Option<bool>,
is_blocked: Option<bool>,
options: Option<Options>,
media_list_options: MediaListOptions,
media_list_options: Option<MediaListOptions>,
#[serde(skip)]
favourites: Favourites,
statistics: UserStatisticTypes,
}

#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)]
#[serde(rename_all(deserialize = "camelCase"))]
struct Options {
title_language: UserTitleLanguage,
title_language: Option<UserTitleLanguage>,
#[serde(default)]
display_adult_content: bool,
#[serde(default)]
airing_notifications: bool,
profile_color: Color,
notifications_options: Vec<NotificationOption>,
timezone: String,
notifications_options: Option<Vec<NotificationOption>>,
timezone: Option<String>,
#[serde(default)]
activity_merge_time: i32,
#[serde(default)]
staff_name_language: UserStaffNameLanguage,
#[serde(default)]
restrict_messages_to_following: bool,
disabled_list_activity: Vec<ListActivityOption>,
disabled_list_activity: Option<Vec<ListActivityOption>>,
}

#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)]
Expand Down Expand Up @@ -94,7 +101,6 @@ pub struct MediaListTypeOptions {
}

#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Favourites {
anime: Vec<Anime>,
manga: Vec<Manga>,
Expand All @@ -114,12 +120,12 @@ pub struct UserStatisticTypes {
#[serde(rename_all(deserialize = "camelCase"))]
pub struct UserStatistics {
count: i32,
standard_deviation: f32,
standard_deviation: Option<f32>,
minutes_watched: Option<i32>,
episodes_watched: Option<i32>,
chapters_read: Option<i32>,
volumes_read: Option<i32>,
formats: Vec<UserFormatStatistic>,
formats: Option<Vec<UserFormatStatistic>>,
statuses: Vec<UserStatusStatistic>,
}

Expand All @@ -129,6 +135,7 @@ pub struct UserFormatStatistic {
count: i32,
minutes_watched: Option<i32>,
chapters_read: Option<i32>,
#[serde(default)]
media_ids: Vec<i32>,
format: Format,
}
Expand All @@ -139,6 +146,7 @@ pub struct UserStatusStatistic {
count: i32,
minutes_watched: Option<i32>,
chapters_read: Option<i32>,
#[serde(default)]
media_ids: Vec<i32>,
status: Status,
}
14 changes: 14 additions & 0 deletions tests/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use rust_anilist::Client;

#[tokio::test]
async fn get_user() {
let user = Client::default().get_user(5375822).await;
user.as_ref().unwrap();
assert!(user.is_ok())
}

#[tokio::test]
async fn get_user_by_name() {
let user = Client::default().get_user_by_name("andrielfr").await;
assert!(user.is_ok())
}

0 comments on commit 25629f8

Please sign in to comment.