]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/following/accept.rs
Split activity table into sent and received parts (fixes #3103) (#3583)
[lemmy.git] / crates / apub / src / activities / following / accept.rs
1 use crate::{
2   activities::{generate_activity_id, send_lemmy_activity},
3   insert_received_activity,
4   protocol::activities::following::{accept::AcceptFollow, follow::Follow},
5 };
6 use activitypub_federation::{
7   config::Data,
8   kinds::activity::AcceptType,
9   protocol::verification::verify_urls_match,
10   traits::{ActivityHandler, Actor},
11 };
12 use lemmy_api_common::context::LemmyContext;
13 use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
14 use lemmy_utils::error::LemmyError;
15 use url::Url;
16
17 impl AcceptFollow {
18   #[tracing::instrument(skip_all)]
19   pub async fn send(follow: Follow, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
20     let user_or_community = follow.object.dereference_local(context).await?;
21     let person = follow.actor.clone().dereference(context).await?;
22     let accept = AcceptFollow {
23       actor: user_or_community.id().into(),
24       to: Some([person.id().into()]),
25       object: follow,
26       kind: AcceptType::Accept,
27       id: generate_activity_id(
28         AcceptType::Accept,
29         &context.settings().get_protocol_and_hostname(),
30       )?,
31     };
32     let inbox = vec![person.shared_inbox_or_inbox()];
33     send_lemmy_activity(context, accept, &user_or_community, inbox, true).await
34   }
35 }
36
37 /// Handle accepted follows
38 #[async_trait::async_trait]
39 impl ActivityHandler for AcceptFollow {
40   type DataType = LemmyContext;
41   type Error = LemmyError;
42
43   fn id(&self) -> &Url {
44     &self.id
45   }
46
47   fn actor(&self) -> &Url {
48     self.actor.inner()
49   }
50
51   #[tracing::instrument(skip_all)]
52   async fn verify(&self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
53     insert_received_activity(&self.id, context).await?;
54     verify_urls_match(self.actor.inner(), self.object.object.inner())?;
55     self.object.verify(context).await?;
56     if let Some(to) = &self.to {
57       verify_urls_match(to[0].inner(), self.object.actor.inner())?;
58     }
59     Ok(())
60   }
61
62   #[tracing::instrument(skip_all)]
63   async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
64     let community = self.actor.dereference(context).await?;
65     let person = self.object.actor.dereference(context).await?;
66     // This will throw an error if no follow was requested
67     let community_id = community.id;
68     let person_id = person.id;
69     CommunityFollower::follow_accepted(&mut context.pool(), community_id, person_id).await?;
70
71     Ok(())
72   }
73 }