2022-03-23 21:27:51 +00:00
|
|
|
use crate::fetcher::webfinger::webfinger_resolve_actor;
|
|
|
|
use itertools::Itertools;
|
2022-05-03 17:44:13 +00:00
|
|
|
use lemmy_api_common::utils::blocking;
|
2022-03-23 21:27:51 +00:00
|
|
|
use lemmy_apub_lib::traits::{ActorType, ApubObject};
|
|
|
|
use lemmy_db_schema::traits::ApubActor;
|
|
|
|
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
|
|
|
use lemmy_websocket::LemmyContext;
|
|
|
|
|
2021-09-25 15:44:52 +00:00
|
|
|
pub mod post_or_comment;
|
2021-03-11 04:43:11 +00:00
|
|
|
pub mod search;
|
2021-11-03 17:33:51 +00:00
|
|
|
pub mod user_or_community;
|
2021-11-16 17:03:09 +00:00
|
|
|
pub mod webfinger;
|
2022-03-23 21:27:51 +00:00
|
|
|
|
|
|
|
/// Resolve actor identifier (eg `!news@example.com`) from local database to avoid network requests.
|
|
|
|
/// This only works for local actors, and remote actors which were previously fetched (so it doesnt
|
|
|
|
/// trigger any new fetch).
|
|
|
|
#[tracing::instrument(skip_all)]
|
|
|
|
pub async fn resolve_actor_identifier<Actor, DbActor>(
|
|
|
|
identifier: &str,
|
|
|
|
context: &LemmyContext,
|
|
|
|
) -> Result<DbActor, LemmyError>
|
|
|
|
where
|
|
|
|
Actor:
|
|
|
|
ApubObject<DataType = LemmyContext> + ApubObject<DbType = DbActor> + ActorType + Send + 'static,
|
|
|
|
for<'de2> <Actor as ApubObject>::ApubType: 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!("{}://{}", Settings::get().get_protocol_string(), domain);
|
|
|
|
let actor = blocking(context.pool(), move |conn| {
|
|
|
|
DbActor::read_from_name_and_domain(conn, &name, &domain)
|
|
|
|
})
|
|
|
|
.await?;
|
|
|
|
if actor.is_ok() {
|
|
|
|
Ok(actor?)
|
|
|
|
} else {
|
|
|
|
// Fetch the actor from its home instance using webfinger
|
|
|
|
let id = webfinger_resolve_actor::<Actor>(identifier, context, &mut 0).await?;
|
|
|
|
let actor: DbActor = blocking(context.pool(), move |conn| {
|
|
|
|
DbActor::read_from_apub_id(conn, &id)
|
|
|
|
})
|
|
|
|
.await??
|
|
|
|
.expect("actor exists as we fetched just before");
|
|
|
|
Ok(actor)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// local actor
|
|
|
|
else {
|
|
|
|
let identifier = identifier.to_string();
|
|
|
|
Ok(
|
|
|
|
blocking(context.pool(), move |conn| {
|
|
|
|
DbActor::read_from_name(conn, &identifier)
|
|
|
|
})
|
|
|
|
.await??,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|