]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/block/mod.rs
Extract Activitypub logic into separate library (#2288)
[lemmy.git] / crates / apub / src / activities / block / mod.rs
1 use crate::{
2   objects::{community::ApubCommunity, instance::ApubSite, person::ApubPerson},
3   protocol::objects::{group::Group, instance::Instance},
4   ActorType,
5 };
6 use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
7 use chrono::NaiveDateTime;
8 use lemmy_api_common::utils::blocking;
9 use lemmy_db_schema::{source::site::Site, utils::DbPool};
10 use lemmy_utils::error::LemmyError;
11 use lemmy_websocket::LemmyContext;
12 use serde::Deserialize;
13 use url::Url;
14
15 pub mod block_user;
16 pub mod undo_block_user;
17
18 #[derive(Clone, Debug)]
19 pub enum SiteOrCommunity {
20   Site(ApubSite),
21   Community(ApubCommunity),
22 }
23
24 #[derive(Deserialize)]
25 #[serde(untagged)]
26 pub enum InstanceOrGroup {
27   Instance(Instance),
28   Group(Group),
29 }
30
31 #[async_trait::async_trait(?Send)]
32 impl ApubObject for SiteOrCommunity {
33   type DataType = LemmyContext;
34   type ApubType = InstanceOrGroup;
35   type DbType = ();
36   type Error = LemmyError;
37
38   #[tracing::instrument(skip_all)]
39   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
40     Some(match self {
41       SiteOrCommunity::Site(i) => i.last_refreshed_at,
42       SiteOrCommunity::Community(c) => c.last_refreshed_at,
43     })
44   }
45
46   #[tracing::instrument(skip_all)]
47   async fn read_from_apub_id(
48     object_id: Url,
49     data: &Self::DataType,
50   ) -> Result<Option<Self>, LemmyError>
51   where
52     Self: Sized,
53   {
54     let site = ApubSite::read_from_apub_id(object_id.clone(), data).await?;
55     Ok(match site {
56       Some(o) => Some(SiteOrCommunity::Site(o)),
57       None => ApubCommunity::read_from_apub_id(object_id, data)
58         .await?
59         .map(SiteOrCommunity::Community),
60     })
61   }
62
63   async fn delete(self, _data: &Self::DataType) -> Result<(), LemmyError> {
64     unimplemented!()
65   }
66
67   async fn into_apub(self, _data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
68     unimplemented!()
69   }
70
71   #[tracing::instrument(skip_all)]
72   async fn verify(
73     apub: &Self::ApubType,
74     expected_domain: &Url,
75     data: &Self::DataType,
76     request_counter: &mut i32,
77   ) -> Result<(), LemmyError> {
78     match apub {
79       InstanceOrGroup::Instance(i) => {
80         ApubSite::verify(i, expected_domain, data, request_counter).await
81       }
82       InstanceOrGroup::Group(g) => {
83         ApubCommunity::verify(g, expected_domain, data, request_counter).await
84       }
85     }
86   }
87
88   #[tracing::instrument(skip_all)]
89   async fn from_apub(
90     apub: Self::ApubType,
91     data: &Self::DataType,
92     request_counter: &mut i32,
93   ) -> Result<Self, LemmyError>
94   where
95     Self: Sized,
96   {
97     Ok(match apub {
98       InstanceOrGroup::Instance(p) => {
99         SiteOrCommunity::Site(ApubSite::from_apub(p, data, request_counter).await?)
100       }
101       InstanceOrGroup::Group(n) => {
102         SiteOrCommunity::Community(ApubCommunity::from_apub(n, data, request_counter).await?)
103       }
104     })
105   }
106 }
107
108 impl SiteOrCommunity {
109   fn id(&self) -> ObjectId<SiteOrCommunity> {
110     match self {
111       SiteOrCommunity::Site(s) => ObjectId::new(s.actor_id.clone()),
112       SiteOrCommunity::Community(c) => ObjectId::new(c.actor_id.clone()),
113     }
114   }
115 }
116
117 async fn generate_cc(target: &SiteOrCommunity, pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
118   Ok(match target {
119     SiteOrCommunity::Site(_) => blocking(pool, Site::read_remote_sites)
120       .await??
121       .into_iter()
122       .map(|s| s.actor_id.into())
123       .collect(),
124     SiteOrCommunity::Community(c) => vec![c.actor_id()],
125   })
126 }
127
128 async fn generate_instance_inboxes(
129   blocked_user: &ApubPerson,
130   pool: &DbPool,
131 ) -> Result<Vec<Url>, LemmyError> {
132   let mut inboxes: Vec<Url> = blocking(pool, Site::read_remote_sites)
133     .await??
134     .into_iter()
135     .map(|s| s.inbox_url.into())
136     .collect();
137   inboxes.push(blocked_user.shared_inbox_or_inbox_url());
138   Ok(inboxes)
139 }