]> Untitled Git - lemmy.git/blob - crates/apub/src/fetcher/person.rs
Moving settings and secrets to context.
[lemmy.git] / crates / apub / src / fetcher / person.rs
1 use crate::{
2   fetcher::{fetch::fetch_remote_object, is_deleted, should_refetch_actor},
3   objects::{person::Person as ApubPerson, FromApub},
4 };
5 use anyhow::anyhow;
6 use diesel::result::Error::NotFound;
7 use lemmy_api_common::blocking;
8 use lemmy_db_queries::{source::person::Person_, ApubObject};
9 use lemmy_db_schema::source::person::Person;
10 use lemmy_utils::LemmyError;
11 use lemmy_websocket::LemmyContext;
12 use log::debug;
13 use url::Url;
14
15 /// Get a person from its apub ID.
16 ///
17 /// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
18 /// Otherwise it is fetched from the remote instance, stored and returned.
19 pub(crate) async fn get_or_fetch_and_upsert_person(
20   apub_id: &Url,
21   context: &LemmyContext,
22   recursion_counter: &mut i32,
23 ) -> Result<Person, LemmyError> {
24   let apub_id_owned = apub_id.to_owned();
25   let person = blocking(context.pool(), move |conn| {
26     Person::read_from_apub_id(conn, &apub_id_owned.into())
27   })
28   .await?;
29
30   match person {
31     // If its older than a day, re-fetch it
32     Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => {
33       debug!("Fetching and updating from remote person: {}", apub_id);
34       let person = fetch_remote_object::<ApubPerson>(
35         context.client(),
36         &context.settings(),
37         apub_id,
38         recursion_counter,
39       )
40       .await;
41
42       if is_deleted(&person) {
43         // TODO: use Person::update_deleted() once implemented
44         blocking(context.pool(), move |conn| {
45           Person::delete_account(conn, u.id)
46         })
47         .await??;
48         return Err(anyhow!("Person was deleted by remote instance").into());
49       } else if person.is_err() {
50         return Ok(u);
51       }
52
53       let person = Person::from_apub(&person?, context, apub_id, recursion_counter).await?;
54
55       let person_id = person.id;
56       blocking(context.pool(), move |conn| {
57         Person::mark_as_updated(conn, person_id)
58       })
59       .await??;
60
61       Ok(person)
62     }
63     Ok(u) => Ok(u),
64     Err(NotFound {}) => {
65       debug!("Fetching and creating remote person: {}", apub_id);
66       let person = fetch_remote_object::<ApubPerson>(
67         context.client(),
68         &context.settings(),
69         apub_id,
70         recursion_counter,
71       )
72       .await?;
73
74       let person = Person::from_apub(&person, context, apub_id, recursion_counter).await?;
75
76       Ok(person)
77     }
78     Err(e) => Err(e.into()),
79   }
80 }