]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/announce.rs
For verify_is_public() we also need to check cc field
[lemmy.git] / crates / apub / src / activities / community / announce.rs
1 use crate::{
2   activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_is_public},
3   activity_lists::AnnouncableActivities,
4   http::{is_activity_already_known, ActivityCommonFields},
5   insert_activity,
6   objects::community::ApubCommunity,
7   protocol::activities::community::announce::AnnounceActivity,
8 };
9 use activitystreams::{activity::kind::AnnounceType, public};
10 use lemmy_apub_lib::{
11   data::Data,
12   object_id::ObjectId,
13   traits::{ActivityHandler, ActorType},
14 };
15 use lemmy_utils::LemmyError;
16 use lemmy_websocket::LemmyContext;
17 use url::Url;
18
19 #[async_trait::async_trait(?Send)]
20 pub(crate) trait GetCommunity {
21   async fn get_community(
22     &self,
23     context: &LemmyContext,
24     request_counter: &mut i32,
25   ) -> Result<ApubCommunity, LemmyError>;
26 }
27
28 impl AnnounceActivity {
29   pub async fn send(
30     object: AnnouncableActivities,
31     community: &ApubCommunity,
32     additional_inboxes: Vec<Url>,
33     context: &LemmyContext,
34   ) -> Result<(), LemmyError> {
35     let announce = AnnounceActivity {
36       actor: ObjectId::new(community.actor_id()),
37       to: vec![public()],
38       object,
39       cc: vec![community.followers_url.clone().into()],
40       kind: AnnounceType::Announce,
41       id: generate_activity_id(
42         &AnnounceType::Announce,
43         &context.settings().get_protocol_and_hostname(),
44       )?,
45       unparsed: Default::default(),
46     };
47     let inboxes = community
48       .get_follower_inboxes(additional_inboxes, context)
49       .await?;
50     send_lemmy_activity(context, &announce, &announce.id, community, inboxes, false).await
51   }
52 }
53
54 #[async_trait::async_trait(?Send)]
55 impl ActivityHandler for AnnounceActivity {
56   type DataType = LemmyContext;
57   async fn verify(
58     &self,
59     context: &Data<LemmyContext>,
60     request_counter: &mut i32,
61   ) -> Result<(), LemmyError> {
62     verify_is_public(&self.to, &self.cc)?;
63     verify_activity(&self.id, self.actor.inner(), &context.settings())?;
64     self.object.verify(context, request_counter).await?;
65     Ok(())
66   }
67
68   async fn receive(
69     self,
70     context: &Data<LemmyContext>,
71     request_counter: &mut i32,
72   ) -> Result<(), LemmyError> {
73     // TODO: this is pretty ugly, but i cant think of a much better way
74     let object = serde_json::to_string(&self.object)?;
75     let object_data: ActivityCommonFields = serde_json::from_str(&object)?;
76
77     if is_activity_already_known(context.pool(), &object_data.id).await? {
78       return Ok(());
79     }
80     insert_activity(
81       &object_data.id,
82       self.object.clone(),
83       false,
84       true,
85       context.pool(),
86     )
87     .await?;
88     self.object.receive(context, request_counter).await
89   }
90 }