1use super::model::*;
2use super::Error;
3use super::{get, handle_response, API_URL};
4use crate::auth::OAuth;
5use serde::Serialize;
6
7#[derive(Clone, Debug, Serialize)]
8pub struct GetMangaListQuery {
9 pub q: String,
10 pub limit: u64,
11 pub offset: u64,
12 pub nsfw: bool,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub fields: Option<String>,
15}
16
17pub async fn get_manga_list(query: &GetMangaListQuery, auth: &OAuth) -> Result<Page<Manga>, Error> {
18 let response = get(
19 &format! {"{}/manga?{}", API_URL, serde_urlencoded::to_string(query)?},
20 auth,
21 )
22 .await?;
23 handle_response(&response)
24}
25
26#[derive(Clone, Debug, Serialize)]
27pub struct GetMangaDetailQuery {
28 #[serde(skip_serializing_if = "Option::is_none")]
29 pub fields: Option<String>,
30 pub nsfw: bool,
31}
32
33pub async fn get_manga_details(
34 manga_id: u64,
35 query: &GetMangaDetailQuery,
36 auth: &OAuth,
37) -> Result<Manga, Error> {
38 let response = get(
39 &format!(
40 "{}/manga/{}?{}",
41 API_URL,
42 manga_id,
43 serde_urlencoded::to_string(query)?
44 ),
45 auth,
46 )
47 .await?;
48 handle_response(&response)
49}
50
51#[derive(Clone, Debug, Serialize)]
52pub struct GetMangaRankingQuery {
53 pub ranking_type: MangaRankingType,
54 pub limit: u64,
55 pub offset: u64,
56 pub nsfw: bool,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub fields: Option<String>,
59}
60
61pub async fn get_manga_ranking(
62 query: &GetMangaRankingQuery,
63 auth: &OAuth,
64) -> Result<Ranking<RankingMangaPair>, Error> {
65 let response = get(
66 &format!(
67 "{}/manga/ranking?{}",
68 API_URL,
69 serde_urlencoded::to_string(query)?
70 ),
71 auth,
72 )
73 .await?;
74 handle_response(&response)
75}
76
77#[cfg(test)]
78pub mod tests {
79 use super::*;
80
81 pub async fn get_manga<T: ToString>(q: T, auth: &OAuth) -> Result<Manga, Error> {
82 let manga_query = GetMangaListQuery {
83 q: q.to_string(),
84 limit: 4,
85 offset: 0,
86 nsfw: false,
87 fields: Some(ALL_ANIME_AND_MANGA_FIELDS.to_string()),
88 };
89 let manga_list = get_manga_list(&manga_query, auth).await.unwrap();
90 let manga = manga_list.data.first().unwrap().node.clone();
91 Ok(manga)
92 }
93
94 #[tokio::test]
95 async fn test_get_manga_list() {
96 let auth = crate::auth::tests::get_auth();
97 let query = GetMangaListQuery {
98 q: "Kaguya-Sama Wa Kokurasetai".to_string(),
99 limit: 2,
100 offset: 0,
101 nsfw: false,
102 fields: Some(ALL_ANIME_AND_MANGA_FIELDS.to_string()),
103 };
104 let result = get_manga_list(&query, &auth).await.unwrap();
105 println!("{:#?}", result);
106 assert!(!result.data.is_empty());
107 }
108
109 #[tokio::test]
110 async fn test_get_manga_details() {
111 let auth = crate::auth::tests::get_auth();
112 let query = GetMangaDetailQuery {
113 fields: Some(ALL_ANIME_AND_MANGA_FIELDS.to_string()),
114 nsfw: false,
115 };
116
117 let manga = get_manga("Kaguya-Sama Wa Kokurasetai", &auth)
118 .await
119 .unwrap();
120 let result = get_manga_details(manga.id, &query, &auth).await.unwrap();
121 println!("{:#?}", result);
122 assert_eq!(result.title, manga.title);
123 }
124
125 #[tokio::test]
126 async fn test_get_manga_ranking() {
127 let auth = crate::auth::tests::get_auth();
128 let query = GetMangaRankingQuery {
129 ranking_type: MangaRankingType::All,
130 limit: 100,
131 offset: 0,
132 nsfw: false,
133 fields: Some(ALL_ANIME_AND_MANGA_FIELDS.to_string()),
134 };
135 let result = get_manga_ranking(&query, &auth).await.unwrap();
136 println!("{:#?}", result);
137 assert!(!result.data.is_empty());
138 }
139}