]> Untitled Git - lemmy.git/blob - crates/apub/src/fetcher/mod.rs
Rewrite delete activities (#1699)
[lemmy.git] / crates / apub / src / fetcher / mod.rs
1 pub mod community;
2 mod fetch;
3 pub mod objects;
4 pub mod person;
5 pub mod search;
6
7 use crate::{
8   fetcher::{
9     community::get_or_fetch_and_upsert_community,
10     fetch::FetchError,
11     person::get_or_fetch_and_upsert_person,
12   },
13   ActorType,
14 };
15 use chrono::NaiveDateTime;
16 use http::StatusCode;
17 use lemmy_db_schema::naive_now;
18 use lemmy_utils::LemmyError;
19 use lemmy_websocket::LemmyContext;
20 use serde::Deserialize;
21 use url::Url;
22
23 static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60;
24 static ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG: i64 = 10;
25
26 fn is_deleted<Response>(fetch_response: &Result<Response, FetchError>) -> bool
27 where
28   Response: for<'de> Deserialize<'de>,
29 {
30   if let Err(e) = fetch_response {
31     if let Some(status) = e.status_code {
32       if status == StatusCode::GONE {
33         return true;
34       }
35     }
36   }
37   false
38 }
39
40 /// Get a remote actor from its apub ID (either a person or a community). Thin wrapper around
41 /// `get_or_fetch_and_upsert_person()` and `get_or_fetch_and_upsert_community()`.
42 ///
43 /// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
44 /// Otherwise it is fetched from the remote instance, stored and returned.
45 pub(crate) async fn get_or_fetch_and_upsert_actor(
46   apub_id: &Url,
47   context: &LemmyContext,
48   recursion_counter: &mut i32,
49 ) -> Result<Box<dyn ActorType>, LemmyError> {
50   let community = get_or_fetch_and_upsert_community(apub_id, context, recursion_counter).await;
51   let actor: Box<dyn ActorType> = match community {
52     Ok(c) => Box::new(c),
53     Err(_) => Box::new(get_or_fetch_and_upsert_person(apub_id, context, recursion_counter).await?),
54   };
55   Ok(actor)
56 }
57
58 /// Determines when a remote actor should be refetched from its instance. In release builds, this is
59 /// `ACTOR_REFETCH_INTERVAL_SECONDS` after the last refetch, in debug builds
60 /// `ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG`.
61 ///
62 /// TODO it won't pick up new avatars, summaries etc until a day after.
63 /// Actors need an "update" activity pushed to other servers to fix this.
64 fn should_refetch_actor(last_refreshed: NaiveDateTime) -> bool {
65   let update_interval = if cfg!(debug_assertions) {
66     // avoid infinite loop when fetching community outbox
67     chrono::Duration::seconds(ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG)
68   } else {
69     chrono::Duration::seconds(ACTOR_REFETCH_INTERVAL_SECONDS)
70   };
71   last_refreshed.lt(&(naive_now() - update_interval))
72 }