Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions wp_api/src/wp_com/client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::endpoint::{
followers_endpoint::{FollowersRequestBuilder, FollowersRequestExecutor},
freshly_pressed::{FreshlyPressedRequestBuilder, FreshlyPressedRequestExecutor},
jetpack_connection_endpoint::{
JetpackConnectionRequestBuilder, JetpackConnectionRequestExecutor,
},
Expand Down Expand Up @@ -36,6 +37,7 @@ impl UniffiWpComApiRequestBuilder {

pub struct WpComApiRequestBuilder {
followers: Arc<FollowersRequestBuilder>,
freshly_pressed: Arc<FreshlyPressedRequestBuilder>,
jetpack_connection: Arc<JetpackConnectionRequestBuilder>,
oauth2: Arc<Oauth2RequestBuilder>,
subscribers: Arc<SubscribersRequestBuilder>,
Expand All @@ -52,6 +54,7 @@ impl WpComApiRequestBuilder {
api_url_resolver,
auth_provider;
followers,
freshly_pressed,
jetpack_connection,
oauth2,
subscribers,
Expand Down Expand Up @@ -79,6 +82,7 @@ impl UniffiWpComApiClient {

pub struct WpComApiClient {
followers: Arc<FollowersRequestExecutor>,
freshly_pressed: Arc<FreshlyPressedRequestExecutor>,
jetpack_connection: Arc<JetpackConnectionRequestExecutor>,
oauth2: Arc<Oauth2RequestExecutor>,
subscribers: Arc<SubscribersRequestExecutor>,
Expand All @@ -96,6 +100,7 @@ impl WpComApiClient {
api_url_resolver,
delegate;
followers,
freshly_pressed,
jetpack_connection,
oauth2,
subscribers,
Expand All @@ -106,6 +111,7 @@ impl WpComApiClient {
}
}
api_client_generate_endpoint_impl!(WpComApi, followers);
api_client_generate_endpoint_impl!(WpComApi, freshly_pressed);
api_client_generate_endpoint_impl!(WpComApi, jetpack_connection);
api_client_generate_endpoint_impl!(WpComApi, oauth2);
api_client_generate_endpoint_impl!(WpComApi, subscribers);
Expand Down
1 change: 1 addition & 0 deletions wp_api/src/wp_com/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use strum::IntoEnumIterator;

pub mod extensions;
pub mod followers_endpoint;
pub mod freshly_pressed;
pub mod jetpack_connection_endpoint;
pub mod oauth2;
pub mod subscribers_endpoint;
Expand Down
20 changes: 20 additions & 0 deletions wp_api/src/wp_com/endpoint/freshly_pressed.rs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, all endpoint files have an _endpoint suffix, which this file should also follow.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::{
request::endpoint::{AsNamespace, DerivedRequest},
wp_com::{
WpComNamespace,
freshly_pressed::{FreshlyPressedListParams, FreshlyPressedPostList},
},
};
use wp_derive_request_builder::WpDerivedRequest;

#[derive(WpDerivedRequest)]
enum FreshlyPressedRequest {
#[get(url = "/freshly-pressed", params = &FreshlyPressedListParams, output = FreshlyPressedPostList)]
List,
}

impl DerivedRequest for FreshlyPressedRequest {
fn namespace() -> impl AsNamespace {
WpComNamespace::RestV1_2
}
}
287 changes: 287 additions & 0 deletions wp_api/src/wp_com/freshly_pressed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
use std::collections::HashMap;

use crate::{
JsonValue,
date::WpGmtDateTime,
posts::PostId,
url_query::{
AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap,
},
users::UserId,
wp_com::WpComSiteId,
};
use serde::{Deserialize, Serialize};
use strum_macros::IntoStaticStr;
use wp_serde_helper::{
deserialize_empty_array_or_hashmap, deserialize_false_or_string, deserialize_u64_or_none,
};

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedPostList {
pub date_range: FreshlyPressedDateRange,
pub number: u32,
pub posts: Vec<FreshlyPressedPost>,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedDateRange {
pub before: WpGmtDateTime,
pub after: WpGmtDateTime,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedPost {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Freshly Pressed" seemingly uses the same response format as all other response streams in Reader: site, tags, feeds, discover. I suggest generalizing it from the start even if we don't end up using it everywhere originally.

#[serde(rename = "ID")]
pub id: PostId,
#[serde(alias = "site_ID")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless we specifically need to alias, we should be consistent and use rename everywhere.

pub site_id: WpComSiteId,
pub author: FreshlyPressedAuthor,
pub date: String,
pub modified: String,
pub title: String,
#[serde(rename = "URL")]
pub url: String,
#[serde(rename = "short_URL")]
pub short_url: String,
pub content: String,
pub excerpt: String,
pub slug: String,
pub guid: String,
pub status: String,
pub sticky: bool,
pub password: String,
#[serde(deserialize_with = "deserialize_u64_or_none")]
pub parent: Option<u64>,
pub r#type: String,
pub likes_enabled: bool,
pub sharing_enabled: bool,
pub like_count: u32,
pub i_like: bool,
pub is_reblogged: bool,
pub is_following: bool,
#[serde(rename = "global_ID")]
pub global_id: String,
pub featured_image: String,
pub post_thumbnail: Option<FreshlyPressedPostThumbnail>,
pub format: String,
// pub geo: bool // TODO: need sample data to figure out the shape of this
pub menu_order: u32,
pub page_template: String,
#[serde(rename = "publicize_URLs")]
pub publicize_urls: Vec<String>,
#[serde(deserialize_with = "deserialize_empty_array_or_hashmap")]
pub terms: HashMap<String, HashMap<String, FreshlyPressedTerm>>,
#[serde(deserialize_with = "deserialize_empty_array_or_hashmap")]
pub tags: HashMap<String, FreshlyPressedTerm>,
#[serde(deserialize_with = "deserialize_empty_array_or_hashmap")]
pub categories: HashMap<String, FreshlyPressedTerm>,
#[serde(deserialize_with = "deserialize_empty_array_or_hashmap")]
pub attachments: HashMap<String, FreshlyPressedAttachment>,
pub attachment_count: u64,
pub metadata: Vec<FreshlyPressedKeyValuePair>,
pub meta: FreshlyPressedObjectMeta,
pub capabilities: HashMap<String, bool>,
#[serde(alias = "other_URLs")]
pub other_urls: HashMap<String, String>,
#[serde(alias = "pseudo_ID")]
pub pseudo_id: String,
pub is_external: bool,
pub site_name: String,
#[serde(alias = "site_URL")]
pub site_url: String,
pub site_is_private: bool,
#[serde(deserialize_with = "deserialize_empty_array_or_hashmap")]
pub site_icon: HashMap<String, String>,
pub featured_media: HashMap<String, String>,
#[serde(alias = "feed_ID")]
pub feed_id: u64,
#[serde(alias = "feed_URL")]
pub feed_url: String,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedPostThumbnail {
#[serde(rename = "ID")]
pub id: u64,
#[serde(rename = "URL")]
pub url: String,
pub guid: String,
pub mime_type: String,
pub width: u32,
pub height: u32,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedTerm {
#[serde(rename = "ID")]
pub id: u64,
pub name: String,
pub slug: String,
pub description: String,
pub post_count: u32,
pub parent: Option<u64>,
pub meta: FreshlyPressedObjectMeta,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedObjectMeta {
pub links: HashMap<String, String>,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedKeyValuePair {
pub id: String,
pub key: String,
pub value: JsonValue,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedAttachment {
#[serde(alias = "ID")]
pub id: u64,
#[serde(alias = "URL")]
pub url: String,
pub guid: String,
pub date: String,
#[serde(alias = "post_ID")]
pub post_id: u64,
#[serde(alias = "author_ID")]
pub author_id: u64,
pub file: String,
pub mime_type: String,
pub extension: String,
pub title: String,
pub caption: String,
pub description: String,
pub alt: String,
pub thumbnails: HashMap<String, String>,
pub height: u32,
pub width: u32,
pub exif: FreshlyPressedAttachmentExifData,
pub meta: FreshlyPressedObjectMeta,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedAttachmentExifData {
pub aperture: String,
pub credit: String,
pub camera: String,
pub caption: String,
pub created_timestamp: String,
pub copyright: String,
pub focal_length: String,
pub iso: String,
pub shutter_speed: String,
pub title: String,
pub orientation: String,
pub keywords: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedAuthor {
#[serde(rename = "ID")]
pub id: UserId,
pub login: String,
#[serde(default, deserialize_with = "deserialize_false_or_string")]
pub email: Option<String>,
pub name: String,
pub first_name: String,
pub last_name: String,
pub nice_name: String,
#[serde(alias = "URL")]
pub url: String,
#[serde(alias = "avatar_URL")]
pub avatar_url: String,
#[serde(alias = "profile_URL")]
pub profile_url: String,
#[serde(alias = "site_ID", deserialize_with = "deserialize_u64_or_none")]
pub site_id: Option<u64>,
pub has_avatar: bool,
pub wpcom_id: u64,
pub wpcom_login: String,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedDiscussionSettings {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am not mistaken, a discussion field needs to be added to FreshlyPressedPost and use this struct. At least, the sample json used in tests seem to include it.

pub comments_open: bool,
pub comment_status: String,
pub pings_open: bool,
pub ping_status: String,
pub comment_count: u32,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct FreshlyPressedEditorialSettings {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be unused.

pub blog_id: String,
pub post_id: String,
pub image: String,
pub custom_headline: String,
pub custom_blog_title: String,

pub displayed_on: WpGmtDateTime,
pub picked_on: WpGmtDateTime,
pub highlight_topic: String,
pub highlight_topic_title: String,
pub screen_offset: String,
pub blog_name: String,
pub site_id: String,
}

#[derive(Debug, Default, Serialize, PartialEq, Eq, uniffi::Record)]
pub struct FreshlyPressedListParams {
#[uniffi(default = None)]
pub number: Option<u32>,
#[uniffi(default = None)]
pub page: Option<u32>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, IntoStaticStr)]
enum FreshlyPressedListParamsField {
#[strum(serialize = "number")]
Number,
#[strum(serialize = "page")]
Page,
}

impl AppendUrlQueryPairs for FreshlyPressedListParams {
fn append_query_pairs(&self, query_pairs_mut: &mut QueryPairs) {
query_pairs_mut
.append_option_query_value_pair(
FreshlyPressedListParamsField::Number,
self.number.as_ref(),
)
.append_option_query_value_pair(
FreshlyPressedListParamsField::Page,
self.page.as_ref(),
);
}
}

impl FromUrlQueryPairs for FreshlyPressedListParams {
fn from_url_query_pairs(query_pairs: UrlQueryPairsMap) -> Option<Self> {
Some(Self {
number: query_pairs.get(FreshlyPressedListParamsField::Number),
page: query_pairs.get(FreshlyPressedListParamsField::Page),
})
}

fn supports_pagination() -> bool {
true
}
}
Comment on lines +238 to +271
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should no longer be necessary and should be replaced with the new macros you've reviewed yesterday.


#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_freshly_pressed_post_deserialization() {
let json = include_str!("../../tests/wpcom/freshly_pressed/post-list-1.json");
let conversation: FreshlyPressedPostList =
serde_json::from_str(json).expect("Failed to deserialize freshly pressed post list");
assert_eq!(conversation.number, 10);
assert_eq!(conversation.posts[0].id, crate::posts::PostId(16283));
assert_eq!(conversation.posts[0].site_id, 121838035.into());
assert_eq!(conversation.posts[0].author.id, crate::users::UserId(1));
}
}
Loading