diff --git a/migrations/V0004__post__add_reply_count.sql b/migrations/V0004__post__add_reply_count.sql new file mode 100644 index 0000000..18d3696 --- /dev/null +++ b/migrations/V0004__post__add_reply_count.sql @@ -0,0 +1 @@ +ALTER TABLE post ADD COLUMN reply_count INTEGER NOT NULL CHECK (reply_count >= 0) DEFAULT 0; diff --git a/migrations/schema.sql b/migrations/schema.sql index dfffed1..961f324 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -34,6 +34,7 @@ CREATE TABLE post ( author_id UUID NOT NULL REFERENCES actor_profile (id) ON DELETE CASCADE, content TEXT NOT NULL, in_reply_to_id UUID REFERENCES post (id) ON DELETE CASCADE, + reply_count INTEGER NOT NULL CHECK (reply_count >= 0) DEFAULT 0, ipfs_cid VARCHAR(200), token_id INTEGER, token_tx_id VARCHAR(200), diff --git a/src/mastodon_api/statuses/types.rs b/src/mastodon_api/statuses/types.rs index ec730ef..7968f23 100644 --- a/src/mastodon_api/statuses/types.rs +++ b/src/mastodon_api/statuses/types.rs @@ -14,6 +14,7 @@ pub struct Status { pub account: Account, pub content: String, pub in_reply_to_id: Option, + pub replies_count: i32, pub media_attachments: Vec, // Extra fields @@ -34,6 +35,7 @@ impl Status { account: account, content: post.content, in_reply_to_id: post.in_reply_to_id, + replies_count: post.reply_count, media_attachments: attachments, ipfs_cid: post.ipfs_cid, token_id: post.token_id, diff --git a/src/models/posts/queries.rs b/src/models/posts/queries.rs index 3363d73..0dfb7c6 100644 --- a/src/models/posts/queries.rs +++ b/src/models/posts/queries.rs @@ -96,6 +96,8 @@ pub async fn create_post( &created_at, ], ).await?; + let db_post: DbPost = post_row.try_get("post")?; + // Create links to attachments let attachment_rows = transaction.query( " UPDATE media_attachment @@ -110,14 +112,19 @@ pub async fn create_post( row.try_get("media_attachment") }) .collect::>()?; - let db_post: DbPost = post_row.try_get("post")?; + // Update counters let author = update_post_count(&transaction, &db_post.author_id, 1).await?; + if let Some(in_reply_to_id) = &db_post.in_reply_to_id { + update_reply_count(&transaction, in_reply_to_id, 1).await?; + } + transaction.commit().await?; let post = Post { id: db_post.id, author: author, content: db_post.content, in_reply_to_id: db_post.in_reply_to_id, + reply_count: db_post.reply_count, attachments: db_attachments, ipfs_cid: db_post.ipfs_cid, token_id: db_post.token_id, @@ -247,6 +254,26 @@ pub async fn update_post( Ok(()) } +pub async fn update_reply_count( + db_client: &impl GenericClient, + post_id: &Uuid, + change: i32, +) -> Result<(), DatabaseError> { + let updated_count = db_client.execute( + " + UPDATE post + SET reply_count = reply_count + $1 + WHERE id = $2 + RETURNING post + ", + &[&change, &post_id], + ).await?; + if updated_count == 0 { + return Err(DatabaseError::NotFound("post")); + } + Ok(()) +} + pub async fn is_waiting_for_token( db_client: &impl GenericClient, ) -> Result { diff --git a/src/models/posts/types.rs b/src/models/posts/types.rs index 1adfa8b..a5e4230 100644 --- a/src/models/posts/types.rs +++ b/src/models/posts/types.rs @@ -17,6 +17,7 @@ pub struct DbPost { pub author_id: Uuid, pub content: String, pub in_reply_to_id: Option, + pub reply_count: i32, pub ipfs_cid: Option, pub token_id: Option, pub token_tx_id: Option, @@ -29,6 +30,7 @@ pub struct Post { pub author: DbActorProfile, pub content: String, pub in_reply_to_id: Option, + pub reply_count: i32, pub attachments: Vec, pub ipfs_cid: Option, pub token_id: Option, @@ -49,6 +51,7 @@ impl TryFrom<&Row> for Post { author: db_profile, content: db_post.content, in_reply_to_id: db_post.in_reply_to_id, + reply_count: db_post.reply_count, attachments: db_attachments, ipfs_cid: db_post.ipfs_cid, token_id: db_post.token_id,