Add replies and reposts to outbox collection
This commit is contained in:
parent
b6e7fa5d13
commit
b77d4a9bdf
4 changed files with 37 additions and 34 deletions
|
@ -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.
|
- Ignore errors when importing activities from outbox.
|
||||||
- Make activity limit in outbox fetcher adjustable.
|
- Make activity limit in outbox fetcher adjustable.
|
||||||
- Updated actix to latest version. MSRV changed to 1.57.
|
- Updated actix to latest version. MSRV changed to 1.57.
|
||||||
|
- Add replies and reposts to outbox collection.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ use crate::activitypub::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Announce {
|
pub struct Announce {
|
||||||
#[serde(rename = "@context")]
|
#[serde(rename = "@context")]
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|
||||||
|
@ -41,18 +41,17 @@ struct Announce {
|
||||||
cc: Vec<String>,
|
cc: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_announce(
|
pub fn build_announce(
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
sender_username: &str,
|
|
||||||
repost: &Post,
|
repost: &Post,
|
||||||
) -> Announce {
|
) -> 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()
|
let post = repost.repost_of.as_ref()
|
||||||
.expect("repost_of field should be populated");
|
.expect("repost_of field should be populated");
|
||||||
let object_id = post_object_id(instance_url, post);
|
let object_id = post_object_id(instance_url, post);
|
||||||
let activity_id = local_object_id(instance_url, &repost.id);
|
let activity_id = local_object_id(instance_url, &repost.id);
|
||||||
let recipient_id = profile_actor_id(instance_url, &post.author);
|
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 {
|
Announce {
|
||||||
context: build_default_context(),
|
context: build_default_context(),
|
||||||
activity_type: ANNOUNCE.to_string(),
|
activity_type: ANNOUNCE.to_string(),
|
||||||
|
@ -91,7 +90,9 @@ pub async fn prepare_announce(
|
||||||
sender: &User,
|
sender: &User,
|
||||||
repost: &Post,
|
repost: &Post,
|
||||||
) -> Result<OutgoingActivity, DatabaseError> {
|
) -> 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(
|
let (recipients, _) = get_announce_recipients(
|
||||||
db_client,
|
db_client,
|
||||||
&instance.url(),
|
&instance.url(),
|
||||||
|
@ -100,7 +101,6 @@ pub async fn prepare_announce(
|
||||||
).await?;
|
).await?;
|
||||||
let activity = build_announce(
|
let activity = build_announce(
|
||||||
&instance.url(),
|
&instance.url(),
|
||||||
&sender.profile.username,
|
|
||||||
repost,
|
repost,
|
||||||
);
|
);
|
||||||
Ok(OutgoingActivity::new(
|
Ok(OutgoingActivity::new(
|
||||||
|
@ -140,14 +140,13 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let repost = Post {
|
let repost = Post {
|
||||||
author: repost_author.clone(),
|
author: repost_author,
|
||||||
repost_of_id: Some(post.id),
|
repost_of_id: Some(post.id),
|
||||||
repost_of: Some(Box::new(post)),
|
repost_of: Some(Box::new(post)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let activity = build_announce(
|
let activity = build_announce(
|
||||||
INSTANCE_URL,
|
INSTANCE_URL,
|
||||||
&repost_author.username,
|
|
||||||
&repost,
|
&repost,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{Value as JsonValue};
|
||||||
|
|
||||||
use super::types::{build_default_context, Context};
|
use super::types::{build_default_context, Context};
|
||||||
use super::vocabulary::{ORDERED_COLLECTION, ORDERED_COLLECTION_PAGE};
|
use super::vocabulary::{ORDERED_COLLECTION, ORDERED_COLLECTION_PAGE};
|
||||||
|
@ -38,8 +38,6 @@ impl OrderedCollection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const COLLECTION_PAGE_SIZE: u16 = 10;
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct OrderedCollectionPage {
|
pub struct OrderedCollectionPage {
|
||||||
|
@ -51,21 +49,19 @@ pub struct OrderedCollectionPage {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub object_type: String,
|
pub object_type: String,
|
||||||
|
|
||||||
ordered_items: Vec<Value>,
|
ordered_items: Vec<JsonValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OrderedCollectionPage {
|
impl OrderedCollectionPage {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
collection_page_id: String,
|
collection_page_id: String,
|
||||||
items: Vec<impl Serialize>,
|
items: Vec<JsonValue>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let ordered_items = items.into_iter()
|
|
||||||
.map(|item| json!(item)).collect();
|
|
||||||
Self {
|
Self {
|
||||||
context: build_default_context(),
|
context: build_default_context(),
|
||||||
id: collection_page_id,
|
id: collection_page_id,
|
||||||
object_type: ORDERED_COLLECTION_PAGE.to_string(),
|
object_type: ORDERED_COLLECTION_PAGE.to_string(),
|
||||||
ordered_items,
|
ordered_items: items,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,13 +30,15 @@ use crate::web_client::urls::{
|
||||||
get_tag_page_url,
|
get_tag_page_url,
|
||||||
};
|
};
|
||||||
use super::actors::types::{get_local_actor, get_instance_actor};
|
use super::actors::types::{get_local_actor, get_instance_actor};
|
||||||
use super::builders::create_note::{
|
use super::builders::{
|
||||||
build_emoji_tag,
|
announce::build_announce,
|
||||||
build_note,
|
create_note::{
|
||||||
build_create_note,
|
build_emoji_tag,
|
||||||
|
build_note,
|
||||||
|
build_create_note,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use super::collections::{
|
use super::collections::{
|
||||||
COLLECTION_PAGE_SIZE,
|
|
||||||
OrderedCollection,
|
OrderedCollection,
|
||||||
OrderedCollectionPage,
|
OrderedCollectionPage,
|
||||||
};
|
};
|
||||||
|
@ -171,26 +173,31 @@ async fn outbox(
|
||||||
let db_client = &**get_database_client(&db_pool).await?;
|
let db_client = &**get_database_client(&db_pool).await?;
|
||||||
let user = get_user_by_name(db_client, &username).await?;
|
let user = get_user_by_name(db_client, &username).await?;
|
||||||
// Posts are ordered by creation date
|
// Posts are ordered by creation date
|
||||||
|
const COLLECTION_PAGE_SIZE: u16 = 20;
|
||||||
let mut posts = get_posts_by_author(
|
let mut posts = get_posts_by_author(
|
||||||
db_client,
|
db_client,
|
||||||
&user.id,
|
&user.id,
|
||||||
None, // include only public posts
|
None, // include only public posts
|
||||||
false, // exclude replies
|
true, // include replies
|
||||||
false, // exclude reposts
|
true, // include reposts
|
||||||
None,
|
None,
|
||||||
COLLECTION_PAGE_SIZE,
|
COLLECTION_PAGE_SIZE,
|
||||||
).await?;
|
).await?;
|
||||||
add_related_posts(db_client, posts.iter_mut().collect()).await?;
|
add_related_posts(db_client, posts.iter_mut().collect()).await?;
|
||||||
let activities: Vec<_> = posts.iter().filter_map(|post| {
|
let activities = posts.iter().map(|post| {
|
||||||
if post.in_reply_to_id.is_some() || post.repost_of_id.is_some() {
|
if post.repost_of_id.is_some() {
|
||||||
return None;
|
let activity = build_announce(&instance.url(), post);
|
||||||
};
|
serde_json::to_value(activity)
|
||||||
let activity = build_create_note(
|
.expect("activity should be serializable")
|
||||||
&instance.hostname(),
|
} else {
|
||||||
&instance.url(),
|
let activity = build_create_note(
|
||||||
post,
|
&instance.hostname(),
|
||||||
);
|
&instance.url(),
|
||||||
Some(activity)
|
post,
|
||||||
|
);
|
||||||
|
serde_json::to_value(activity)
|
||||||
|
.expect("activity should be serializable")
|
||||||
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
let collection_page = OrderedCollectionPage::new(
|
let collection_page = OrderedCollectionPage::new(
|
||||||
first_page_id,
|
first_page_id,
|
||||||
|
|
Loading…
Reference in a new issue