Refactor import_post function
This commit is contained in:
parent
5e1f441e8b
commit
b85a0fb7ac
6 changed files with 59 additions and 36 deletions
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use mitra_config::{Config, Instance};
|
use mitra_config::Instance;
|
||||||
|
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
actors::helpers::{create_remote_profile, update_remote_profile},
|
actors::helpers::{create_remote_profile, update_remote_profile},
|
||||||
|
@ -187,12 +187,12 @@ pub async fn get_post_by_object_id(
|
||||||
const RECURSION_DEPTH_MAX: usize = 50;
|
const RECURSION_DEPTH_MAX: usize = 50;
|
||||||
|
|
||||||
pub async fn import_post(
|
pub async fn import_post(
|
||||||
config: &Config,
|
|
||||||
db_client: &mut impl DatabaseClient,
|
db_client: &mut impl DatabaseClient,
|
||||||
|
instance: &Instance,
|
||||||
|
storage: &MediaStorage,
|
||||||
object_id: String,
|
object_id: String,
|
||||||
object_received: Option<Object>,
|
object_received: Option<Object>,
|
||||||
) -> Result<Post, HandlerError> {
|
) -> Result<Post, HandlerError> {
|
||||||
let instance = config.instance();
|
|
||||||
if parse_local_object_id(&instance.url(), &object_id).is_ok() {
|
if parse_local_object_id(&instance.url(), &object_id).is_ok() {
|
||||||
return Err(HandlerError::LocalObject);
|
return Err(HandlerError::LocalObject);
|
||||||
};
|
};
|
||||||
|
@ -250,7 +250,7 @@ pub async fn import_post(
|
||||||
// TODO: create tombstone
|
// TODO: create tombstone
|
||||||
return Err(FetchError::RecursionError.into());
|
return Err(FetchError::RecursionError.into());
|
||||||
};
|
};
|
||||||
let object = fetch_object(&instance, &object_id).await
|
let object = fetch_object(instance, &object_id).await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
log::warn!("{}", err);
|
log::warn!("{}", err);
|
||||||
ValidationError("failed to fetch object")
|
ValidationError("failed to fetch object")
|
||||||
|
@ -287,8 +287,9 @@ pub async fn import_post(
|
||||||
objects.reverse();
|
objects.reverse();
|
||||||
for object in objects {
|
for object in objects {
|
||||||
let post = handle_note(
|
let post = handle_note(
|
||||||
config,
|
|
||||||
db_client,
|
db_client,
|
||||||
|
instance,
|
||||||
|
storage,
|
||||||
object,
|
object,
|
||||||
&redirects,
|
&redirects,
|
||||||
).await?;
|
).await?;
|
||||||
|
|
|
@ -52,20 +52,28 @@ pub async fn handle_announce(
|
||||||
Err(DatabaseError::NotFound(_)) => (),
|
Err(DatabaseError::NotFound(_)) => (),
|
||||||
Err(other_error) => return Err(other_error.into()),
|
Err(other_error) => return Err(other_error.into()),
|
||||||
};
|
};
|
||||||
|
let instance = config.instance();
|
||||||
|
let storage = MediaStorage::from(config);
|
||||||
let author = get_or_import_profile_by_actor_id(
|
let author = get_or_import_profile_by_actor_id(
|
||||||
db_client,
|
db_client,
|
||||||
&config.instance(),
|
&instance,
|
||||||
&MediaStorage::from(config),
|
&storage,
|
||||||
&activity.actor,
|
&activity.actor,
|
||||||
).await?;
|
).await?;
|
||||||
let post_id = match parse_local_object_id(
|
let post_id = match parse_local_object_id(
|
||||||
&config.instance_url(),
|
&instance.url(),
|
||||||
&activity.object,
|
&activity.object,
|
||||||
) {
|
) {
|
||||||
Ok(post_id) => post_id,
|
Ok(post_id) => post_id,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Try to get remote post
|
// Try to get remote post
|
||||||
let post = import_post(config, db_client, activity.object, None).await?;
|
let post = import_post(
|
||||||
|
db_client,
|
||||||
|
&instance,
|
||||||
|
&storage,
|
||||||
|
activity.object,
|
||||||
|
None,
|
||||||
|
).await?;
|
||||||
post.id
|
post.id
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -126,13 +126,12 @@ fn is_gnu_social_link(author_id: &str, attachment: &Attachment) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_object_attachments(
|
pub async fn get_object_attachments(
|
||||||
config: &Config,
|
|
||||||
db_client: &impl DatabaseClient,
|
db_client: &impl DatabaseClient,
|
||||||
|
instance: &Instance,
|
||||||
|
storage: &MediaStorage,
|
||||||
object: &Object,
|
object: &Object,
|
||||||
author: &DbActorProfile,
|
author: &DbActorProfile,
|
||||||
) -> Result<(Vec<Uuid>, Vec<String>), HandlerError> {
|
) -> Result<(Vec<Uuid>, Vec<String>), HandlerError> {
|
||||||
let instance = config.instance();
|
|
||||||
let media_dir = config.media_dir();
|
|
||||||
let mut attachments = vec![];
|
let mut attachments = vec![];
|
||||||
let mut unprocessed = vec![];
|
let mut unprocessed = vec![];
|
||||||
if let Some(ref value) = object.attachment {
|
if let Some(ref value) = object.attachment {
|
||||||
|
@ -160,11 +159,11 @@ pub async fn get_object_attachments(
|
||||||
let attachment_url = attachment.url
|
let attachment_url = attachment.url
|
||||||
.ok_or(ValidationError("attachment URL is missing"))?;
|
.ok_or(ValidationError("attachment URL is missing"))?;
|
||||||
let (file_name, file_size, maybe_media_type) = match fetch_file(
|
let (file_name, file_size, maybe_media_type) = match fetch_file(
|
||||||
&instance,
|
instance,
|
||||||
&attachment_url,
|
&attachment_url,
|
||||||
attachment.media_type.as_deref(),
|
attachment.media_type.as_deref(),
|
||||||
config.limits.media.file_size_limit,
|
storage.file_size_limit,
|
||||||
&media_dir,
|
&storage.media_dir,
|
||||||
).await {
|
).await {
|
||||||
Ok(file) => file,
|
Ok(file) => file,
|
||||||
Err(FetchError::FileTooLarge) => {
|
Err(FetchError::FileTooLarge) => {
|
||||||
|
@ -331,13 +330,12 @@ pub async fn handle_emoji(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_object_tags(
|
pub async fn get_object_tags(
|
||||||
config: &Config,
|
|
||||||
db_client: &mut impl DatabaseClient,
|
db_client: &mut impl DatabaseClient,
|
||||||
|
instance: &Instance,
|
||||||
|
storage: &MediaStorage,
|
||||||
object: &Object,
|
object: &Object,
|
||||||
redirects: &HashMap<String, String>,
|
redirects: &HashMap<String, String>,
|
||||||
) -> Result<(Vec<Uuid>, Vec<String>, Vec<Uuid>, Vec<Uuid>), HandlerError> {
|
) -> Result<(Vec<Uuid>, Vec<String>, Vec<Uuid>, Vec<Uuid>), HandlerError> {
|
||||||
let instance = config.instance();
|
|
||||||
let storage = MediaStorage::from(config);
|
|
||||||
let mut mentions = vec![];
|
let mut mentions = vec![];
|
||||||
let mut hashtags = vec![];
|
let mut hashtags = vec![];
|
||||||
let mut links = vec![];
|
let mut links = vec![];
|
||||||
|
@ -381,8 +379,8 @@ pub async fn get_object_tags(
|
||||||
// but also can be actor URL (profile link).
|
// but also can be actor URL (profile link).
|
||||||
match get_or_import_profile_by_actor_id(
|
match get_or_import_profile_by_actor_id(
|
||||||
db_client,
|
db_client,
|
||||||
&instance,
|
instance,
|
||||||
&storage,
|
storage,
|
||||||
&href,
|
&href,
|
||||||
).await {
|
).await {
|
||||||
Ok(profile) => {
|
Ok(profile) => {
|
||||||
|
@ -411,8 +409,8 @@ pub async fn get_object_tags(
|
||||||
if let Ok(actor_address) = ActorAddress::from_mention(&tag_name) {
|
if let Ok(actor_address) = ActorAddress::from_mention(&tag_name) {
|
||||||
let profile = match get_or_import_profile_by_actor_address(
|
let profile = match get_or_import_profile_by_actor_address(
|
||||||
db_client,
|
db_client,
|
||||||
&instance,
|
instance,
|
||||||
&storage,
|
storage,
|
||||||
&actor_address,
|
&actor_address,
|
||||||
).await {
|
).await {
|
||||||
Ok(profile) => profile,
|
Ok(profile) => profile,
|
||||||
|
@ -467,8 +465,8 @@ pub async fn get_object_tags(
|
||||||
};
|
};
|
||||||
match handle_emoji(
|
match handle_emoji(
|
||||||
db_client,
|
db_client,
|
||||||
&instance,
|
instance,
|
||||||
&storage,
|
storage,
|
||||||
tag_value,
|
tag_value,
|
||||||
).await? {
|
).await? {
|
||||||
Some(emoji) => {
|
Some(emoji) => {
|
||||||
|
@ -527,13 +525,12 @@ fn get_object_visibility(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_note(
|
pub async fn handle_note(
|
||||||
config: &Config,
|
|
||||||
db_client: &mut impl DatabaseClient,
|
db_client: &mut impl DatabaseClient,
|
||||||
|
instance: &Instance,
|
||||||
|
storage: &MediaStorage,
|
||||||
object: Object,
|
object: Object,
|
||||||
redirects: &HashMap<String, String>,
|
redirects: &HashMap<String, String>,
|
||||||
) -> Result<Post, HandlerError> {
|
) -> Result<Post, HandlerError> {
|
||||||
let instance = config.instance();
|
|
||||||
let storage = MediaStorage::from(config);
|
|
||||||
match object.object_type.as_str() {
|
match object.object_type.as_str() {
|
||||||
NOTE => (),
|
NOTE => (),
|
||||||
ARTICLE | EVENT | QUESTION | PAGE | VIDEO => {
|
ARTICLE | EVENT | QUESTION | PAGE | VIDEO => {
|
||||||
|
@ -548,8 +545,8 @@ pub async fn handle_note(
|
||||||
let author_id = get_object_attributed_to(&object)?;
|
let author_id = get_object_attributed_to(&object)?;
|
||||||
let author = get_or_import_profile_by_actor_id(
|
let author = get_or_import_profile_by_actor_id(
|
||||||
db_client,
|
db_client,
|
||||||
&instance,
|
instance,
|
||||||
&storage,
|
storage,
|
||||||
&author_id,
|
&author_id,
|
||||||
).await.map_err(|err| {
|
).await.map_err(|err| {
|
||||||
log::warn!("failed to import {} ({})", author_id, err);
|
log::warn!("failed to import {} ({})", author_id, err);
|
||||||
|
@ -563,8 +560,9 @@ pub async fn handle_note(
|
||||||
content += &create_content_link(object_url);
|
content += &create_content_link(object_url);
|
||||||
};
|
};
|
||||||
let (attachments, unprocessed) = get_object_attachments(
|
let (attachments, unprocessed) = get_object_attachments(
|
||||||
config,
|
|
||||||
db_client,
|
db_client,
|
||||||
|
instance,
|
||||||
|
storage,
|
||||||
&object,
|
&object,
|
||||||
&author,
|
&author,
|
||||||
).await?;
|
).await?;
|
||||||
|
@ -576,8 +574,9 @@ pub async fn handle_note(
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mentions, hashtags, links, emojis) = get_object_tags(
|
let (mentions, hashtags, links, emojis) = get_object_tags(
|
||||||
config,
|
|
||||||
db_client,
|
db_client,
|
||||||
|
instance,
|
||||||
|
storage,
|
||||||
&object,
|
&object,
|
||||||
redirects,
|
redirects,
|
||||||
).await?;
|
).await?;
|
||||||
|
@ -654,7 +653,13 @@ pub async fn handle_create(
|
||||||
// Most likely it's a forwarded reply.
|
// Most likely it's a forwarded reply.
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
import_post(config, db_client, object_id, object_received).await?;
|
import_post(
|
||||||
|
db_client,
|
||||||
|
&config.instance(),
|
||||||
|
&MediaStorage::from(config),
|
||||||
|
object_id,
|
||||||
|
object_received,
|
||||||
|
).await?;
|
||||||
Ok(Some(NOTE))
|
Ok(Some(NOTE))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,9 +56,12 @@ async fn handle_update_note(
|
||||||
let object_url = get_object_url(&object)?;
|
let object_url = get_object_url(&object)?;
|
||||||
content += &create_content_link(object_url);
|
content += &create_content_link(object_url);
|
||||||
};
|
};
|
||||||
|
let instance = config.instance();
|
||||||
|
let storage = MediaStorage::from(config);
|
||||||
let (attachments, unprocessed) = get_object_attachments(
|
let (attachments, unprocessed) = get_object_attachments(
|
||||||
config,
|
|
||||||
db_client,
|
db_client,
|
||||||
|
&instance,
|
||||||
|
&storage,
|
||||||
&object,
|
&object,
|
||||||
&post.author,
|
&post.author,
|
||||||
).await?;
|
).await?;
|
||||||
|
@ -69,8 +72,9 @@ async fn handle_update_note(
|
||||||
return Err(ValidationError("post is empty").into());
|
return Err(ValidationError("post is empty").into());
|
||||||
};
|
};
|
||||||
let (mentions, hashtags, links, emojis) = get_object_tags(
|
let (mentions, hashtags, links, emojis) = get_object_tags(
|
||||||
config,
|
|
||||||
db_client,
|
db_client,
|
||||||
|
&instance,
|
||||||
|
&storage,
|
||||||
&object,
|
&object,
|
||||||
&HashMap::new(),
|
&HashMap::new(),
|
||||||
).await?;
|
).await?;
|
||||||
|
|
|
@ -154,8 +154,10 @@ async fn find_post_by_url(
|
||||||
db_client: &mut impl DatabaseClient,
|
db_client: &mut impl DatabaseClient,
|
||||||
url: &str,
|
url: &str,
|
||||||
) -> Result<Option<Post>, DatabaseError> {
|
) -> Result<Option<Post>, DatabaseError> {
|
||||||
|
let instance = config.instance();
|
||||||
|
let storage = MediaStorage::from(config);
|
||||||
let maybe_post = match parse_local_object_id(
|
let maybe_post = match parse_local_object_id(
|
||||||
&config.instance_url(),
|
&instance.url(),
|
||||||
url,
|
url,
|
||||||
) {
|
) {
|
||||||
Ok(post_id) => {
|
Ok(post_id) => {
|
||||||
|
@ -168,8 +170,9 @@ async fn find_post_by_url(
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
match import_post(
|
match import_post(
|
||||||
config,
|
|
||||||
db_client,
|
db_client,
|
||||||
|
&instance,
|
||||||
|
&storage,
|
||||||
url.to_string(),
|
url.to_string(),
|
||||||
None,
|
None,
|
||||||
).await {
|
).await {
|
||||||
|
|
|
@ -89,6 +89,7 @@ pub async fn remove_media(
|
||||||
|
|
||||||
pub struct MediaStorage {
|
pub struct MediaStorage {
|
||||||
pub media_dir: PathBuf,
|
pub media_dir: PathBuf,
|
||||||
|
pub file_size_limit: usize,
|
||||||
pub emoji_size_limit: usize,
|
pub emoji_size_limit: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +97,7 @@ impl From<&Config> for MediaStorage {
|
||||||
fn from(config: &Config) -> Self {
|
fn from(config: &Config) -> Self {
|
||||||
Self {
|
Self {
|
||||||
media_dir: config.media_dir(),
|
media_dir: config.media_dir(),
|
||||||
|
file_size_limit: config.limits.media.file_size_limit,
|
||||||
emoji_size_limit: config.limits.media.emoji_size_limit,
|
emoji_size_limit: config.limits.media.emoji_size_limit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue