use activitypub_federation::{ config::Data, fetch::webfinger::webfinger_resolve_actor, traits::{Actor, Object}, }; use diesel::NotFound; use itertools::Itertools; use lemmy_api_common::context::LemmyContext; use lemmy_db_schema::traits::ApubActor; use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::LemmyError; pub mod post_or_comment; pub mod search; pub mod user_or_community; /// Resolve actor identifier like `!news@example.com` to user or community object. /// /// In case the requesting user is logged in and the object was not found locally, it is attempted /// to fetch via webfinger from the original instance. #[tracing::instrument(skip_all)] pub async fn resolve_actor_identifier( identifier: &str, context: &Data, local_user_view: &Option, include_deleted: bool, ) -> Result where ActorType: Object + Object + Actor + From + Send + 'static, for<'de2> ::Kind: serde::Deserialize<'de2>, DbActor: ApubActor + Send + 'static, { // remote actor if identifier.contains('@') { let (name, domain) = identifier .splitn(2, '@') .collect_tuple() .expect("invalid query"); let name = name.to_string(); let domain = format!("{}://{}", context.settings().get_protocol_string(), domain); let actor = DbActor::read_from_name_and_domain(context.pool(), &name, &domain).await; if actor.is_ok() { Ok(actor?.into()) } else if local_user_view.is_some() { // Fetch the actor from its home instance using webfinger let actor: ActorType = webfinger_resolve_actor(identifier, context).await?; Ok(actor) } else { Err(NotFound.into()) } } // local actor else { let identifier = identifier.to_string(); Ok( DbActor::read_from_name(context.pool(), &identifier, include_deleted) .await? .into(), ) } }