Move fetch_profile_by_actor_id to fetcher::helpers module

This commit is contained in:
silverpill 2022-07-09 21:24:37 +00:00
parent a06f1b4aba
commit 145622e805
3 changed files with 55 additions and 52 deletions

View file

@ -8,15 +8,11 @@ use crate::activitypub::actor::{Actor, ActorAddress};
use crate::activitypub::constants::ACTIVITY_CONTENT_TYPE; use crate::activitypub::constants::ACTIVITY_CONTENT_TYPE;
use crate::config::Instance; use crate::config::Instance;
use crate::http_signatures::create::{create_http_signature, SignatureError}; use crate::http_signatures::create::{create_http_signature, SignatureError};
use crate::models::profiles::types::ProfileCreateData;
use crate::utils::files::{save_file, FileError}; use crate::utils::files::{save_file, FileError};
use crate::webfinger::types::JsonResourceDescriptor; use crate::webfinger::types::JsonResourceDescriptor;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum FetchError { pub enum FetchError {
#[error("invalid URL")]
UrlError(#[from] url::ParseError),
#[error(transparent)] #[error(transparent)]
SignatureError(#[from] SignatureError), SignatureError(#[from] SignatureError),
@ -150,40 +146,6 @@ pub async fn fetch_avatar_and_banner(
Ok((avatar, banner)) Ok((avatar, banner))
} }
pub async fn fetch_profile_by_actor_id(
instance: &Instance,
actor_url: &str,
media_dir: &Path,
) -> Result<ProfileCreateData, FetchError> {
let actor = fetch_actor(instance, actor_url).await?;
let actor_host = url::Url::parse(&actor.id)?
.host_str()
.ok_or(url::ParseError::EmptyHost)?
.to_owned();
if actor_host == instance.host() {
return Err(FetchError::OtherError("trying to fetch local profile"));
};
let actor_address = format!(
"{}@{}",
actor.preferred_username,
actor_host,
);
let (avatar, banner) = fetch_avatar_and_banner(&actor, media_dir).await?;
let (identity_proofs, extra_fields) = actor.parse_attachments();
let profile_data = ProfileCreateData {
username: actor.preferred_username.clone(),
display_name: actor.name.clone(),
acct: actor_address,
bio: actor.summary.clone(),
avatar,
banner,
identity_proofs,
extra_fields,
actor_json: Some(actor),
};
Ok(profile_data)
}
pub async fn fetch_object( pub async fn fetch_object(
instance: &Instance, instance: &Instance,
object_url: &str, object_url: &str,

View file

@ -4,7 +4,7 @@ use std::path::Path;
use tokio_postgres::GenericClient; use tokio_postgres::GenericClient;
use crate::activitypub::activity::Object; use crate::activitypub::activity::Object;
use crate::activitypub::actor::ActorAddress; use crate::activitypub::actor::{Actor, ActorAddress};
use crate::activitypub::handlers::{ use crate::activitypub::handlers::{
create_note::handle_note, create_note::handle_note,
update_person::update_actor, update_person::update_actor,
@ -19,11 +19,11 @@ use crate::models::profiles::queries::{
get_profile_by_acct, get_profile_by_acct,
create_profile, create_profile,
}; };
use crate::models::profiles::types::DbActorProfile; use crate::models::profiles::types::{DbActorProfile, ProfileCreateData};
use super::fetchers::{ use super::fetchers::{
fetch_actor, fetch_actor,
fetch_avatar_and_banner,
fetch_object, fetch_object,
fetch_profile_by_actor_id,
perform_webfinger_query, perform_webfinger_query,
FetchError, FetchError,
}; };
@ -56,6 +56,45 @@ impl From<ImportError> for HttpError {
} }
} }
fn get_actor_host(actor_id: &str) -> Result<String, url::ParseError> {
let actor_host = url::Url::parse(actor_id)?
.host_str()
.ok_or(url::ParseError::EmptyHost)?
.to_owned();
Ok(actor_host)
}
async fn prepare_remote_profile_data(
instance: &Instance,
media_dir: &Path,
actor: Actor,
) -> Result<ProfileCreateData, ImportError> {
let actor_host = get_actor_host(&actor.id)
.map_err(|_| ValidationError("invalid actor ID"))?;
if actor_host == instance.host() {
return Err(ImportError::LocalObject);
};
let actor_address = format!(
"{}@{}",
actor.preferred_username,
actor_host,
);
let (avatar, banner) = fetch_avatar_and_banner(&actor, media_dir).await?;
let (identity_proofs, extra_fields) = actor.parse_attachments();
let profile_data = ProfileCreateData {
username: actor.preferred_username.clone(),
display_name: actor.name.clone(),
acct: actor_address,
bio: actor.summary.clone(),
avatar,
banner,
identity_proofs,
extra_fields,
actor_json: Some(actor),
};
Ok(profile_data)
}
pub async fn get_or_import_profile_by_actor_id( pub async fn get_or_import_profile_by_actor_id(
db_client: &impl GenericClient, db_client: &impl GenericClient,
instance: &Instance, instance: &Instance,
@ -77,14 +116,12 @@ pub async fn get_or_import_profile_by_actor_id(
} }
}, },
Err(DatabaseError::NotFound(_)) => { Err(DatabaseError::NotFound(_)) => {
let mut profile_data = fetch_profile_by_actor_id( let actor = fetch_actor(instance, actor_id).await?;
instance, actor_id, media_dir, let mut profile_data = prepare_remote_profile_data(
) instance,
.await media_dir,
.map_err(|err| { actor,
log::warn!("failed to fetch {} ({})", actor_id, err); ).await?;
err
})?;
log::info!("fetched profile {}", profile_data.acct); log::info!("fetched profile {}", profile_data.acct);
profile_data.clean()?; profile_data.clean()?;
let profile = create_profile(db_client, profile_data).await?; let profile = create_profile(db_client, profile_data).await?;
@ -106,10 +143,11 @@ pub async fn import_profile_by_actor_address(
return Err(ImportError::LocalObject); return Err(ImportError::LocalObject);
}; };
let actor_id = perform_webfinger_query(instance, actor_address).await?; let actor_id = perform_webfinger_query(instance, actor_address).await?;
let mut profile_data = fetch_profile_by_actor_id( let actor = fetch_actor(instance, &actor_id).await?;
let mut profile_data = prepare_remote_profile_data(
instance, instance,
&actor_id,
media_dir, media_dir,
actor,
).await?; ).await?;
if profile_data.acct != actor_address.acct() { if profile_data.acct != actor_address.acct() {
// Redirected to different server // Redirected to different server

View file

@ -106,7 +106,10 @@ pub async fn handle_note(
instance, instance,
media_dir, media_dir,
&author_id, &author_id,
).await?; ).await.map_err(|err| {
log::warn!("failed to import {} ({})", author_id, err);
err
})?;
let content = get_note_content(&object)?; let content = get_note_content(&object)?;
let mut attachments: Vec<Uuid> = Vec::new(); let mut attachments: Vec<Uuid> = Vec::new();