dynasty_api/
recent_chapter.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{tag::TagItem, DynastyReaderRoute, DYNASTY_READER_BASE};
4
5/// A configuration to get a [RecentChapter]
6#[allow(missing_docs)]
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct RecentChapterConfig {
9    pub page_number: u64,
10}
11
12impl std::default::Default for RecentChapterConfig {
13    fn default() -> Self {
14        RecentChapterConfig { page_number: 1 }
15    }
16}
17
18impl DynastyReaderRoute for RecentChapterConfig {
19    fn request_builder(
20        &self,
21        client: &reqwest::Client,
22        url: reqwest::Url,
23    ) -> reqwest::RequestBuilder {
24        client.get(url).query(&[("page", self.page_number)])
25    }
26
27    fn request_url(&self) -> reqwest::Url {
28        DYNASTY_READER_BASE.join("chapters/added.json").unwrap()
29    }
30}
31
32/// A wrapper around Dynasty Reader's recently added chapters
33///
34/// <https://dynasty-scans.com/chapters/added>
35#[allow(missing_docs)]
36#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
37pub struct RecentChapter {
38    pub items: Vec<RecentChapterItem>,
39    pub page_number: u64,
40    pub max_page_number: u64,
41}
42
43impl<'de> Deserialize<'de> for RecentChapter {
44    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45    where
46        D: serde::Deserializer<'de>,
47    {
48        #[derive(Deserialize)]
49        struct RecentWrapper {
50            chapters: Vec<RecentChapterItem>,
51            current_page: u64,
52            total_pages: u64,
53        }
54
55        let wrapper: RecentWrapper = Deserialize::deserialize(deserializer)?;
56
57        let RecentWrapper {
58            chapters: items,
59            current_page: page_number,
60            total_pages: max_page_number,
61        } = wrapper;
62
63        Ok(RecentChapter {
64            items,
65            max_page_number,
66            page_number,
67        })
68    }
69}
70
71/// A Dynasty Reader's recently added chapters item
72#[allow(missing_docs)]
73#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
74pub struct RecentChapterItem {
75    pub title: String,
76    pub series: Option<String>,
77    pub permalink: String,
78    pub tags: Vec<TagItem>,
79}
80
81#[cfg(test)]
82mod tests {
83    use anyhow::Result;
84
85    use crate::test_utils::tryhard_configs;
86
87    use super::*;
88
89    #[tokio::test]
90    #[ignore = "requires internet"]
91    async fn response_structure() -> Result<()> {
92        let configs = (1..5).map(|page_number| RecentChapterConfig { page_number });
93
94        tryhard_configs(configs, |client, config| client.recent(config)).await?;
95
96        Ok(())
97    }
98}