summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Reeder <colin@vpzom.click>2020-11-11 22:47:11 -0700
committerColin Reeder <colin@vpzom.click>2020-11-11 22:47:11 -0700
commit9bb065b5da31d4b1b5d212a1ca7941717f17ace5 (patch)
treeccde0bf669cd71865c48638c3d1fe76ce59a57d0
parent0acc624f44acc4d645d25820a29da268115fd2c4 (diff)
Include replies_count_total in post lists (#123)
-rw-r--r--openapi/openapi.json16
-rw-r--r--src/routes/api/communities.rs5
-rw-r--r--src/routes/api/mod.rs19
-rw-r--r--src/routes/api/posts.rs18
-rw-r--r--src/routes/api/users.rs14
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 {