tosho_rbean/models/
common.rs

1//! A module containing some common models.
2//!
3//! If something is missing, please [open an issue](https://github.com/noaione/tosho-mango/issues/new/choose) or a [pull request](https://github.com/noaione/tosho-mango/compare).
4
5use serde::{Deserialize, Serialize};
6use tosho_macros::AutoGetter;
7
8use super::Image;
9
10/// Creator or author of a manga.
11#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize)]
12pub struct Creator {
13    /// The name of the creator.
14    name: String,
15    /// The UUID of the creator.
16    uuid: String,
17}
18
19/// Publisher of a manga.
20#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize)]
21pub struct Publisher {
22    /// The name of the publisher.
23    name: String,
24    /// The UUID of the publisher.
25    uuid: String,
26    /// The URL slug of the publisher.
27    slug: String,
28}
29
30/// A label of a manga with UUID.
31#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize)]
32pub struct Label {
33    /// The name of the label.
34    #[serde(rename = "label")]
35    name: String,
36    /// The UUID of the label.
37    uuid: String,
38}
39
40/// A sort options filters for searching.
41#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize)]
42pub struct SortOptions {
43    /// The sort type.
44    r#type: String,
45    /// The sort name.
46    name: String,
47}
48
49/// Tags available for searching.
50#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize)]
51pub struct Tag {
52    /// The name of the tag.
53    name: String,
54    /// The slug of the tag.
55    slug: String,
56}
57
58/// Genres available from [`crate::models::HomeResponse`].
59#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize)]
60pub struct HomeGenre {
61    /// The name of the genre.
62    name: String,
63    /// The tag of the genre.
64    tag: String,
65}
66
67/// A collection of manga filters.
68#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize)]
69pub struct MangaFilters {
70    /// The sort options.
71    sort_options: Vec<SortOptions>,
72    /// The available tags.
73    tags: Vec<Tag>,
74    /// The available options that can be toggled.
75    bool_options: Vec<String>,
76    /// The available publishers that can be used.
77    publishers: Vec<Publisher>,
78}
79
80/// A manga product.
81#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize)]
82pub struct Product {
83    /// The UUID of the product.
84    uuid: String,
85    /// The type of the item
86    #[serde(rename = "item_type")]
87    r#type: String,
88    /// The retail price of the product.
89    retail_price: String,
90    /// The sale price of the product.
91    sale_price: String,
92}
93
94/// A chapter range.
95#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize, PartialEq)]
96pub struct ChapterRange {
97    /// The start of the chapter range.
98    start: String,
99    /// The end of the chapter range.
100    end: String,
101}
102
103/// A chapter gap.
104#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize, PartialEq)]
105pub struct ChapterGap {
106    /// The range of the gap.
107    range: ChapterRange,
108}
109
110/// A chapter explainer, commonly used in separator.
111#[derive(Debug, Clone, Copy, AutoGetter, Serialize, Deserialize, PartialEq)]
112pub struct ChapterExplainer {
113    /// The number of chapters specified on the separator.
114    #[serde(rename = "num_chapters")]
115    count: i32,
116}
117
118/// A separator for some common chapter explainer.
119#[derive(Debug, Clone, Copy, AutoGetter, Serialize, Deserialize, PartialEq)]
120pub struct SeparatorChapterExplainer {
121    /// The index of the separator.
122    #[serde(rename = "list_index")]
123    index: i32,
124    /// The data of the separator.
125    data: ChapterExplainer,
126}
127
128/// A separator for chapter gap.
129#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize, PartialEq)]
130pub struct SeparatorChapterGap {
131    /// The index of the separator.
132    #[serde(rename = "list_index")]
133    index: i32,
134    /// The data of the separator.
135    data: ChapterGap,
136}
137
138/// A separator for chapters.
139#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
140#[serde(tag = "type")]
141pub enum Separator {
142    /// A separator for premium notice.
143    #[serde(rename = "SEPARATOR_PREMIUM_NOTICE")]
144    PremiumNotice(SeparatorChapterExplainer),
145    /// A separator for ala carte or volume purchase notice.
146    #[serde(rename = "SEPARATOR_ALC_NOTICE")]
147    AlaCarteNotice(SeparatorChapterExplainer),
148    /// A separator for chapter gap notice.
149    #[serde(rename = "SEPARATOR_CHAPTER_GAP")]
150    ChapterGap(SeparatorChapterGap),
151    /// Unknown separator.
152    #[serde(rename = "SEPARATOR_UNKNOWN")]
153    Unknown,
154}
155
156/// A volume release product.
157#[derive(Debug, Clone, AutoGetter, Serialize, Deserialize)]
158pub struct Volume {
159    /// The UUID of the volume.
160    uuid: String,
161    /// The manga UUID of the volume.
162    #[serde(rename = "manga_uuid")]
163    manga: String,
164    /// The ISBN of the volume.
165    isbn: Option<String>,
166    /// The cover image of the volume.
167    #[serde(rename = "image")]
168    cover: Image,
169    /// The title of the volume.
170    #[serde(rename = "full_name")]
171    title: String,
172    /// The short title of the volume.
173    #[serde(rename = "short_name")]
174    short_title: String,
175    /// The volume number of the volume.
176    #[serde(rename = "label")]
177    volume: String,
178    /// Is DRM free
179    #[serde(rename = "is_drm_free")]
180    drm_free: bool,
181    /// The retail/product info of the volume.
182    #[serde(rename = "product", default)]
183    retail: Option<Product>,
184    /// The order of the volume.
185    #[serde(rename = "order_number")]
186    order: i32,
187}
188
189#[cfg(test)]
190mod tests {
191    use super::*;
192
193    #[test]
194    fn test_separator_premium_notice() {
195        let json_test = r#"{
196            "type": "SEPARATOR_PREMIUM_NOTICE",
197            "list_index": 0,
198            "data": {
199                "num_chapters": 1
200            }
201        }"#;
202
203        let separator: Separator = serde_json::from_str(json_test).unwrap();
204        match separator {
205            Separator::PremiumNotice(data) => {
206                assert_eq!(data.index, 0);
207                assert_eq!(data.data.count, 1);
208            }
209            _ => panic!("Invalid separator type"),
210        }
211    }
212
213    #[test]
214    fn test_separator_alacarte_notice() {
215        let json_test = r#"{
216            "type": "SEPARATOR_ALC_NOTICE",
217            "list_index": 0,
218            "data": {
219                "num_chapters": 1
220            }
221        }"#;
222
223        let separator: Separator = serde_json::from_str(json_test).unwrap();
224        match separator {
225            Separator::AlaCarteNotice(data) => {
226                assert_eq!(data.index, 0);
227                assert_eq!(data.data.count, 1);
228            }
229            _ => panic!("Invalid separator type"),
230        }
231    }
232
233    #[test]
234    fn test_separator_chapter_gap() {
235        let json_test = r#"{
236            "type": "SEPARATOR_CHAPTER_GAP",
237            "list_index": 0,
238            "data": {
239                "range": {
240                    "start": "1",
241                    "end": "2"
242                }
243            }
244        }"#;
245
246        let separator: Separator = serde_json::from_str(json_test).unwrap();
247        match separator {
248            Separator::ChapterGap(data) => {
249                assert_eq!(data.index, 0);
250                assert_eq!(data.data.range.start, "1");
251                assert_eq!(data.data.range.end, "2");
252            }
253            _ => panic!("Invalid separator type"),
254        }
255    }
256
257    #[test]
258    fn test_separator_unknown() {
259        let json_test = r#"{
260            "type": "SEPARATOR_UNKNOWN"
261        }"#;
262
263        let separator: Separator = serde_json::from_str(json_test).unwrap();
264        assert_eq!(separator, Separator::Unknown)
265    }
266}