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