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