diff options
author | Colin Reeder <colin@vpzom.click> | 2020-11-11 22:47:11 -0700 |
---|---|---|
committer | Colin Reeder <colin@vpzom.click> | 2020-11-11 22:47:11 -0700 |
commit | 9bb065b5da31d4b1b5d212a1ca7941717f17ace5 (patch) | |
tree | ccde0bf669cd71865c48638c3d1fe76ce59a57d0 | |
parent | 0acc624f44acc4d645d25820a29da268115fd2c4 (diff) |
Include replies_count_total in post lists (#123)
-rw-r--r-- | openapi/openapi.json | 16 | ||||
-rw-r--r-- | src/routes/api/communities.rs | 5 | ||||
-rw-r--r-- | src/routes/api/mod.rs | 19 | ||||
-rw-r--r-- | src/routes/api/posts.rs | 18 | ||||
-rw-r--r-- | src/routes/api/users.rs | 14 |
5 files changed, 54 insertions, 18 deletions
diff --git a/openapi/openapi.json b/openapi/openapi.json index ee61fde..5168fbc 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -100,7 +100,7 @@ } } }, - "PostListPost": { + "SomePostInfo": { "type": "object", "required": ["id", "title", "created", "community", "score"], "properties": { @@ -134,6 +134,18 @@ "your_vote": {"$ref": "#/components/schemas/YourVote"} } }, + "PostListPost": { + "allOf": [ + {"$ref": "#/components/schemas/SomePostInfo"}, + { + "type": "object", + "required": ["replies_count_total"], + "properties": { + "replies_count_total": {"type": "integer"} + } + } + ] + }, "PostCommentInfo": { "type": "object", "required": ["id", "content_text", "content_html", "author", "created", "deleted", "replies", "has_replies", "attachments", "local"], @@ -1140,7 +1152,7 @@ "content": { "application/json": { "schema": { - "allOf": [{"$ref": "#/components/schemas/PostListPost"}], + "allOf": [{"$ref": "#/components/schemas/SomePostInfo"}], "type": "object", "required": ["approved", "local", "replies"], "properties": { diff --git a/src/routes/api/communities.rs b/src/routes/api/communities.rs index f4d919d..29bbcad 100644 --- a/src/routes/api/communities.rs +++ b/src/routes/api/communities.rs @@ -602,7 +602,7 @@ async fn route_unstable_communities_posts_list( let mut values: Vec<&(dyn tokio_postgres::types::ToSql + Sync)> = vec![&community_id, &limit]; let sql: &str = &format!( - "SELECT post.id, post.author, post.href, post.content_text, post.title, post.created, post.content_html, person.username, person.local, person.ap_id, person.avatar, (SELECT COUNT(*) FROM post_like WHERE post_like.post = post.id){} FROM post LEFT OUTER JOIN person ON (person.id = post.author) WHERE post.community = $1 AND post.approved=TRUE AND post.deleted=FALSE ORDER BY {} LIMIT $2", + "SELECT post.id, post.author, post.href, post.content_text, post.title, post.created, post.content_html, person.username, person.local, person.ap_id, person.avatar, (SELECT COUNT(*) FROM post_like WHERE post_like.post = post.id), (SELECT COUNT(*) FROM reply WHERE reply.post = post.id){} FROM post LEFT OUTER JOIN person ON (person.id = post.author) WHERE post.community = $1 AND post.approved=TRUE AND post.deleted=FALSE ORDER BY {} LIMIT $2", if let Some(user) = &include_your_for { values.push(user); ", EXISTS(SELECT 1 FROM post_like WHERE post=post.id AND person=$3)" @@ -658,9 +658,10 @@ async fn route_unstable_communities_posts_list( author: author.as_ref(), created: &created.to_rfc3339(), community: &community, + replies_count_total: Some(row.get(12)), score: row.get(11), your_vote: if include_your_for.is_some() { - Some(if row.get(12) { + Some(if row.get(13) { Some(crate::Empty {}) } else { None diff --git a/src/routes/api/mod.rs b/src/routes/api/mod.rs index dbaff5f..f2c5199 100644 --- a/src/routes/api/mod.rs +++ b/src/routes/api/mod.rs @@ -111,6 +111,8 @@ struct RespPostListPost<'a> { author: Option<&'a RespMinimalAuthorInfo<'a>>, created: &'a str, community: &'a RespMinimalCommunityInfo<'a>, + #[serde(skip_serializing_if = "Option::is_none")] + replies_count_total: Option<i64>, score: i64, #[serde(skip_serializing_if = "Option::is_none")] your_vote: Option<Option<crate::Empty>>, @@ -156,6 +158,8 @@ enum RespThingInfo<'a> { title: &'a str, created: String, community: RespMinimalCommunityInfo<'a>, + replies_count_total: i64, + score: i64, }, #[serde(rename = "comment")] Comment { @@ -758,6 +762,18 @@ async fn route_unstable_misc_render_markdown( crate::json_response(&serde_json::json!({ "content_html": html })) } +fn common_posts_list_query(include_your_idx: Option<usize>) -> Cow<'static, str> { + const BASE: &str = "post.id, post.author, post.href, post.content_text, post.title, post.created, post.content_html, community.id, community.name, community.local, community.ap_id, person.username, person.local, person.ap_id, person.avatar, (SELECT COUNT(*) FROM post_like WHERE post_like.post = post.id), (SELECT COUNT(*) FROM reply WHERE reply.post = post.id)"; + match include_your_idx { + None => BASE.into(), + Some(idx) => format!( + "{}, EXISTS(SELECT 1 FROM post_like WHERE post=post.id AND person=${})", + BASE, idx + ) + .into(), + } +} + async fn handle_common_posts_list( stream: impl futures::stream::TryStream<Ok = tokio_postgres::Row, Error = tokio_postgres::Error> + Send, @@ -824,8 +840,9 @@ async fn handle_common_posts_list( created: &created.to_rfc3339(), community: &community, score: row.get(15), + replies_count_total: Some(row.get(16)), your_vote: if include_your { - Some(if row.get(16) { + Some(if row.get(17) { Some(crate::Empty {}) } else { None diff --git a/src/routes/api/posts.rs b/src/routes/api/posts.rs index 9108a0c..2bfa0e2 100644 --- a/src/routes/api/posts.rs +++ b/src/routes/api/posts.rs @@ -125,14 +125,17 @@ async fn route_unstable_posts_list( let mut values: Vec<&(dyn tokio_postgres::types::ToSql + Sync)> = vec![&limit]; - let sql: &str = &format!( - "SELECT post.id, post.author, post.href, post.content_text, post.title, post.created, post.content_html, community.id, community.name, community.local, community.ap_id, person.username, person.local, person.ap_id, person.avatar, (SELECT COUNT(*) FROM post_like WHERE post_like.post = post.id){} FROM community, post LEFT OUTER JOIN person ON (person.id = post.author) WHERE post.community = community.id AND deleted=FALSE ORDER BY hot_rank((SELECT COUNT(*) FROM post_like WHERE post = post.id AND person != post.author), post.created) DESC LIMIT $1", - if let Some(user) = &include_your_for { + let include_your_idx = match &include_your_for { + None => None, + Some(user) => { values.push(user); - ", EXISTS(SELECT 1 FROM post_like WHERE post=post.id AND person=$2)" - } else { - "" - }, + Some(values.len()) + } + }; + + let sql: &str = &format!( + "SELECT {} FROM community, post LEFT OUTER JOIN person ON (person.id = post.author) WHERE post.community = community.id AND deleted=FALSE ORDER BY hot_rank((SELECT COUNT(*) FROM post_like WHERE post = post.id AND person != post.author), post.created) DESC LIMIT $1", + super::common_posts_list_query(include_your_idx), ); let stream = crate::query_stream(&db, sql, &values).await?; @@ -380,6 +383,7 @@ async fn route_unstable_posts_get( author: author.as_ref(), created: &created.to_rfc3339(), community: &community, + replies_count_total: None, score: row.get(13), your_vote, }; diff --git a/src/routes/api/users.rs b/src/routes/api/users.rs index a0c8f21..ad1d77d 100644 --- a/src/routes/api/users.rs +++ b/src/routes/api/users.rs @@ -1,11 +1,11 @@ use super::{ - handle_common_posts_list, MaybeIncludeYour, RespAvatarInfo, RespLoginUserInfo, - RespMinimalAuthorInfo, RespMinimalCommentInfo, RespMinimalCommunityInfo, RespMinimalPostInfo, - RespThingInfo, + MaybeIncludeYour, RespAvatarInfo, RespLoginUserInfo, RespMinimalAuthorInfo, + RespMinimalCommentInfo, RespMinimalCommunityInfo, RespMinimalPostInfo, RespThingInfo, }; use crate::{CommentLocalID, CommunityLocalID, PostLocalID, UserLocalID}; use serde_derive::{Deserialize, Serialize}; use std::borrow::Cow; +use std::ops::Deref; use std::sync::Arc; struct MeOrLocalAndAdminResult { @@ -357,11 +357,11 @@ async fn route_unstable_users_following_posts_list( let values: &[&(dyn tokio_postgres::types::ToSql + Sync)] = &[&user, &limit]; let stream = db.query_raw( - "SELECT post.id, post.author, post.href, post.content_text, post.title, post.created, post.content_html, community.id, community.name, community.local, community.ap_id, person.username, person.local, person.ap_id, person.avatar, (SELECT COUNT(*) FROM post_like WHERE post_like.post = post.id), EXISTS(SELECT 1 FROM post_like WHERE post = post.id AND person = $1) FROM community, post LEFT OUTER JOIN person ON (person.id = post.author) WHERE post.community = community.id AND post.approved AND post.deleted=FALSE AND community.id IN (SELECT community FROM community_follow WHERE follower=$1 AND accepted) ORDER BY hot_rank((SELECT COUNT(*) FROM post_like WHERE post = post.id AND person != post.author), post.created) DESC LIMIT $2", + format!("SELECT {} FROM community, post LEFT OUTER JOIN person ON (person.id = post.author) WHERE post.community = community.id AND post.approved AND post.deleted=FALSE AND community.id IN (SELECT community FROM community_follow WHERE follower=$1 AND accepted) ORDER BY hot_rank((SELECT COUNT(*) FROM post_like WHERE post = post.id AND person != post.author), post.created) DESC LIMIT $2", super::common_posts_list_query(Some(1))).deref(), values.iter().map(|s| *s as _) ).await?; - let posts = handle_common_posts_list(stream, &ctx, true).await?; + let posts = super::handle_common_posts_list(stream, &ctx, true).await?; crate::json_response(&posts) } @@ -608,7 +608,7 @@ async fn route_unstable_users_things_list( let limit: i64 = 30; let rows = db.query( - "(SELECT TRUE, post.id, post.href, post.title, post.created, community.id, community.name, community.local, community.ap_id FROM post, community WHERE post.community = community.id AND post.author = $1 AND NOT post.deleted) UNION ALL (SELECT FALSE, reply.id, reply.content_text, reply.content_html, reply.created, post.id, post.title, NULL, NULL FROM reply, post WHERE post.id = reply.post AND reply.author = $1 AND NOT reply.deleted) ORDER BY created DESC LIMIT $2", + "(SELECT TRUE, post.id, post.href, post.title, post.created, community.id, community.name, community.local, community.ap_id, (SELECT COUNT(*) FROM post_like WHERE post_like.post = post.id), (SELECT COUNT(*) FROM reply WHERE reply.post = post.id) FROM post, community WHERE post.community = community.id AND post.author = $1 AND NOT post.deleted) UNION ALL (SELECT FALSE, reply.id, reply.content_text, reply.content_html, reply.created, post.id, post.title, NULL, NULL, NULL, NULL FROM reply, post WHERE post.id = reply.post AND reply.author = $1 AND NOT reply.deleted) ORDER BY created DESC LIMIT $2", &[&user_id, &limit], ) .await?; @@ -641,6 +641,8 @@ async fn route_unstable_users_things_list( ), remote_url: community_ap_id, }, + replies_count_total: row.get(10), + score: row.get(9), } } else { RespThingInfo::Comment { |