Add replies and reposts to outbox collection

This commit is contained in:
silverpill 2023-04-22 01:01:52 +00:00
parent a63d528302
commit fc1be9d651
4 changed files with 37 additions and 34 deletions

View file

@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Updated actix to latest version. MSRV changed to 1.57.
- Make `/api/v1/accounts` endpoint accept optional `authentication_method` parameter.
- Make attached subscription links compatible with FEP-0ea0.
- Add replies and reposts to outbox collection.
### Deprecated

View file

@ -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<String>,
}
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<OutgoingActivity, DatabaseError> {
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!(

View file

@ -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<Value>,
ordered_items: Vec<JsonValue>,
}
impl OrderedCollectionPage {
pub fn new(
collection_page_id: String,
items: Vec<impl Serialize>,
items: Vec<JsonValue>,
) -> 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,
}
}
}

View file

@ -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::{
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 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,
);
Some(activity)
serde_json::to_value(activity)
.expect("activity should be serializable")
}
}).collect();
let collection_page = OrderedCollectionPage::new(
first_page_id,