]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/announce.rs
Move code to apub library (#1795)
[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   context::lemmy_context,
21   fetcher::object_id::ObjectId,
22   http::is_activity_already_known,
23   insert_activity,
24   send_lemmy_activity,
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::{
34   data::Data,
35   traits::{ActivityFields, ActivityHandler, ActorType},
36   values::PublicUrl,
37 };
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, ActivityFields)]
45 #[serde(untagged)]
46 #[activity_handler(LemmyContext)]
47 pub enum AnnouncableActivities {
48   CreateOrUpdateComment(CreateOrUpdateComment),
49   CreateOrUpdatePost(Box<CreateOrUpdatePost>),
50   Vote(Vote),
51   UndoVote(UndoVote),
52   Delete(Delete),
53   UndoDelete(UndoDelete),
54   UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
55   UpdateCommunity(Box<UpdateCommunity>),
56   BlockUserFromCommunity(BlockUserFromCommunity),
57   UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
58   AddMod(AddMod),
59   RemoveMod(RemoveMod),
60 }
61
62 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
63 #[serde(rename_all = "camelCase")]
64 pub struct AnnounceActivity {
65   actor: ObjectId<Community>,
66   to: [PublicUrl; 1],
67   object: AnnouncableActivities,
68   cc: Vec<Url>,
69   #[serde(rename = "type")]
70   kind: AnnounceType,
71   id: Url,
72   #[serde(rename = "@context")]
73   context: OneOrMany<AnyBase>,
74   #[serde(flatten)]
75   unparsed: Unparsed,
76 }
77
78 impl AnnounceActivity {
79   pub async fn send(
80     object: AnnouncableActivities,
81     community: &Community,
82     additional_inboxes: Vec<Url>,
83     context: &LemmyContext,
84   ) -> Result<(), LemmyError> {
85     let announce = AnnounceActivity {
86       actor: ObjectId::new(community.actor_id()),
87       to: [PublicUrl::Public],
88       object,
89       cc: vec![community.followers_url()],
90       kind: AnnounceType::Announce,
91       id: generate_activity_id(
92         &AnnounceType::Announce,
93         &context.settings().get_protocol_and_hostname(),
94       )?,
95       context: lemmy_context(),
96       unparsed: Default::default(),
97     };
98     let inboxes = list_community_follower_inboxes(community, additional_inboxes, context).await?;
99     send_lemmy_activity(context, &announce, &announce.id, community, inboxes, false).await
100   }
101 }
102
103 #[async_trait::async_trait(?Send)]
104 impl ActivityHandler for AnnounceActivity {
105   type DataType = LemmyContext;
106   async fn verify(
107     &self,
108     context: &Data<LemmyContext>,
109     request_counter: &mut i32,
110   ) -> Result<(), LemmyError> {
111     verify_activity(self, &context.settings())?;
112     verify_community(&self.actor, context, request_counter).await?;
113     self.object.verify(context, request_counter).await?;
114     Ok(())
115   }
116
117   async fn receive(
118     self,
119     context: &Data<LemmyContext>,
120     request_counter: &mut i32,
121   ) -> Result<(), LemmyError> {
122     if is_activity_already_known(context.pool(), self.object.id_unchecked()).await? {
123       return Ok(());
124     }
125     insert_activity(
126       self.object.id_unchecked(),
127       self.object.clone(),
128       false,
129       true,
130       context.pool(),
131     )
132     .await?;
133     self.object.receive(context, request_counter).await
134   }
135 }