mal/api/
animelist.rs

1use super::model::*;
2use super::Error;
3use super::{delete, get, handle_response, patch, API_URL};
4use crate::auth::OAuth;
5use serde::Serialize;
6
7/// Update specified anime in animelist
8#[derive(Clone, Debug, Serialize)]
9pub struct UpdateUserAnimeListStatusQuery {
10    #[serde(skip_serializing_if = "Option::is_none")]
11    pub status: Option<UserWatchStatus>,
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub is_rewatching: Option<bool>,
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub score: Option<u8>,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub num_watched_episodes: Option<u64>,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub priority: Option<u8>,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub num_times_rewatched: Option<u64>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub rewatch_value: Option<u8>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub tags: Option<String>,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub comments: Option<String>,
28}
29
30pub async fn update_anime_list_status(
31    anime_id: u64,
32    update: &UpdateUserAnimeListStatusQuery,
33    auth: &OAuth,
34) -> Result<UserAnimeListStatus, Error> {
35    let response = patch(
36        &format!("{}/anime/{}/my_list_status", API_URL, anime_id,),
37        auth,
38        update,
39    )
40    .await?;
41    handle_response(&response)
42}
43
44pub async fn delete_anime_from_list(anime_id: u64, auth: &OAuth) -> Result<(), Error> {
45    let response = delete(
46        &format!("{}/anime/{}/my_list_status", API_URL, anime_id),
47        auth,
48    )
49    .await?;
50    if response.status.is_success() {
51        Ok(())
52    } else {
53        Err(Error::HttpError(response.status))
54    }
55}
56
57#[derive(Clone, Debug, Serialize)]
58pub struct GetUserAnimeListQuery {
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub fields: Option<String>,
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub status: Option<UserWatchStatus>,
63    #[serde(skip_serializing_if = "Option::is_none")]
64    pub sort: Option<SortStyle>,
65    pub limit: u64,
66    pub offset: u64,
67    pub nsfw: bool,
68}
69
70pub async fn get_user_anime_list<U: ToString>(
71    user: U,
72    query: &GetUserAnimeListQuery,
73    auth: &OAuth,
74) -> Result<Page<Anime>, Error> {
75    let response = get(
76        &format!(
77            "{}/users/{}/animelist?{}",
78            API_URL,
79            user.to_string(),
80            serde_urlencoded::to_string(query)?
81        ),
82        auth,
83    )
84    .await?;
85    handle_response(&response)
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91    use crate::api::anime::tests::*;
92
93    #[tokio::test]
94    #[ignore]
95    async fn test_delete_anime_from_list() {
96        let auth = crate::auth::tests::get_auth();
97        let anime = get_anime("God of High School", &auth).await.unwrap();
98        delete_anime_from_list(anime.id, &auth).await.unwrap();
99    }
100
101    #[tokio::test]
102    async fn test_update_anime_list() {
103        let auth = crate::auth::tests::get_auth();
104        let query = UpdateUserAnimeListStatusQuery {
105            status: Some(UserWatchStatus::Completed),
106            is_rewatching: None,
107            score: Some(8),
108            num_watched_episodes: Some(13),
109            priority: None,
110            num_times_rewatched: None,
111            rewatch_value: None,
112            tags: None,
113            comments: None,
114        };
115
116        let anime = get_anime(
117            "Yahari Ore no Seishun Love Comedy wa Machigatteiru. Kan",
118            &auth,
119        )
120        .await
121        .unwrap();
122
123        let result = update_anime_list_status(anime.id, &query, &auth)
124            .await
125            .unwrap();
126        println!("{:#?}", result);
127        assert_eq!(result.num_episodes_watched, 5);
128    }
129
130    #[tokio::test]
131    async fn test_get_user_anime_list() {
132        let auth = crate::auth::tests::get_auth();
133        let query = GetUserAnimeListQuery {
134            fields: Some(ALL_ANIME_AND_MANGA_FIELDS.to_string()),
135            status: None,
136            sort: Some(SortStyle::ListScore),
137            limit: 2,
138            offset: 0,
139            nsfw: true,
140        };
141        let result = get_user_anime_list("@me", &query, &auth).await.unwrap();
142
143        print!("{:#?}", result);
144
145        assert!(!result.data.is_empty());
146    }
147}