1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use crate::models::Resource;
use crate::{OpenLibraryClient, OpenLibraryError, OpenLibraryErrorResponse};
use chrono::{DateTime, Utc};
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize};
#[derive(Serialize)]
pub struct LoginRequest {
pub username: String,
pub password: String,
}
pub enum ReadingLogResponseWrapper {
Success(ReadingLogResponse),
Err(OpenLibraryErrorResponse),
}
impl<'de> Deserialize<'de> for ReadingLogResponseWrapper {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let json: serde_json::Value = Deserialize::deserialize(deserializer)?;
match json.get("error") {
None => Ok(ReadingLogResponseWrapper::Success(
serde_json::from_value(json).map_err(D::Error::custom)?,
)),
Some(_) => Ok(ReadingLogResponseWrapper::Err(
serde_json::from_value(json).map_err(D::Error::custom)?,
)),
}
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Session {
cookie: String,
username: String,
}
impl Session {
pub fn from(cookie: String, username: String) -> Self {
Session { cookie, username }
}
pub fn cookie(&self) -> &String {
&self.cookie
}
pub fn username(&self) -> &String {
&self.username
}
}
#[derive(Clone)]
pub enum ReadingLog {
AlreadyRead,
CurrentlyReading,
WantToRead,
}
impl ReadingLog {
pub fn url(&self) -> &str {
match self {
ReadingLog::AlreadyRead => "already-read.json",
ReadingLog::CurrentlyReading => "currently-reading.json",
ReadingLog::WantToRead => "want-to-read.json",
}
}
pub async fn retrieve_for(
&self,
client: &OpenLibraryClient,
username: String,
) -> Result<Vec<ReadingLogEntry>, OpenLibraryError> {
match self {
ReadingLog::AlreadyRead => client.account.get_already_read(username).await,
ReadingLog::CurrentlyReading => client.account.get_currently_reading(username).await,
ReadingLog::WantToRead => client.account.get_want_to_read(username).await,
}
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ReadingLogResponse {
pub page: i16,
pub reading_log_entries: Vec<ReadingLogEntry>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ReadingLogEntry {
pub work: ReadingLogWork,
pub logged_edition: Resource,
#[serde(with = "crate::format::datetime")]
pub logged_date: DateTime<Utc>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ReadingLogWork {
pub title: String,
pub key: Resource,
pub author_keys: Vec<Resource>,
pub author_names: Vec<String>,
pub first_publish_year: Option<i32>,
pub lending_edition_s: Option<String>,
pub edition_key: Vec<String>,
pub cover_id: Option<i32>,
pub cover_edition_key: Option<String>,
}