]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/following/accept.rs
34764264e76647d03fb9584f909377146be7143c
[lemmy.git] / crates / apub / src / activities / following / accept.rs
1 use crate::{
2   activities::{generate_activity_id, send_lemmy_activity},
3   local_instance,
4   protocol::activities::following::{accept::AcceptFollowCommunity, follow::FollowCommunity},
5   ActorType,
6 };
7 use activitypub_federation::{
8   core::object_id::ObjectId,
9   data::Data,
10   traits::{ActivityHandler, Actor},
11   utils::verify_urls_match,
12 };
13 use activitystreams_kinds::activity::AcceptType;
14 use lemmy_api_common::utils::blocking;
15 use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
16 use lemmy_utils::error::LemmyError;
17 use lemmy_websocket::LemmyContext;
18 use url::Url;
19
20 impl AcceptFollowCommunity {
21   #[tracing::instrument(skip_all)]
22   pub async fn send(
23     follow: FollowCommunity,
24     context: &LemmyContext,
25     request_counter: &mut i32,
26   ) -> Result<(), LemmyError> {
27     let community = follow.object.dereference_local(context).await?;
28     let person = follow
29       .actor
30       .clone()
31       .dereference(context, local_instance(context), request_counter)
32       .await?;
33     let accept = AcceptFollowCommunity {
34       actor: ObjectId::new(community.actor_id()),
35       object: follow,
36       kind: AcceptType::Accept,
37       id: generate_activity_id(
38         AcceptType::Accept,
39         &context.settings().get_protocol_and_hostname(),
40       )?,
41       unparsed: Default::default(),
42     };
43     let inbox = vec![person.shared_inbox_or_inbox()];
44     send_lemmy_activity(context, accept, &community, inbox, true).await
45   }
46 }
47
48 /// Handle accepted follows
49 #[async_trait::async_trait(?Send)]
50 impl ActivityHandler for AcceptFollowCommunity {
51   type DataType = LemmyContext;
52   type Error = LemmyError;
53
54   fn id(&self) -> &Url {
55     &self.id
56   }
57
58   fn actor(&self) -> &Url {
59     self.actor.inner()
60   }
61
62   #[tracing::instrument(skip_all)]
63   async fn verify(
64     &self,
65     context: &Data<LemmyContext>,
66     request_counter: &mut i32,
67   ) -> Result<(), LemmyError> {
68     verify_urls_match(self.actor.inner(), self.object.object.inner())?;
69     self.object.verify(context, request_counter).await?;
70     Ok(())
71   }
72
73   #[tracing::instrument(skip_all)]
74   async fn receive(
75     self,
76     context: &Data<LemmyContext>,
77     request_counter: &mut i32,
78   ) -> Result<(), LemmyError> {
79     let person = self
80       .actor
81       .dereference(context, local_instance(context), request_counter)
82       .await?;
83     let community = self
84       .object
85       .actor
86       .dereference(context, local_instance(context), request_counter)
87       .await?;
88     // This will throw an error if no follow was requested
89     blocking(context.pool(), move |conn| {
90       CommunityFollower::follow_accepted(conn, person.id, community.id)
91     })
92     .await??;
93
94     Ok(())
95   }
96 }