orly/
models.rs

1use reqwest::Url;
2use serde::{de::Error, Deserialize, Deserializer};
3use std::result::Result as StdResult;
4
5fn parse_url<'de, D>(deserializer: D) -> StdResult<Url, D::Error>
6where
7    D: Deserializer<'de>,
8{
9    let s: &str = Deserialize::deserialize(deserializer)?;
10    Url::parse(s).map_err(D::Error::custom)
11}
12
13fn parse_vec_url<'de, D>(deserializer: D) -> StdResult<Vec<Url>, D::Error>
14where
15    D: Deserializer<'de>,
16{
17    let vec: Vec<&str> = Deserialize::deserialize(deserializer)?;
18    vec.into_iter()
19        .map(Url::parse)
20        .collect::<std::result::Result<_, _>>()
21        .map_err(D::Error::custom)
22}
23
24fn to_xhtml<'de, D>(deserializer: D) -> StdResult<String, D::Error>
25where
26    D: Deserializer<'de>,
27{
28    let s: String = Deserialize::deserialize(deserializer)?;
29    Ok(s.replace(".html", ".xhtml"))
30}
31
32#[derive(Deserialize, Debug)]
33pub(crate) struct BillingInfo {
34    pub subscription: SubscriptionInfo,
35    pub trial: TrialInfo,
36}
37
38#[derive(Deserialize, Debug, Default)]
39pub(crate) struct SubscriptionInfo {
40    pub cancellation_date: Option<String>,
41}
42
43#[derive(Deserialize, Debug, Default)]
44pub(crate) struct TrialInfo {
45    pub trial_expiration_date: Option<String>,
46}
47
48#[derive(Deserialize, Debug)]
49pub(crate) struct Credentials {
50    pub logged_in: bool,
51}
52
53#[derive(Deserialize, Debug)]
54pub(crate) struct LoginLookup {
55    pub password_login_allowed: bool,
56}
57
58#[derive(Deserialize, Debug)]
59pub struct Author {
60    pub name: String,
61}
62
63#[derive(Deserialize, Debug)]
64pub struct Subject {
65    pub name: String,
66}
67
68#[derive(Deserialize, Debug)]
69pub struct Publisher {
70    pub name: String,
71}
72
73#[derive(Deserialize, Debug)]
74pub struct Book {
75    pub identifier: String,
76    pub isbn: String,
77    #[serde(deserialize_with = "parse_url")]
78    pub cover: Url,
79    pub chapter_list: String,
80    pub toc: String,
81    pub flat_toc: String,
82    pub title: String,
83    pub source: String,
84    pub pagecount: usize,
85    pub authors: Vec<Author>,
86    pub subjects: Vec<Subject>,
87    pub publishers: Vec<Publisher>,
88    pub description: String,
89    pub issued: String,
90    #[serde(default)]
91    pub rights: String,
92    pub language: String,
93}
94
95#[derive(Deserialize, Debug)]
96pub struct Stylesheet {
97    pub full_path: String,
98    #[serde(deserialize_with = "parse_url")]
99    pub url: Url,
100    pub original_url: String,
101}
102
103#[derive(Deserialize, Debug)]
104pub struct ChapterNode {
105    pub url: String,
106    pub web_url: String,
107    pub title: String,
108}
109
110#[derive(Deserialize, Debug)]
111pub struct ChapterMeta {
112    #[serde(deserialize_with = "parse_url")]
113    pub asset_base_url: Url,
114    pub title: String,
115    #[serde(deserialize_with = "to_xhtml")]
116    pub filename: String,
117    pub images: Vec<String>,
118    pub stylesheets: Vec<Stylesheet>,
119    #[serde(deserialize_with = "parse_vec_url")]
120    pub site_styles: Vec<Url>,
121    #[serde(deserialize_with = "parse_url", rename = "content")]
122    pub content_url: Url,
123    #[serde(default)]
124    pub position: usize,
125}
126
127#[derive(Debug)]
128pub struct Chapter {
129    pub meta: ChapterMeta,
130    pub content: String,
131}
132
133#[derive(Deserialize, Debug)]
134pub(crate) struct ChaptersResponse {
135    pub count: usize,
136    pub results: Vec<ChapterMeta>,
137}
138
139#[derive(Deserialize, Debug)]
140pub struct TocElement {
141    pub depth: usize,
142    pub url: String,
143    pub minutes_required: f64,
144    pub fragment: String,
145    pub filename: String,
146    pub natural_key: Vec<String>,
147    pub label: String,
148    pub full_path: String,
149    #[serde(deserialize_with = "to_xhtml")]
150    pub href: String,
151    pub id: String,
152    pub media_type: String,
153    pub children: Vec<TocElement>,
154}