Fetch object referenced by quoteUrl property and create a link between posts

This commit is contained in:
silverpill 2022-08-21 22:51:40 +00:00
parent d9def75b32
commit f4d1e756d4
3 changed files with 60 additions and 19 deletions

View file

@ -78,6 +78,9 @@ pub struct Object {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub content: Option<String>, pub content: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quote_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub tag: Option<Vec<Tag>>, pub tag: Option<Vec<Tag>>,

View file

@ -205,6 +205,7 @@ pub async fn import_post(
// Fetch ancestors by going through inReplyTo references // Fetch ancestors by going through inReplyTo references
// TODO: fetch replies too // TODO: fetch replies too
#[allow(clippy::while_let_loop)] #[allow(clippy::while_let_loop)]
#[allow(clippy::manual_map)]
loop { loop {
let object_id = match maybe_object_id_to_fetch { let object_id = match maybe_object_id_to_fetch {
Some(object_id) => { Some(object_id) => {
@ -212,7 +213,7 @@ pub async fn import_post(
// Object is a local post // Object is a local post
assert!(objects.len() > 0); assert!(objects.len() > 0);
break; break;
} };
match get_post_by_object_id(db_client, &object_id).await { match get_post_by_object_id(db_client, &object_id).await {
Ok(post) => { Ok(post) => {
// Object already fetched // Object already fetched
@ -252,11 +253,21 @@ pub async fn import_post(
// Don't re-fetch object on the next iteration // Don't re-fetch object on the next iteration
maybe_object = Some(object); maybe_object = Some(object);
} else { } 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; maybe_object = None;
objects.push(object); objects.push(object);
}; };
} };
let initial_object_id = objects[0].id.clone(); let initial_object_id = objects[0].id.clone();
// Objects are ordered according to their place in reply tree, // Objects are ordered according to their place in reply tree,
@ -271,7 +282,7 @@ pub async fn import_post(
&redirects, &redirects,
).await?; ).await?;
posts.push(post); posts.push(post);
} };
let initial_post = posts.into_iter() let initial_post = posts.into_iter()
.find(|post| post.object_id.as_ref() == Some(&initial_object_id)) .find(|post| post.object_id.as_ref() == Some(&initial_object_id))

View file

@ -114,6 +114,27 @@ fn get_note_visibility(
Visibility::Direct Visibility::Direct
} }
async fn get_internal_post_id(
db_client: &impl GenericClient,
instance_url: &str,
object_id: &String,
redirects: &HashMap<String, String>,
) -> Result<Uuid, ImportError> {
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( pub async fn handle_note(
db_client: &mut impl GenericClient, db_client: &mut impl GenericClient,
instance: &Instance, instance: &Instance,
@ -175,6 +196,7 @@ pub async fn handle_note(
}; };
let mut mentions: Vec<Uuid> = Vec::new(); let mut mentions: Vec<Uuid> = Vec::new();
let mut tags = vec![]; let mut tags = vec![];
let mut links = vec![];
if let Some(list) = object.tag { if let Some(list) = object.tag {
for tag in list { for tag in list {
if tag.tag_type == HASHTAG { 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 { let in_reply_to_id = match object.in_reply_to {
Some(object_id) => { Some(ref object_id) => {
match parse_local_object_id(&instance.url(), &object_id) { let in_reply_to_id = get_internal_post_id(
Ok(post_id) => { db_client,
// Local post &instance.url(),
let post = get_post_by_id(db_client, &post_id).await?; object_id,
Some(post.id) redirects,
}, ).await?;
Err(_) => { Some(in_reply_to_id)
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)
},
}
}, },
None => None, None => None,
}; };
@ -321,7 +348,7 @@ pub async fn handle_note(
attachments: attachments, attachments: attachments,
mentions: mentions, mentions: mentions,
tags: tags, tags: tags,
links: vec![], links: links,
object_id: Some(object.id), object_id: Some(object.id),
created_at: object.published, created_at: object.published,
}; };