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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use crate::utils::serde::parse_intbool; use super::annotations::Annotations; use super::common::ID; use super::tags::Tags; /// type alias: a list of entries as returned from some endpoints pub type Entries = Vec<Entry>; /// A struct representing an entry from wallabag (a full saved article including /// all annotations and tags; annotations and tags do not need to be requested /// separately). /// /// Most fields are controlled by the server. When creating an entry, the server will send a /// request to the given url and use the response to populate many of the fields. This response is /// what `headers`, `http_status`, `mimetype`, etc. are referring to. #[derive(Deserialize, Serialize, Debug)] pub struct Entry { /// Annotation objects for this entry. pub annotations: Option<Annotations>, /// Content. Should be HTML if present. pub content: Option<String>, /// The timestamp of when the entry was created on the server. pub created_at: DateTime<Utc>, /// The resolved domain name of the url. Could be None if the server couldn't resolve the url. pub domain_name: Option<String>, /// A map of header name -> header value. These appear to be headers from the original source /// url. pub headers: Option<HashMap<String, String>>, /// I'm guessing this is the status the server got when retrieving the content from the url. pub http_status: Option<String>, /// ID of the entry. Should be an integer. Should also be unique, so can use this directly as /// the local id if storing the entry in a DB. pub id: ID, /// The archived (or read) status of the entry. These boolean options are sometimes represented /// as 0 or 1 from the API, which makes parsing in a strongly typed language annoying. #[serde(deserialize_with = "parse_intbool")] pub is_archived: bool, /// The public shared status of the entry. If this is true, then there should be a public link /// to this exact entry on the server. The link will be based around the value of the `uid` /// field and (TODO: confirm if this can be relied on) formatted as BASE_URL/share/UID. #[serde(deserialize_with = "parse_intbool")] pub is_public: bool, /// The starred status of the entry. #[serde(deserialize_with = "parse_intbool")] pub is_starred: bool, /// The language of the entry - probably generated by the server from inspecting the response. pub language: Option<String>, /// The mimetype of the entry - probably generated by the server from inspecting the response. /// Not sure about the support status for other mimetypes. Observed behaviour suggests that the /// server converts everything to HTML - eg. a text/plain mimetype content will be plain text /// surrounded by `<pre>` tags. pub mimetype: Option<String>, /// Supposedly the original url given will be stored here. If a shortened link is submitted to /// the server, the short link will be here, but the resolved link will be in URL. Observed /// behaviour is that this field is never set. pub origin_url: Option<String>, /// Optional url for an image related to the entry. Eg. for displaying as a background image to /// the entry tile. pub preview_picture: Option<String>, /// Data about when the entry was published (scraped from the original web page). pub published_at: Option<DateTime<Utc>>, /// Data about who published the entry (scraped from the original web page). pub published_by: Option<Vec<Option<String>>>, /// Estimated reading time in minutes. Generated by the server, probably based off your set /// reading speed or a default. pub reading_time: u32, /// Timestamp of when the entry was starred, if it is starred. Unstarring an entry sets this to /// None. pub starred_at: Option<DateTime<Utc>>, /// A list of tag objects associated with this entry. pub tags: Tags, /// An optional title for the entry. pub title: Option<String>, /// This will be only set by the server as a unique id to identify the entry if it has been /// shared. For example if you share via public link on framabag and the uid is FOO, then the /// public url will be framabag.org/share/FOO pub uid: Option<String>, /// Timestamp when the entry was last updated. This is bumped for any change to any field /// attached to the entry except for annotations. /// /// TODO: check if entry updates if a tag is globally edited (eg. renamed) pub updated_at: DateTime<Utc>, /// Resolved url of the entry. If the origin_url redirected to a different url (eg. via a /// shortened link), the final url will be stored here. pub url: Option<String>, /// Email of the user who owns this entry. Currently `user_*` fields are redundant since you /// can only access entries that belong to you. Entry sharing between users is planned for the /// future so this may become relevant soon. pub user_email: String, /// ID of the user who owns this entry. pub user_id: ID, /// username of the user who owns this entry. pub user_name: String, } /// A struct representing a deleted entry from wallabag (a full saved article including /// annotations and tags). The only difference from the full entry is that this /// doesn't have an id. Only used internally because a full entry gets /// reconstituted before being returned to the client. #[derive(Deserialize, Debug)] pub(crate) struct DeletedEntry { pub annotations: Option<Annotations>, pub content: Option<String>, pub created_at: DateTime<Utc>, pub domain_name: Option<String>, pub headers: Option<HashMap<String, String>>, pub http_status: Option<String>, #[serde(deserialize_with = "parse_intbool")] pub is_archived: bool, #[serde(deserialize_with = "parse_intbool")] pub is_public: bool, #[serde(deserialize_with = "parse_intbool")] pub is_starred: bool, pub language: Option<String>, pub mimetype: Option<String>, pub origin_url: Option<String>, pub preview_picture: Option<String>, pub published_at: Option<DateTime<Utc>>, pub published_by: Option<Vec<Option<String>>>, pub reading_time: u32, pub starred_at: Option<DateTime<Utc>>, pub tags: Tags, pub title: Option<String>, pub uid: Option<String>, pub updated_at: DateTime<Utc>, pub url: Option<String>, pub user_email: String, pub user_id: ID, pub user_name: String, } /// This is implemented so that an Entry can be used interchangeably with an ID /// for some client methods. For convenience. impl From<Entry> for ID { fn from(entry: Entry) -> Self { entry.id } } /// This is implemented so that an &Entry can be used interchangeably with an ID /// for some client methods. For convenience. impl From<&Entry> for ID { fn from(entry: &Entry) -> Self { entry.id } } /// Internal struct for retrieving a list of entries from the api when /// paginated. #[derive(Deserialize, Debug)] pub(crate) struct PaginatedEntries { pub limit: u32, pub page: u32, pub pages: u32, pub total: u32, #[serde(rename = "_embedded")] pub embedded: EmbeddedEntries, } /// Entries as stored in `PaginatedEntries`. #[derive(Deserialize, Debug)] pub(crate) struct EmbeddedEntries { pub items: Entries, } /// Represents a page of Entries returned. Includes both the payload and metadata about the page. #[derive(Debug)] pub struct EntriesPage { /// Number of entries returned per page. This is set by the server; useful to know if you're /// accepting the server default because this will inform what the server default is. pub per_page: u32, /// The current page number of results. pub current_page: u32, /// Total number of pages in the set. pub total_pages: u32, /// Total number of entries in the query set. pub total_entries: u32, /// The list of entries returned. pub entries: Entries, }