diff --git a/src/activitypub/activity.rs b/src/activitypub/activity.rs index 7593a31..cb0f81e 100644 --- a/src/activitypub/activity.rs +++ b/src/activitypub/activity.rs @@ -121,13 +121,19 @@ pub fn create_note( url, } }).collect(); + let mut recipients = vec![AP_PUBLIC.to_string()]; let in_reply_to_object_id = match post.in_reply_to_id { Some(in_reply_to_id) => { let post = in_reply_to.unwrap(); assert_eq!(post.id, in_reply_to_id); - match post.author.is_local() { - false => post.object_id.clone(), - true => Some(get_object_url(instance_url, &post.id)), + match post.author.actor_json { + Some(ref actor_value) => { + // Replying to remote post + let remote_actor_id = actor_value["id"].as_str().unwrap(); + recipients.push(remote_actor_id.to_string()); + post.object_id.clone() + }, + None => Some(get_object_url(instance_url, &post.id)), } }, None => None, @@ -143,7 +149,7 @@ pub fn create_note( attributed_to: Some(actor_id), in_reply_to: in_reply_to_object_id, content: Some(post.content.clone()), - to: Some(json!(AP_PUBLIC)), + to: Some(json!(recipients)), } } @@ -324,12 +330,16 @@ mod tests { note.in_reply_to.unwrap(), format!("{}/objects/{}", INSTANCE_URL, parent.id), ); + assert_eq!(note.to.unwrap(), json!([AP_PUBLIC])); } #[test] fn test_create_note_with_remote_parent() { + let parent_author_actor_id = "https://test.net/user/test"; let parent_author = DbActorProfile { - actor_json: Some(json!("test")), + actor_json: Some(json!({ + "id": parent_author_actor_id, + })), ..Default::default() }; let parent = Post { @@ -347,6 +357,10 @@ mod tests { note.in_reply_to.unwrap(), parent.object_id.unwrap(), ); + assert_eq!( + note.to.unwrap(), + json!([AP_PUBLIC, parent_author_actor_id]), + ); } #[test] diff --git a/src/activitypub/deliverer.rs b/src/activitypub/deliverer.rs index b7c5a0e..3433beb 100644 --- a/src/activitypub/deliverer.rs +++ b/src/activitypub/deliverer.rs @@ -90,14 +90,19 @@ async fn deliver_activity_worker( ), ); let activity_json = serde_json::to_string(&activity)?; - for recipient in recipients { + let mut inboxes: Vec = recipients.into_iter() + .map(|actor| actor.inbox) + .collect(); + inboxes.sort(); + inboxes.dedup(); + for inbox_url in inboxes { // TODO: retry on error if let Err(err) = send_activity( &config, &actor_key, &actor_key_id, &activity_json, - &recipient.inbox, + &inbox_url, ).await { log::error!("{}", err); } diff --git a/src/mastodon_api/statuses/views.rs b/src/mastodon_api/statuses/views.rs index dfb984a..7f3865d 100644 --- a/src/mastodon_api/statuses/views.rs +++ b/src/mastodon_api/statuses/views.rs @@ -49,7 +49,7 @@ async fn create_status( post_data.validate()?; let post = create_post(db_client, ¤t_user.id, post_data).await?; // Federate - let in_reply_to = match post.in_reply_to_id { + let maybe_in_reply_to = match post.in_reply_to_id { Some(in_reply_to_id) => { let in_reply_to = get_post_by_id(db_client, &in_reply_to_id).await?; Some(in_reply_to) @@ -59,7 +59,7 @@ async fn create_status( let activity = create_activity_note( &config.instance_url(), &post, - in_reply_to.as_ref(), + maybe_in_reply_to.as_ref(), ); let followers = get_followers(db_client, ¤t_user.id).await?; let mut recipients: Vec = Vec::new(); @@ -70,6 +70,13 @@ async fn create_status( recipients.push(remote_actor); }; }; + if let Some(in_reply_to) = maybe_in_reply_to { + let maybe_remote_actor = in_reply_to.author.actor() + .map_err(|_| HttpError::InternalError)?; + if let Some(remote_actor) = maybe_remote_actor { + recipients.push(remote_actor); + } + } deliver_activity(&config, ¤t_user, activity, recipients); let status = Status::from_post(post, &config.instance_url()); Ok(HttpResponse::Created().json(status))