Add in_reply_to field to Post struct

create_note refactored to accept Post without additional in_reply_to argument.
This commit is contained in:
silverpill 2021-12-31 17:15:00 +00:00
parent a9a99d7172
commit 94aad001f8
4 changed files with 32 additions and 22 deletions

View file

@ -157,7 +157,6 @@ pub fn create_note(
instance_host: &str, instance_host: &str,
instance_url: &str, instance_url: &str,
post: &Post, post: &Post,
in_reply_to: Option<&Post>,
) -> Note { ) -> Note {
let object_id = get_object_url( let object_id = get_object_url(
instance_url, instance_url,
@ -203,7 +202,7 @@ pub fn create_note(
}; };
let in_reply_to_object_id = match post.in_reply_to_id { let in_reply_to_object_id = match post.in_reply_to_id {
Some(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); assert_eq!(post.id, in_reply_to_id);
if post.author.is_local() { if post.author.is_local() {
Some(get_object_url(instance_url, &post.id)) Some(get_object_url(instance_url, &post.id))
@ -236,9 +235,8 @@ pub fn create_activity_note(
instance_host: &str, instance_host: &str,
instance_url: &str, instance_url: &str,
post: &Post, post: &Post,
in_reply_to: Option<&Post>,
) -> Activity { ) -> 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 recipients = object.to.clone();
let activity = create_activity( let activity = create_activity(
instance_url, instance_url,
@ -474,7 +472,7 @@ mod tests {
..Default::default() ..Default::default()
}; };
let post = Post { author, ..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!( assert_eq!(
note.id, note.id,
@ -494,9 +492,10 @@ mod tests {
let parent = Post::default(); let parent = Post::default();
let post = Post { let post = Post {
in_reply_to_id: Some(parent.id), in_reply_to_id: Some(parent.id),
in_reply_to: Some(Box::new(parent.clone())),
..Default::default() ..Default::default()
}; };
let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post, Some(&parent)); let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post);
assert_eq!( assert_eq!(
note.in_reply_to.unwrap(), note.in_reply_to.unwrap(),
@ -525,10 +524,11 @@ mod tests {
}; };
let post = Post { let post = Post {
in_reply_to_id: Some(parent.id), in_reply_to_id: Some(parent.id),
in_reply_to: Some(Box::new(parent.clone())),
mentions: vec![parent_author], mentions: vec![parent_author],
..Default::default() ..Default::default()
}; };
let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post, Some(&parent)); let note = create_note(INSTANCE_HOST, INSTANCE_URL, &post);
assert_eq!( assert_eq!(
note.in_reply_to.unwrap(), note.in_reply_to.unwrap(),

View file

@ -62,7 +62,7 @@ fn is_activitypub_request(headers: &HeaderMap) -> bool {
if let Some(content_type) = headers.get("Accept") { if let Some(content_type) = headers.get("Accept") {
let content_type_str = content_type.to_str().ok() let content_type_str = content_type.to_str().ok()
// Take first content type if there are many // Take first content type if there are many
.and_then(|value| value.split(",").next()) .and_then(|value| value.split(',').next())
.unwrap_or(""); .unwrap_or("");
return CONTENT_TYPES.contains(&content_type_str); return CONTENT_TYPES.contains(&content_type_str);
}; };
@ -78,7 +78,7 @@ async fn actor_view(
) -> Result<HttpResponse, HttpError> { ) -> Result<HttpResponse, HttpError> {
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?;
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 page_url = get_profile_page_url(&config.instance_url(), &user.id);
let response = HttpResponse::Found() let response = HttpResponse::Found()
.header("Location", page_url) .header("Location", page_url)
@ -166,11 +166,12 @@ async fn outbox(
match post.repost_of_id { match post.repost_of_id {
Some(_) => None, Some(_) => None,
None => { None => {
// Replies are not included so post.in_reply_to
// does not need to be populated
let activity = create_activity_note( let activity = create_activity_note(
&instance.host(), &instance.host(),
&instance.url(), &instance.url(),
post, post,
None,
); );
Some(activity) Some(activity)
}, },
@ -270,27 +271,32 @@ pub async fn object_view(
let db_client = &**get_database_client(&db_pool).await?; let db_client = &**get_database_client(&db_pool).await?;
// Try to find local post by ID, return 404 if not found // Try to find local post by ID, return 404 if not found
let thread = get_thread(db_client, &internal_object_id, None).await?; 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()) .find(|post| post.id == internal_object_id && post.author.is_local())
.ok_or(HttpError::NotFoundError("post"))?; .ok_or(HttpError::NotFoundError("post"))?
if !is_activitypub_request(&request.headers()) { .clone();
if !is_activitypub_request(request.headers()) {
let page_url = get_post_page_url(&config.instance_url(), &post.id); let page_url = get_post_page_url(&config.instance_url(), &post.id);
let response = HttpResponse::Found() let response = HttpResponse::Found()
.header("Location", page_url) .header("Location", page_url)
.finish(); .finish();
return Ok(response); 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) => { 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, None => None,
}; };
let object = create_note( let object = create_note(
&config.instance().host(), &config.instance().host(),
&config.instance().url(), &config.instance().url(),
post, &post,
in_reply_to,
); );
let response = HttpResponse::Ok() let response = HttpResponse::Ok()
.content_type(ACTIVITY_CONTENT_TYPE) .content_type(ACTIVITY_CONTENT_TYPE)

View file

@ -79,12 +79,12 @@ async fn create_status(
&post_data.content, &post_data.content,
&post_data.tags, &post_data.tags,
); );
let post = create_post(db_client, &current_user.id, post_data).await?; let mut post = create_post(db_client, &current_user.id, post_data).await?;
// Federate // 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) => { Some(in_reply_to_id) => {
let in_reply_to = get_post_by_id(db_client, &in_reply_to_id).await?; 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, None => None,
}; };
@ -92,7 +92,6 @@ async fn create_status(
&instance.host(), &instance.host(),
&instance.url(), &instance.url(),
&post, &post,
maybe_in_reply_to.as_ref(),
); );
let followers = get_followers(db_client, &current_user.id).await?; let followers = get_followers(db_client, &current_user.id).await?;
let mut recipients: Vec<Actor> = Vec::new(); let mut recipients: Vec<Actor> = Vec::new();
@ -103,7 +102,7 @@ async fn create_status(
recipients.push(remote_actor); 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() let maybe_remote_actor = in_reply_to.author.remote_actor()
.map_err(|_| HttpError::InternalError)?; .map_err(|_| HttpError::InternalError)?;
if let Some(remote_actor) = maybe_remote_actor { if let Some(remote_actor) = maybe_remote_actor {

View file

@ -93,7 +93,10 @@ pub struct Post {
pub token_tx_id: Option<String>, pub token_tx_id: Option<String>,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
// These fields are not populated automatically
// by functions in posts::queries module
pub actions: Option<PostActions>, pub actions: Option<PostActions>,
pub in_reply_to: Option<Box<Post>>,
pub repost_of: Option<Box<Post>>, pub repost_of: Option<Box<Post>>,
} }
@ -131,6 +134,7 @@ impl Post {
token_tx_id: db_post.token_tx_id, token_tx_id: db_post.token_tx_id,
created_at: db_post.created_at, created_at: db_post.created_at,
actions: None, actions: None,
in_reply_to: None,
repost_of: None, repost_of: None,
}; };
Ok(post) Ok(post)
@ -170,6 +174,7 @@ impl Default for Post {
token_tx_id: None, token_tx_id: None,
created_at: Utc::now(), created_at: Utc::now(),
actions: None, actions: None,
in_reply_to: None,
repost_of: None, repost_of: None,
} }
} }