|
| 1 | +use std::collections::HashMap; |
| 2 | + |
| 3 | +use crate::{ |
| 4 | + date::WpGmtDateTime, posts::PostId, url_query::{ |
| 5 | + AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, |
| 6 | + }, users::UserId, wp_com::WpComSiteId, JsonValue |
| 7 | +}; |
| 8 | +use serde::{Deserialize, Serialize}; |
| 9 | +use strum_macros::IntoStaticStr; |
| 10 | +use wp_serde_helper::{deserialize_false_or_string, deserialize_u64_or_none,deserialize_empty_array_or_hashmap}; |
| 11 | + |
| 12 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 13 | +pub struct FreshlyPressedPostList { |
| 14 | + pub date_range: FreshlyPressedDateRange, |
| 15 | + pub number: u32, |
| 16 | + pub posts: Vec<FreshlyPressedPost>, |
| 17 | +} |
| 18 | + |
| 19 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 20 | +pub struct FreshlyPressedDateRange { |
| 21 | + pub before: WpGmtDateTime, |
| 22 | + pub after: WpGmtDateTime, |
| 23 | +} |
| 24 | + |
| 25 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 26 | +pub struct FreshlyPressedPost { |
| 27 | + #[serde(rename = "ID")] |
| 28 | + pub id: PostId, |
| 29 | + #[serde(alias = "site_ID")] |
| 30 | + pub site_id: WpComSiteId, |
| 31 | + pub author: FreshlyPressedAuthor, |
| 32 | + pub date: String, |
| 33 | + pub modified: String, |
| 34 | + pub title: String, |
| 35 | + #[serde(rename = "URL")] |
| 36 | + pub url: String, |
| 37 | + #[serde(rename = "short_URL")] |
| 38 | + pub short_url: String, |
| 39 | + pub content: String, |
| 40 | + pub excerpt: String, |
| 41 | + pub slug: String, |
| 42 | + pub guid: String, |
| 43 | + pub status: String, |
| 44 | + pub sticky: bool, |
| 45 | + pub password: String, |
| 46 | + #[serde(deserialize_with = "deserialize_u64_or_none")] |
| 47 | + pub parent: Option<u64>, |
| 48 | + pub r#type: String, |
| 49 | + pub likes_enabled: bool, |
| 50 | + pub sharing_enabled: bool, |
| 51 | + pub like_count: u32, |
| 52 | + pub i_like: bool, |
| 53 | + pub is_reblogged: bool, |
| 54 | + pub is_following: bool, |
| 55 | + #[serde(rename = "global_ID")] |
| 56 | + pub global_id: String, |
| 57 | + pub featured_image: String, |
| 58 | + pub post_thumbnail: Option<FreshlyPressedPostThumbnail>, |
| 59 | + pub format: String, |
| 60 | + // pub geo: bool // TODO: need sample data to figure out the shape of this |
| 61 | + pub menu_order: u32, |
| 62 | + pub page_template: String, |
| 63 | + #[serde(rename = "publicize_URLs")] |
| 64 | + pub publicize_urls: Vec<String>, |
| 65 | + #[serde(deserialize_with = "deserialize_empty_array_or_hashmap")] |
| 66 | + pub terms: HashMap<String, HashMap<String, FreshlyPressedTerm>>, |
| 67 | + #[serde(deserialize_with = "deserialize_empty_array_or_hashmap")] |
| 68 | + pub tags: HashMap<String, FreshlyPressedTerm>, |
| 69 | + #[serde(deserialize_with = "deserialize_empty_array_or_hashmap")] |
| 70 | + pub categories: HashMap<String, FreshlyPressedTerm>, |
| 71 | + #[serde(deserialize_with = "deserialize_empty_array_or_hashmap")] |
| 72 | + pub attachments: HashMap<String, FreshlyPressedAttachment>, |
| 73 | + pub attachment_count: u64, |
| 74 | + pub metadata: Vec<FreshlyPressedKeyValuePair>, |
| 75 | + pub meta: FreshlyPressedObjectMeta, |
| 76 | + pub capabilities: HashMap<String, bool>, |
| 77 | + #[serde(alias = "other_URLs")] |
| 78 | + pub other_urls: HashMap<String, String>, |
| 79 | + #[serde(alias = "pseudo_ID")] |
| 80 | + pub pseudo_id: String, |
| 81 | + pub is_external: bool, |
| 82 | + pub site_name: String, |
| 83 | + #[serde(alias = "site_URL")] |
| 84 | + pub site_url: String, |
| 85 | + pub site_is_private: bool, |
| 86 | + #[serde(deserialize_with = "deserialize_empty_array_or_hashmap")] |
| 87 | + pub site_icon: HashMap<String, String>, |
| 88 | + pub featured_media: HashMap<String, String>, |
| 89 | + #[serde(alias = "feed_ID")] |
| 90 | + pub feed_id: u64, |
| 91 | + #[serde(alias = "feed_URL")] |
| 92 | + pub feed_url: String, |
| 93 | +} |
| 94 | + |
| 95 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 96 | +pub struct FreshlyPressedPostThumbnail { |
| 97 | + #[serde(rename = "ID")] |
| 98 | + pub id: u64, |
| 99 | + #[serde(rename = "URL")] |
| 100 | + pub url: String, |
| 101 | + pub guid: String, |
| 102 | + pub mime_type: String, |
| 103 | + pub width: u32, |
| 104 | + pub height: u32, |
| 105 | +} |
| 106 | + |
| 107 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 108 | +pub struct FreshlyPressedTerm { |
| 109 | + #[serde(rename = "ID")] |
| 110 | + pub id: u64, |
| 111 | + pub name: String, |
| 112 | + pub slug: String, |
| 113 | + pub description: String, |
| 114 | + pub post_count: u32, |
| 115 | + pub parent: Option<u64>, |
| 116 | + pub meta: FreshlyPressedObjectMeta, |
| 117 | +} |
| 118 | + |
| 119 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 120 | +pub struct FreshlyPressedObjectMeta { |
| 121 | + pub links: HashMap<String, String>, |
| 122 | +} |
| 123 | + |
| 124 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 125 | +pub struct FreshlyPressedKeyValuePair{ |
| 126 | + pub id: String, |
| 127 | + pub key: String, |
| 128 | + pub value: JsonValue, |
| 129 | +} |
| 130 | + |
| 131 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 132 | +pub struct FreshlyPressedAttachment { |
| 133 | + #[serde(alias = "ID")] |
| 134 | + pub id: u64, |
| 135 | + #[serde(alias = "URL")] |
| 136 | + pub url: String, |
| 137 | + pub guid: String, |
| 138 | + pub date: String, |
| 139 | + #[serde(alias = "post_ID")] |
| 140 | + pub post_id: u64, |
| 141 | + #[serde(alias = "author_ID")] |
| 142 | + pub author_id: u64, |
| 143 | + pub file: String, |
| 144 | + pub mime_type: String, |
| 145 | + pub extension: String, |
| 146 | + pub title: String, |
| 147 | + pub caption: String, |
| 148 | + pub description: String, |
| 149 | + pub alt: String, |
| 150 | + pub thumbnails: HashMap<String, String>, |
| 151 | + pub height: u32, |
| 152 | + pub width: u32, |
| 153 | + pub exif: FreshlyPressedAttachmentExifData, |
| 154 | + pub meta: FreshlyPressedObjectMeta, |
| 155 | +} |
| 156 | + |
| 157 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 158 | +pub struct FreshlyPressedAttachmentExifData { |
| 159 | + pub aperture: String, |
| 160 | + pub credit: String, |
| 161 | + pub camera: String, |
| 162 | + pub caption: String, |
| 163 | + pub created_timestamp: String, |
| 164 | + pub copyright: String, |
| 165 | + pub focal_length: String, |
| 166 | + pub iso: String, |
| 167 | + pub shutter_speed: String, |
| 168 | + pub title: String, |
| 169 | + pub orientation: String, |
| 170 | + pub keywords: Vec<String>, |
| 171 | +} |
| 172 | + |
| 173 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 174 | +pub struct FreshlyPressedAuthor { |
| 175 | + #[serde(rename = "ID")] |
| 176 | + pub id: UserId, |
| 177 | + pub login: String, |
| 178 | + #[serde(default, deserialize_with = "deserialize_false_or_string")] |
| 179 | + pub email: Option<String>, |
| 180 | + pub name: String, |
| 181 | + pub first_name: String, |
| 182 | + pub last_name: String, |
| 183 | + pub nice_name: String, |
| 184 | + #[serde(alias = "URL")] |
| 185 | + pub url: String, |
| 186 | + #[serde(alias = "avatar_URL")] |
| 187 | + pub avatar_url: String, |
| 188 | + #[serde(alias = "profile_URL")] |
| 189 | + pub profile_url: String, |
| 190 | + #[serde(alias = "site_ID", deserialize_with = "deserialize_u64_or_none")] |
| 191 | + pub site_id: Option<u64>, |
| 192 | + pub has_avatar: bool, |
| 193 | + pub wpcom_id: u64, |
| 194 | + pub wpcom_login: String, |
| 195 | +} |
| 196 | + |
| 197 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 198 | +pub struct FreshlyPressedDiscussionSettings { |
| 199 | + pub comments_open: bool, |
| 200 | + pub comment_status: String, |
| 201 | + pub pings_open: bool, |
| 202 | + pub ping_status: String, |
| 203 | + pub comment_count: u32, |
| 204 | +} |
| 205 | + |
| 206 | +#[derive(Debug, Serialize, Deserialize, uniffi::Record)] |
| 207 | +pub struct FreshlyPressedEditorialSettings { |
| 208 | + pub blog_id: String, |
| 209 | + pub post_id: String, |
| 210 | + pub image: String, |
| 211 | + pub custom_headline: String, |
| 212 | + pub custom_blog_title: String, |
| 213 | + |
| 214 | + pub displayed_on: WpGmtDateTime, |
| 215 | + pub picked_on: WpGmtDateTime, |
| 216 | + pub highlight_topic: String, |
| 217 | + pub highlight_topic_title: String, |
| 218 | + pub screen_offset: String, |
| 219 | + pub blog_name: String, |
| 220 | + pub site_id: String, |
| 221 | +} |
| 222 | + |
| 223 | +#[derive(Debug, Default, Serialize, PartialEq, Eq, uniffi::Record)] |
| 224 | +pub struct FreshlyPressedListParams { |
| 225 | + #[uniffi(default = None)] |
| 226 | + pub number: Option<u32>, |
| 227 | + #[uniffi(default = None)] |
| 228 | + pub page: Option<u32>, |
| 229 | +} |
| 230 | + |
| 231 | +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, IntoStaticStr)] |
| 232 | +enum FreshlyPressedListParamsField { |
| 233 | + #[strum(serialize = "number")] |
| 234 | + Number, |
| 235 | + #[strum(serialize = "page")] |
| 236 | + Page, |
| 237 | +} |
| 238 | + |
| 239 | +impl AppendUrlQueryPairs for FreshlyPressedListParams { |
| 240 | + fn append_query_pairs(&self, query_pairs_mut: &mut QueryPairs) { |
| 241 | + query_pairs_mut |
| 242 | + .append_option_query_value_pair(FreshlyPressedListParamsField::Number, self.number.as_ref()) |
| 243 | + .append_option_query_value_pair(FreshlyPressedListParamsField::Page, self.page.as_ref()); |
| 244 | + } |
| 245 | +} |
| 246 | + |
| 247 | +impl FromUrlQueryPairs for FreshlyPressedListParams { |
| 248 | + fn from_url_query_pairs(query_pairs: UrlQueryPairsMap) -> Option<Self> { |
| 249 | + Some(Self { |
| 250 | + number: query_pairs.get(FreshlyPressedListParamsField::Number), |
| 251 | + page: query_pairs.get(FreshlyPressedListParamsField::Page), |
| 252 | + }) |
| 253 | + } |
| 254 | + |
| 255 | + fn supports_pagination() -> bool { |
| 256 | + true |
| 257 | + } |
| 258 | +} |
| 259 | + |
| 260 | + |
| 261 | +#[cfg(test)] |
| 262 | +mod tests { |
| 263 | + use super::*; |
| 264 | + |
| 265 | + #[test] |
| 266 | + fn test_freshly_pressed_post_deserialization() { |
| 267 | + let json = include_str!("../../tests/wpcom/freshly_pressed/post-list-1.json"); |
| 268 | + let conversation: FreshlyPressedPostList = |
| 269 | + serde_json::from_str(json).expect("Failed to deserialize freshly pressed post list"); |
| 270 | + assert_eq!(conversation.number, 10); |
| 271 | + assert_eq!(conversation.posts[0].id, crate::posts::PostId(16283)); |
| 272 | + assert_eq!(conversation.posts[0].site_id, crate::wp_com::WpComSiteId(121838035)); |
| 273 | + assert_eq!(conversation.posts[0].author.id, crate::users::UserId(1)); |
| 274 | + } |
| 275 | +} |
0 commit comments