]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/announce.rs
b72cd1a5cbf1f69955547e2fe1bd1482a5b1b826
[lemmy.git] / crates / apub / src / activities / community / announce.rs
1 use crate::{
2   activities::{
3     comment::create_or_update::CreateOrUpdateComment,
4     community::{
5       add_mod::AddMod,
6       block_user::BlockUserFromCommunity,
7       list_community_follower_inboxes,
8       undo_block_user::UndoBlockUserFromCommunity,
9     },
10     deletion::{
11       delete::DeletePostCommentOrCommunity,
12       undo_delete::UndoDeletePostCommentOrCommunity,
13     },
14     generate_activity_id,
15     post::create_or_update::CreateOrUpdatePost,
16     removal::{
17       remove::RemovePostCommentCommunityOrMod,
18       undo_remove::UndoRemovePostCommentOrCommunity,
19     },
20     verify_activity,
21     verify_community,
22     voting::{
23       dislike::DislikePostOrComment,
24       like::LikePostOrComment,
25       undo_dislike::UndoDislikePostOrComment,
26       undo_like::UndoLikePostOrComment,
27     },
28   },
29   activity_queue::send_activity_new,
30   extensions::context::lemmy_context,
31   http::is_activity_already_known,
32   insert_activity,
33   ActorType,
34   CommunityType,
35 };
36 use activitystreams::activity::kind::AnnounceType;
37 use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
38 use lemmy_db_schema::source::community::Community;
39 use lemmy_utils::LemmyError;
40 use lemmy_websocket::LemmyContext;
41 use serde::{Deserialize, Serialize};
42 use url::Url;
43
44 #[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
45 #[serde(untagged)]
46 pub enum AnnouncableActivities {
47   CreateOrUpdateComment(CreateOrUpdateComment),
48   CreateOrUpdatePost(Box<CreateOrUpdatePost>),
49   LikePostOrComment(LikePostOrComment),
50   DislikePostOrComment(DislikePostOrComment),
51   UndoLikePostOrComment(UndoLikePostOrComment),
52   UndoDislikePostOrComment(UndoDislikePostOrComment),
53   DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
54   UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
55   RemovePostCommentCommunityOrMod(RemovePostCommentCommunityOrMod),
56   UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
57   BlockUserFromCommunity(BlockUserFromCommunity),
58   UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
59   AddMod(AddMod),
60 }
61
62 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
63 #[serde(rename_all = "camelCase")]
64 pub struct AnnounceActivity {
65   to: PublicUrl,
66   object: AnnouncableActivities,
67   cc: Vec<Url>,
68   #[serde(rename = "type")]
69   kind: AnnounceType,
70   #[serde(flatten)]
71   common: ActivityCommonFields,
72 }
73
74 impl AnnounceActivity {
75   pub async fn send(
76     object: AnnouncableActivities,
77     community: &Community,
78     additional_inboxes: Vec<Url>,
79     context: &LemmyContext,
80   ) -> Result<(), LemmyError> {
81     let announce = AnnounceActivity {
82       to: PublicUrl::Public,
83       object,
84       cc: vec![community.followers_url()],
85       kind: AnnounceType::Announce,
86       common: ActivityCommonFields {
87         context: lemmy_context(),
88         id: generate_activity_id(&AnnounceType::Announce)?,
89         actor: community.actor_id(),
90         unparsed: Default::default(),
91       },
92     };
93     let inboxes = list_community_follower_inboxes(community, additional_inboxes, context).await?;
94     send_activity_new(
95       context,
96       &announce,
97       &announce.common.id,
98       community,
99       inboxes,
100       false,
101     )
102     .await
103   }
104 }
105
106 #[async_trait::async_trait(?Send)]
107 impl ActivityHandler for AnnounceActivity {
108   async fn verify(
109     &self,
110     context: &LemmyContext,
111     request_counter: &mut i32,
112   ) -> Result<(), LemmyError> {
113     verify_activity(self.common())?;
114     verify_community(&self.common.actor, context, request_counter).await?;
115     self.object.verify(context, request_counter).await?;
116     Ok(())
117   }
118
119   async fn receive(
120     &self,
121     context: &LemmyContext,
122     request_counter: &mut i32,
123   ) -> Result<(), LemmyError> {
124     if is_activity_already_known(context.pool(), self.object.common().id_unchecked()).await? {
125       return Ok(());
126     }
127     insert_activity(
128       self.object.common().id_unchecked(),
129       self.object.clone(),
130       false,
131       true,
132       context.pool(),
133     )
134     .await?;
135     self.object.receive(context, request_counter).await
136   }
137
138   fn common(&self) -> &ActivityCommonFields {
139     &self.common
140   }
141 }