6 verify_person_in_community,
8 fetcher::user_or_community::UserOrCommunity,
9 insert_received_activity,
10 objects::{community::ApubCommunity, person::ApubPerson},
11 protocol::activities::following::{accept::AcceptFollow, follow::Follow},
13 use activitypub_federation::{
15 kinds::activity::FollowType,
16 protocol::verification::verify_urls_match,
17 traits::{ActivityHandler, Actor},
19 use lemmy_api_common::context::LemmyContext;
20 use lemmy_db_schema::{
22 community::{CommunityFollower, CommunityFollowerForm},
23 person::{PersonFollower, PersonFollowerForm},
27 use lemmy_utils::error::LemmyError;
31 pub(in crate::activities::following) fn new(
33 community: &ApubCommunity,
34 context: &Data<LemmyContext>,
35 ) -> Result<Follow, LemmyError> {
37 actor: actor.id().into(),
38 object: community.id().into(),
39 to: Some([community.id().into()]),
40 kind: FollowType::Follow,
41 id: generate_activity_id(
43 &context.settings().get_protocol_and_hostname(),
48 #[tracing::instrument(skip_all)]
51 community: &ApubCommunity,
52 context: &Data<LemmyContext>,
53 ) -> Result<(), LemmyError> {
54 let community_follower_form = CommunityFollowerForm {
55 community_id: community.id,
59 CommunityFollower::follow(&mut context.pool(), &community_follower_form)
63 let follow = Follow::new(actor, community, context)?;
64 let inbox = vec![community.shared_inbox_or_inbox()];
65 send_lemmy_activity(context, follow, actor, inbox, true).await
69 #[async_trait::async_trait]
70 impl ActivityHandler for Follow {
71 type DataType = LemmyContext;
72 type Error = LemmyError;
74 fn id(&self) -> &Url {
78 fn actor(&self) -> &Url {
82 #[tracing::instrument(skip_all)]
83 async fn verify(&self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
84 insert_received_activity(&self.id, context).await?;
85 verify_person(&self.actor, context).await?;
86 let object = self.object.dereference(context).await?;
87 if let UserOrCommunity::Community(c) = object {
88 verify_person_in_community(&self.actor, &c, context).await?;
90 if let Some(to) = &self.to {
91 verify_urls_match(to[0].inner(), self.object.inner())?;
96 #[tracing::instrument(skip_all)]
97 async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
98 let actor = self.actor.dereference(context).await?;
99 let object = self.object.dereference(context).await?;
101 UserOrCommunity::User(u) => {
102 let form = PersonFollowerForm {
104 follower_id: actor.id,
107 PersonFollower::follow(&mut context.pool(), &form).await?;
109 UserOrCommunity::Community(c) => {
110 let form = CommunityFollowerForm {
115 CommunityFollower::follow(&mut context.pool(), &form).await?;
119 AcceptFollow::send(self, context).await