]> Untitled Git - lemmy.git/blob - crates/apub/src/fetcher/user_or_community.rs
If viewed actor isnt in db, fetch it from other instance (#2145)
[lemmy.git] / crates / apub / src / fetcher / user_or_community.rs
1 use crate::{
2   objects::{community::ApubCommunity, person::ApubPerson},
3   protocol::objects::{group::Group, person::Person},
4 };
5 use chrono::NaiveDateTime;
6 use lemmy_apub_lib::traits::{ActorType, ApubObject};
7 use lemmy_utils::LemmyError;
8 use lemmy_websocket::LemmyContext;
9 use serde::Deserialize;
10 use url::Url;
11
12 #[derive(Clone, Debug)]
13 pub enum UserOrCommunity {
14   User(ApubPerson),
15   Community(ApubCommunity),
16 }
17
18 #[derive(Deserialize)]
19 #[serde(untagged)]
20 pub enum PersonOrGroup {
21   Person(Person),
22   Group(Group),
23 }
24
25 #[async_trait::async_trait(?Send)]
26 impl ApubObject for UserOrCommunity {
27   type DataType = LemmyContext;
28   type ApubType = PersonOrGroup;
29   type DbType = ();
30   type TombstoneType = ();
31
32   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
33     Some(match self {
34       UserOrCommunity::User(p) => p.last_refreshed_at,
35       UserOrCommunity::Community(p) => p.last_refreshed_at,
36     })
37   }
38
39   #[tracing::instrument(skip_all)]
40   async fn read_from_apub_id(
41     object_id: Url,
42     data: &Self::DataType,
43   ) -> Result<Option<Self>, LemmyError> {
44     let person = ApubPerson::read_from_apub_id(object_id.clone(), data).await?;
45     Ok(match person {
46       Some(o) => Some(UserOrCommunity::User(o)),
47       None => ApubCommunity::read_from_apub_id(object_id, data)
48         .await?
49         .map(UserOrCommunity::Community),
50     })
51   }
52
53   #[tracing::instrument(skip_all)]
54   async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
55     match self {
56       UserOrCommunity::User(p) => p.delete(data).await,
57       UserOrCommunity::Community(p) => p.delete(data).await,
58     }
59   }
60
61   async fn into_apub(self, _data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
62     unimplemented!()
63   }
64
65   fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
66     unimplemented!()
67   }
68
69   #[tracing::instrument(skip_all)]
70   async fn verify(
71     apub: &Self::ApubType,
72     expected_domain: &Url,
73     data: &Self::DataType,
74     request_counter: &mut i32,
75   ) -> Result<(), LemmyError> {
76     match apub {
77       PersonOrGroup::Person(a) => {
78         ApubPerson::verify(a, expected_domain, data, request_counter).await
79       }
80       PersonOrGroup::Group(a) => {
81         ApubCommunity::verify(a, expected_domain, data, request_counter).await
82       }
83     }
84   }
85
86   #[tracing::instrument(skip_all)]
87   async fn from_apub(
88     apub: Self::ApubType,
89     data: &Self::DataType,
90     request_counter: &mut i32,
91   ) -> Result<Self, LemmyError> {
92     Ok(match apub {
93       PersonOrGroup::Person(p) => {
94         UserOrCommunity::User(ApubPerson::from_apub(p, data, request_counter).await?)
95       }
96       PersonOrGroup::Group(p) => {
97         UserOrCommunity::Community(ApubCommunity::from_apub(p, data, request_counter).await?)
98       }
99     })
100   }
101 }
102
103 impl ActorType for UserOrCommunity {
104   fn actor_id(&self) -> Url {
105     match self {
106       UserOrCommunity::User(p) => p.actor_id(),
107       UserOrCommunity::Community(p) => p.actor_id(),
108     }
109   }
110
111   fn public_key(&self) -> String {
112     match self {
113       UserOrCommunity::User(p) => p.public_key(),
114       UserOrCommunity::Community(p) => p.public_key(),
115     }
116   }
117
118   fn private_key(&self) -> Option<String> {
119     todo!()
120   }
121
122   fn inbox_url(&self) -> Url {
123     todo!()
124   }
125
126   fn shared_inbox_url(&self) -> Option<Url> {
127     todo!()
128   }
129 }