mal/api/
mangalist.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#[derive(Clone, Debug, Serialize)]
8pub struct UpdateUserMangaStatus {
9    #[serde(skip_serializing_if = "Option::is_none")]
10    pub status: Option<UserReadStatus>,
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub is_rereading: Option<bool>,
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub score: Option<u8>,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub num_volumes_read: Option<u64>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub num_chapters_read: Option<u64>,
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub priority: Option<u8>,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub num_times_reread: Option<u8>,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub reread_value: Option<u8>,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub tags: Option<String>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub comments: Option<String>,
29}
30
31pub async fn update_manga_list_status(
32    manga_id: u64,
33    update: &UpdateUserMangaStatus,
34    auth: &OAuth,
35) -> Result<UserMangaListStatus, Error> {
36    let response = patch(
37        &format!("{}/manga/{}/my_list_status", API_URL, manga_id),
38        auth,
39        update,
40    )
41    .await?;
42    handle_response(&response)
43}
44
45pub async fn delete_manga_from_list(manga_id: u64, auth: &OAuth) -> Result<(), Error> {
46    let response = delete(
47        &format!("{}/manga/{}/my_list_status", API_URL, manga_id),
48        auth,
49    )
50    .await?;
51    if response.status.is_success() {
52        Ok(())
53    } else {
54        Err(Error::HttpError(response.status))
55    }
56}
57
58#[derive(Clone, Debug, Serialize)]
59pub struct GetUserMangaListQuery {
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub fields: Option<String>,
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub status: Option<UserReadStatus>,
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub sort: Option<SortStyle>,
66    pub limit: u64,
67    pub offset: u64,
68    pub nsfw: bool,
69}
70
71pub async fn get_user_manga_list<U: ToString>(
72    user: U,
73    query: &GetUserMangaListQuery,
74    auth: &OAuth,
75) -> Result<Page<Manga>, Error> {
76    let response = get(
77        &format!(
78            "{}/users/{}/mangalist?{}",
79            API_URL,
80            user.to_string(),
81            serde_urlencoded::to_string(query)?
82        ),
83        auth,
84    )
85    .await?;
86    handle_response(&response)
87}
88
89#[cfg(test)]
90mod test {
91    use super::*;
92    use crate::api::manga::tests::*;
93
94    #[tokio::test]
95    async fn test_delete_manga_from_list() {
96        let auth = crate::auth::tests::get_auth();
97        let manga = get_manga("Grand Blue", &auth).await.unwrap();
98        delete_manga_from_list(manga.id, &auth).await.unwrap();
99    }
100
101    #[tokio::test]
102    async fn test_update_manga_list() {
103        let auth = crate::auth::tests::get_auth();
104        let query = UpdateUserMangaStatus {
105            status: Some(UserReadStatus::Reading),
106            is_rereading: None,
107            score: Some(9),
108            num_volumes_read: None,
109            num_chapters_read: Some(62),
110            priority: None,
111            num_times_reread: None,
112            reread_value: None,
113            tags: None,
114            comments: None,
115        };
116        let manga = get_manga("Grand Blue", &auth).await.unwrap();
117        let result = update_manga_list_status(manga.id, &query, &auth)
118            .await
119            .unwrap();
120        println!("{:#?}", result);
121        assert_eq!(result.num_chapters_read, 62);
122    }
123
124    #[tokio::test]
125    async fn test_get_user_manga_list() {
126        let auth = crate::auth::tests::get_auth();
127        let query = GetUserMangaListQuery {
128            fields: Some(ALL_ANIME_AND_MANGA_FIELDS.to_string()),
129            status: None,
130            sort: None,
131            limit: 100,
132            offset: 0,
133            nsfw: true,
134        };
135        let result = get_user_manga_list("@me", &query, &auth).await.unwrap();
136
137        print!("{:#?}", result);
138
139        assert!(!result.data.is_empty());
140    }
141}