]> Untitled Git - lemmy.git/blob - crates/apub/src/fetcher/mod.rs
4f72d1488d5d8d9995e5efc99c1c92cb624d4435
[lemmy.git] / crates / apub / src / fetcher / mod.rs
1 use activitypub_federation::{
2   config::Data,
3   fetch::webfinger::webfinger_resolve_actor,
4   traits::{Actor, Object},
5 };
6 use diesel::NotFound;
7 use itertools::Itertools;
8 use lemmy_api_common::context::LemmyContext;
9 use lemmy_db_schema::traits::ApubActor;
10 use lemmy_db_views::structs::LocalUserView;
11 use lemmy_utils::error::LemmyError;
12
13 pub mod post_or_comment;
14 pub mod search;
15 pub mod user_or_community;
16
17 /// Resolve actor identifier like `!news@example.com` to user or community object.
18 ///
19 /// In case the requesting user is logged in and the object was not found locally, it is attempted
20 /// to fetch via webfinger from the original instance.
21 #[tracing::instrument(skip_all)]
22 pub async fn resolve_actor_identifier<ActorType, DbActor>(
23   identifier: &str,
24   context: &Data<LemmyContext>,
25   local_user_view: &Option<LocalUserView>,
26   include_deleted: bool,
27 ) -> Result<ActorType, LemmyError>
28 where
29   ActorType: Object<DataType = LemmyContext, Error = LemmyError>
30     + Object
31     + Actor
32     + From<DbActor>
33     + Send
34     + 'static,
35   for<'de2> <ActorType as Object>::Kind: serde::Deserialize<'de2>,
36   DbActor: ApubActor + Send + 'static,
37 {
38   // remote actor
39   if identifier.contains('@') {
40     let (name, domain) = identifier
41       .splitn(2, '@')
42       .collect_tuple()
43       .expect("invalid query");
44     let actor = DbActor::read_from_name_and_domain(context.pool(), name, domain).await;
45     if actor.is_ok() {
46       Ok(actor?.into())
47     } else if local_user_view.is_some() {
48       // Fetch the actor from its home instance using webfinger
49       let actor: ActorType = webfinger_resolve_actor(identifier, context).await?;
50       Ok(actor)
51     } else {
52       Err(NotFound.into())
53     }
54   }
55   // local actor
56   else {
57     let identifier = identifier.to_string();
58     Ok(
59       DbActor::read_from_name(context.pool(), &identifier, include_deleted)
60         .await?
61         .into(),
62     )
63   }
64 }