From b77d4a9bdfd45bca151bdada29cda8196a61b9b3 Mon Sep 17 00:00:00 2001 From: silverpill Date: Sat, 22 Apr 2023 01:01:52 +0000 Subject: [PATCH] Add replies and reposts to outbox collection --- CHANGELOG.md | 1 + src/activitypub/builders/announce.rs | 17 ++++++------ src/activitypub/collections.rs | 12 +++----- src/activitypub/views.rs | 41 ++++++++++++++++------------ 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 317bb1d..34d1a4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Ignore errors when importing activities from outbox. - Make activity limit in outbox fetcher adjustable. - Updated actix to latest version. MSRV changed to 1.57. +- Add replies and reposts to outbox collection. ### Fixed diff --git a/src/activitypub/builders/announce.rs b/src/activitypub/builders/announce.rs index 4ffed60..3603905 100644 --- a/src/activitypub/builders/announce.rs +++ b/src/activitypub/builders/announce.rs @@ -25,7 +25,7 @@ use crate::activitypub::{ }; #[derive(Serialize)] -struct Announce { +pub struct Announce { #[serde(rename = "@context")] context: Context, @@ -41,18 +41,17 @@ struct Announce { cc: Vec, } -fn build_announce( +pub fn build_announce( instance_url: &str, - sender_username: &str, repost: &Post, ) -> Announce { - let actor_id = local_actor_id(instance_url, sender_username); + let actor_id = local_actor_id(instance_url, &repost.author.username); let post = repost.repost_of.as_ref() .expect("repost_of field should be populated"); let object_id = post_object_id(instance_url, post); let activity_id = local_object_id(instance_url, &repost.id); let recipient_id = profile_actor_id(instance_url, &post.author); - let followers = local_actor_followers(instance_url, sender_username); + let followers = local_actor_followers(instance_url, &repost.author.username); Announce { context: build_default_context(), activity_type: ANNOUNCE.to_string(), @@ -91,7 +90,9 @@ pub async fn prepare_announce( sender: &User, repost: &Post, ) -> Result { - let post = repost.repost_of.as_ref().unwrap(); + assert_eq!(sender.id, repost.author.id); + let post = repost.repost_of.as_ref() + .expect("repost_of field should be populated"); let (recipients, _) = get_announce_recipients( db_client, &instance.url(), @@ -100,7 +101,6 @@ pub async fn prepare_announce( ).await?; let activity = build_announce( &instance.url(), - &sender.profile.username, repost, ); Ok(OutgoingActivity::new( @@ -140,14 +140,13 @@ mod tests { ..Default::default() }; let repost = Post { - author: repost_author.clone(), + author: repost_author, repost_of_id: Some(post.id), repost_of: Some(Box::new(post)), ..Default::default() }; let activity = build_announce( INSTANCE_URL, - &repost_author.username, &repost, ); assert_eq!( diff --git a/src/activitypub/collections.rs b/src/activitypub/collections.rs index e3cc02a..eeb3918 100644 --- a/src/activitypub/collections.rs +++ b/src/activitypub/collections.rs @@ -1,5 +1,5 @@ use serde::Serialize; -use serde_json::{json, Value}; +use serde_json::{Value as JsonValue}; use super::types::{build_default_context, Context}; use super::vocabulary::{ORDERED_COLLECTION, ORDERED_COLLECTION_PAGE}; @@ -38,8 +38,6 @@ impl OrderedCollection { } } -pub const COLLECTION_PAGE_SIZE: u16 = 10; - #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct OrderedCollectionPage { @@ -51,21 +49,19 @@ pub struct OrderedCollectionPage { #[serde(rename = "type")] pub object_type: String, - ordered_items: Vec, + ordered_items: Vec, } impl OrderedCollectionPage { pub fn new( collection_page_id: String, - items: Vec, + items: Vec, ) -> Self { - let ordered_items = items.into_iter() - .map(|item| json!(item)).collect(); Self { context: build_default_context(), id: collection_page_id, object_type: ORDERED_COLLECTION_PAGE.to_string(), - ordered_items, + ordered_items: items, } } } diff --git a/src/activitypub/views.rs b/src/activitypub/views.rs index 0d4e7df..bd882f6 100644 --- a/src/activitypub/views.rs +++ b/src/activitypub/views.rs @@ -30,13 +30,15 @@ use crate::web_client::urls::{ get_tag_page_url, }; use super::actors::types::{get_local_actor, get_instance_actor}; -use super::builders::create_note::{ - build_emoji_tag, - build_note, - build_create_note, +use super::builders::{ + announce::build_announce, + create_note::{ + build_emoji_tag, + build_note, + build_create_note, + }, }; use super::collections::{ - COLLECTION_PAGE_SIZE, OrderedCollection, OrderedCollectionPage, }; @@ -171,26 +173,31 @@ async fn outbox( let db_client = &**get_database_client(&db_pool).await?; let user = get_user_by_name(db_client, &username).await?; // Posts are ordered by creation date + const COLLECTION_PAGE_SIZE: u16 = 20; let mut posts = get_posts_by_author( db_client, &user.id, None, // include only public posts - false, // exclude replies - false, // exclude reposts + true, // include replies + true, // include reposts None, COLLECTION_PAGE_SIZE, ).await?; add_related_posts(db_client, posts.iter_mut().collect()).await?; - let activities: Vec<_> = posts.iter().filter_map(|post| { - if post.in_reply_to_id.is_some() || post.repost_of_id.is_some() { - return None; - }; - let activity = build_create_note( - &instance.hostname(), - &instance.url(), - post, - ); - Some(activity) + let activities = posts.iter().map(|post| { + if post.repost_of_id.is_some() { + let activity = build_announce(&instance.url(), post); + serde_json::to_value(activity) + .expect("activity should be serializable") + } else { + let activity = build_create_note( + &instance.hostname(), + &instance.url(), + post, + ); + serde_json::to_value(activity) + .expect("activity should be serializable") + } }).collect(); let collection_page = OrderedCollectionPage::new( first_page_id,