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