diff --git a/src/activitypub/activity.rs b/src/activitypub/activity.rs index d7311c7..ab3ff28 100644 --- a/src/activitypub/activity.rs +++ b/src/activitypub/activity.rs @@ -157,7 +157,6 @@ pub fn create_note( instance_host: &str, instance_url: &str, post: &Post, - in_reply_to: Option<&Post>, ) -> Note { let object_id = get_object_url( instance_url, @@ -203,7 +202,7 @@ pub fn create_note( }; let in_reply_to_object_id = match post.in_reply_to_id { Some(in_reply_to_id) => { - let post = in_reply_to.unwrap(); + let post = post.in_reply_to.as_ref().unwrap(); assert_eq!(post.id, in_reply_to_id); if post.author.is_local() { Some(get_object_url(instance_url, &post.id)) @@ -236,9 +235,8 @@ pub fn create_activity_note( instance_host: &str, instance_url: &str, post: &Post, - in_reply_to: Option<&Post>, ) -> Activity { - let object = create_note(instance_host, instance_url, post, in_reply_to); + let object = create_note(instance_host, instance_url, post); let recipients = object.to.clone(); let activity = create_activity( instance_url, @@ -474,7 +472,7 @@ mod tests { ..Default::default() }; let post = Post { author, ..Default::default() }; - let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post, None); + let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post); assert_eq!( note.id, @@ -494,9 +492,10 @@ mod tests { let parent = Post::default(); let post = Post { in_reply_to_id: Some(parent.id), + in_reply_to: Some(Box::new(parent.clone())), ..Default::default() }; - let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post, Some(&parent)); + let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post); assert_eq!( note.in_reply_to.unwrap(), @@ -525,10 +524,11 @@ mod tests { }; let post = Post { in_reply_to_id: Some(parent.id), + in_reply_to: Some(Box::new(parent.clone())), mentions: vec![parent_author], ..Default::default() }; - let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post, Some(&parent)); + let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post); assert_eq!( note.in_reply_to.unwrap(), diff --git a/src/activitypub/views.rs b/src/activitypub/views.rs index 9bee2dc..f399aa6 100644 --- a/src/activitypub/views.rs +++ b/src/activitypub/views.rs @@ -62,7 +62,7 @@ fn is_activitypub_request(headers: &HeaderMap) -> bool { if let Some(content_type) = headers.get("Accept") { let content_type_str = content_type.to_str().ok() // Take first content type if there are many - .and_then(|value| value.split(",").next()) + .and_then(|value| value.split(',').next()) .unwrap_or(""); return CONTENT_TYPES.contains(&content_type_str); }; @@ -78,7 +78,7 @@ async fn actor_view( ) -> Result { let db_client = &**get_database_client(&db_pool).await?; let user = get_user_by_name(db_client, &username).await?; - if !is_activitypub_request(&request.headers()) { + if !is_activitypub_request(request.headers()) { let page_url = get_profile_page_url(&config.instance_url(), &user.id); let response = HttpResponse::Found() .header("Location", page_url) @@ -166,11 +166,12 @@ async fn outbox( match post.repost_of_id { Some(_) => None, None => { + // Replies are not included so post.in_reply_to + // does not need to be populated let activity = create_activity_note( &instance.host(), &instance.url(), post, - None, ); Some(activity) }, @@ -270,27 +271,32 @@ pub async fn object_view( let db_client = &**get_database_client(&db_pool).await?; // Try to find local post by ID, return 404 if not found let thread = get_thread(db_client, &internal_object_id, None).await?; - let post = thread.iter() + let mut post = thread.iter() .find(|post| post.id == internal_object_id && post.author.is_local()) - .ok_or(HttpError::NotFoundError("post"))?; - if !is_activitypub_request(&request.headers()) { + .ok_or(HttpError::NotFoundError("post"))? + .clone(); + if !is_activitypub_request(request.headers()) { let page_url = get_post_page_url(&config.instance_url(), &post.id); let response = HttpResponse::Found() .header("Location", page_url) .finish(); return Ok(response); }; - let in_reply_to = match post.in_reply_to_id { + post.in_reply_to = match post.in_reply_to_id { Some(in_reply_to_id) => { - thread.iter().find(|post| post.id == in_reply_to_id) + let in_reply_to = thread.iter() + .find(|post| post.id == in_reply_to_id) + // Parent post must be present in thread + .ok_or(HttpError::InternalError)? + .clone(); + Some(Box::new(in_reply_to)) }, None => None, }; let object = create_note( &config.instance().host(), &config.instance().url(), - post, - in_reply_to, + &post, ); let response = HttpResponse::Ok() .content_type(ACTIVITY_CONTENT_TYPE) diff --git a/src/mastodon_api/statuses/views.rs b/src/mastodon_api/statuses/views.rs index df03fe7..56c8a83 100644 --- a/src/mastodon_api/statuses/views.rs +++ b/src/mastodon_api/statuses/views.rs @@ -79,12 +79,12 @@ async fn create_status( &post_data.content, &post_data.tags, ); - let post = create_post(db_client, ¤t_user.id, post_data).await?; + let mut post = create_post(db_client, ¤t_user.id, post_data).await?; // Federate - let maybe_in_reply_to = match post.in_reply_to_id { + post.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) + Some(Box::new(in_reply_to)) }, None => None, }; @@ -92,7 +92,6 @@ async fn create_status( &instance.host(), &instance.url(), &post, - maybe_in_reply_to.as_ref(), ); let followers = get_followers(db_client, ¤t_user.id).await?; let mut recipients: Vec = Vec::new(); @@ -103,7 +102,7 @@ async fn create_status( recipients.push(remote_actor); }; }; - if let Some(in_reply_to) = maybe_in_reply_to { + if let Some(ref in_reply_to) = post.in_reply_to { let maybe_remote_actor = in_reply_to.author.remote_actor() .map_err(|_| HttpError::InternalError)?; if let Some(remote_actor) = maybe_remote_actor { diff --git a/src/models/posts/types.rs b/src/models/posts/types.rs index 436e17c..9700fcf 100644 --- a/src/models/posts/types.rs +++ b/src/models/posts/types.rs @@ -93,7 +93,10 @@ pub struct Post { pub token_tx_id: Option, pub created_at: DateTime, + // These fields are not populated automatically + // by functions in posts::queries module pub actions: Option, + pub in_reply_to: Option>, pub repost_of: Option>, } @@ -131,6 +134,7 @@ impl Post { token_tx_id: db_post.token_tx_id, created_at: db_post.created_at, actions: None, + in_reply_to: None, repost_of: None, }; Ok(post) @@ -170,6 +174,7 @@ impl Default for Post { token_tx_id: None, created_at: Utc::now(), actions: None, + in_reply_to: None, repost_of: None, } }