From f4d1e756d4cd88abca027023ece6803d6453c310 Mon Sep 17 00:00:00 2001 From: silverpill Date: Sun, 21 Aug 2022 22:51:40 +0000 Subject: [PATCH] Fetch object referenced by quoteUrl property and create a link between posts --- src/activitypub/activity.rs | 3 ++ src/activitypub/fetcher/helpers.rs | 19 +++++++-- src/activitypub/handlers/create_note.rs | 57 ++++++++++++++++++------- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/activitypub/activity.rs b/src/activitypub/activity.rs index 0f4e039..e7fa99e 100644 --- a/src/activitypub/activity.rs +++ b/src/activitypub/activity.rs @@ -78,6 +78,9 @@ pub struct Object { #[serde(skip_serializing_if = "Option::is_none")] pub content: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub quote_url: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub tag: Option>, diff --git a/src/activitypub/fetcher/helpers.rs b/src/activitypub/fetcher/helpers.rs index 8a9955e..2f678ac 100644 --- a/src/activitypub/fetcher/helpers.rs +++ b/src/activitypub/fetcher/helpers.rs @@ -205,6 +205,7 @@ pub async fn import_post( // Fetch ancestors by going through inReplyTo references // TODO: fetch replies too #[allow(clippy::while_let_loop)] + #[allow(clippy::manual_map)] loop { let object_id = match maybe_object_id_to_fetch { Some(object_id) => { @@ -212,7 +213,7 @@ pub async fn import_post( // Object is a local post assert!(objects.len() > 0); break; - } + }; match get_post_by_object_id(db_client, &object_id).await { Ok(post) => { // Object already fetched @@ -252,11 +253,21 @@ pub async fn import_post( // Don't re-fetch object on the next iteration maybe_object = Some(object); } else { - maybe_object_id_to_fetch = object.in_reply_to.clone(); + maybe_object_id_to_fetch = if let Some(ref object_id) = object.in_reply_to { + // Fetch parent object on next iteration + Some(object_id.to_owned()) + } else if let Some(ref object_id) = object.quote_url { + // Fetch quoted object on next iteration + // (only if object doesn't have a parent). + Some(object_id.to_owned()) + } else { + // Stop + None + }; maybe_object = None; objects.push(object); }; - } + }; let initial_object_id = objects[0].id.clone(); // Objects are ordered according to their place in reply tree, @@ -271,7 +282,7 @@ pub async fn import_post( &redirects, ).await?; posts.push(post); - } + }; let initial_post = posts.into_iter() .find(|post| post.object_id.as_ref() == Some(&initial_object_id)) diff --git a/src/activitypub/handlers/create_note.rs b/src/activitypub/handlers/create_note.rs index a19f031..0cf48e1 100644 --- a/src/activitypub/handlers/create_note.rs +++ b/src/activitypub/handlers/create_note.rs @@ -114,6 +114,27 @@ fn get_note_visibility( Visibility::Direct } +async fn get_internal_post_id( + db_client: &impl GenericClient, + instance_url: &str, + object_id: &String, + redirects: &HashMap, +) -> Result { + match parse_local_object_id(instance_url, object_id) { + Ok(post_id) => { + // Local post + let post = get_post_by_id(db_client, &post_id).await?; + Ok(post.id) + }, + Err(_) => { + let real_object_id = redirects.get(object_id) + .unwrap_or(object_id); + let post = get_post_by_object_id(db_client, real_object_id).await?; + Ok(post.id) + }, + } +} + pub async fn handle_note( db_client: &mut impl GenericClient, instance: &Instance, @@ -175,6 +196,7 @@ pub async fn handle_note( }; let mut mentions: Vec = Vec::new(); let mut tags = vec![]; + let mut links = vec![]; if let Some(list) = object.tag { for tag in list { if tag.tag_type == HASHTAG { @@ -269,21 +291,26 @@ pub async fn handle_note( }; }; }; + if let Some(ref object_id) = object.quote_url { + log::warn!("link to object found: {}", object_id); + let quoted_id = get_internal_post_id( + db_client, + &instance.url(), + object_id, + redirects, + ).await?; + links.push(quoted_id); + }; + let in_reply_to_id = match object.in_reply_to { - Some(object_id) => { - match parse_local_object_id(&instance.url(), &object_id) { - Ok(post_id) => { - // Local post - let post = get_post_by_id(db_client, &post_id).await?; - Some(post.id) - }, - Err(_) => { - let note_id = redirects.get(&object_id) - .unwrap_or(&object_id); - let post = get_post_by_object_id(db_client, note_id).await?; - Some(post.id) - }, - } + Some(ref object_id) => { + let in_reply_to_id = get_internal_post_id( + db_client, + &instance.url(), + object_id, + redirects, + ).await?; + Some(in_reply_to_id) }, None => None, }; @@ -321,7 +348,7 @@ pub async fn handle_note( attachments: attachments, mentions: mentions, tags: tags, - links: vec![], + links: links, object_id: Some(object.id), created_at: object.published, };