]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/announce.rs
e7d917b72d9524827088e9a761f48b7ab42aeba8
[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       remove_mod::RemoveMod,
9       undo_block_user::UndoBlockUserFromCommunity,
10       update::UpdateCommunity,
11     },
12     deletion::{delete::Delete, undo_delete::UndoDelete},
13     generate_activity_id,
14     post::create_or_update::CreateOrUpdatePost,
15     undo_remove::UndoRemovePostCommentOrCommunity,
16     verify_activity,
17     verify_community,
18     voting::{undo_vote::UndoVote, vote::Vote},
19   },
20   activity_queue::send_activity_new,
21   extensions::context::lemmy_context,
22   http::is_activity_already_known,
23   insert_activity,
24   ActorType,
25   CommunityType,
26 };
27 use activitystreams::{
28   activity::kind::AnnounceType,
29   base::AnyBase,
30   primitives::OneOrMany,
31   unparsed::Unparsed,
32 };
33 use lemmy_apub_lib::{values::PublicUrl, ActivityFields, ActivityHandler};
34 use lemmy_db_schema::source::community::Community;
35 use lemmy_utils::LemmyError;
36 use lemmy_websocket::LemmyContext;
37 use serde::{Deserialize, Serialize};
38 use url::Url;
39
40 #[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
41 #[serde(untagged)]
42 pub enum AnnouncableActivities {
43   CreateOrUpdateComment(CreateOrUpdateComment),
44   CreateOrUpdatePost(Box<CreateOrUpdatePost>),
45   Vote(Vote),
46   UndoVote(UndoVote),
47   Delete(Delete),
48   UndoDelete(UndoDelete),
49   UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
50   UpdateCommunity(Box<UpdateCommunity>),
51   BlockUserFromCommunity(BlockUserFromCommunity),
52   UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
53   AddMod(AddMod),
54   RemoveMod(RemoveMod),
55 }
56
57 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
58 #[serde(rename_all = "camelCase")]
59 pub struct AnnounceActivity {
60   actor: Url,
61   to: PublicUrl,
62   object: AnnouncableActivities,
63   cc: Vec<Url>,
64   #[serde(rename = "type")]
65   kind: AnnounceType,
66   id: Url,
67   #[serde(rename = "@context")]
68   context: OneOrMany<AnyBase>,
69   #[serde(flatten)]
70   unparsed: Unparsed,
71 }
72
73 impl AnnounceActivity {
74   pub async fn send(
75     object: AnnouncableActivities,
76     community: &Community,
77     additional_inboxes: Vec<Url>,
78     context: &LemmyContext,
79   ) -> Result<(), LemmyError> {
80     let announce = AnnounceActivity {
81       actor: community.actor_id(),
82       to: PublicUrl::Public,
83       object,
84       cc: vec![community.followers_url()],
85       kind: AnnounceType::Announce,
86       id: generate_activity_id(&AnnounceType::Announce)?,
87       context: lemmy_context(),
88       unparsed: Default::default(),
89     };
90     let inboxes = list_community_follower_inboxes(community, additional_inboxes, context).await?;
91     send_activity_new(context, &announce, &announce.id, community, inboxes, false).await
92   }
93 }
94
95 #[async_trait::async_trait(?Send)]
96 impl ActivityHandler for AnnounceActivity {
97   async fn verify(
98     &self,
99     context: &LemmyContext,
100     request_counter: &mut i32,
101   ) -> Result<(), LemmyError> {
102     verify_activity(self)?;
103     verify_community(&self.actor, context, request_counter).await?;
104     self.object.verify(context, request_counter).await?;
105     Ok(())
106   }
107
108   async fn receive(
109     self,
110     context: &LemmyContext,
111     request_counter: &mut i32,
112   ) -> Result<(), LemmyError> {
113     if is_activity_already_known(context.pool(), self.object.id_unchecked()).await? {
114       return Ok(());
115     }
116     insert_activity(
117       self.object.id_unchecked(),
118       self.object.clone(),
119       false,
120       true,
121       context.pool(),
122     )
123     .await?;
124     self.object.receive(context, request_counter).await
125   }
126 }