6 verify_person_in_community,
8 fetcher::user_or_community::UserOrCommunity,
10 objects::{community::ApubCommunity, person::ApubPerson},
11 protocol::activities::following::{
14 undo_follow::UndoFollow,
18 use activitypub_federation::{
20 kinds::activity::FollowType,
21 protocol::verification::verify_urls_match,
22 traits::{ActivityHandler, Actor},
24 use lemmy_api_common::{
25 community::{BlockCommunity, BlockCommunityResponse},
26 context::LemmyContext,
27 utils::get_local_user_view_from_jwt,
29 use lemmy_db_schema::{
31 community::{Community, CommunityFollower, CommunityFollowerForm},
32 person::{PersonFollower, PersonFollowerForm},
34 traits::{Crud, Followable},
36 use lemmy_utils::error::LemmyError;
40 pub(in crate::activities::following) fn new(
42 community: &ApubCommunity,
43 context: &Data<LemmyContext>,
44 ) -> Result<Follow, LemmyError> {
46 actor: actor.id().into(),
47 object: community.id().into(),
48 to: Some([community.id().into()]),
49 kind: FollowType::Follow,
50 id: generate_activity_id(
52 &context.settings().get_protocol_and_hostname(),
57 #[tracing::instrument(skip_all)]
60 community: &ApubCommunity,
61 context: &Data<LemmyContext>,
62 ) -> Result<(), LemmyError> {
63 let community_follower_form = CommunityFollowerForm {
64 community_id: community.id,
68 CommunityFollower::follow(context.pool(), &community_follower_form)
72 let follow = Follow::new(actor, community, context)?;
73 let inbox = vec![community.shared_inbox_or_inbox()];
74 send_lemmy_activity(context, follow, actor, inbox, true).await
78 #[async_trait::async_trait]
79 impl ActivityHandler for Follow {
80 type DataType = LemmyContext;
81 type Error = LemmyError;
83 fn id(&self) -> &Url {
87 fn actor(&self) -> &Url {
91 #[tracing::instrument(skip_all)]
92 async fn verify(&self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
93 verify_person(&self.actor, context).await?;
94 let object = self.object.dereference(context).await?;
95 if let UserOrCommunity::Community(c) = object {
96 verify_person_in_community(&self.actor, &c, context).await?;
98 if let Some(to) = &self.to {
99 verify_urls_match(to[0].inner(), self.object.inner())?;
104 #[tracing::instrument(skip_all)]
105 async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
106 insert_activity(&self.id, &self, false, true, context).await?;
107 let actor = self.actor.dereference(context).await?;
108 let object = self.object.dereference(context).await?;
110 UserOrCommunity::User(u) => {
111 let form = PersonFollowerForm {
113 follower_id: actor.id,
116 PersonFollower::follow(context.pool(), &form).await?;
118 UserOrCommunity::Community(c) => {
119 let form = CommunityFollowerForm {
124 CommunityFollower::follow(context.pool(), &form).await?;
128 AcceptFollow::send(self, context).await
132 #[async_trait::async_trait]
133 impl SendActivity for BlockCommunity {
134 type Response = BlockCommunityResponse;
136 async fn send_activity(
138 _response: &Self::Response,
139 context: &Data<LemmyContext>,
140 ) -> Result<(), LemmyError> {
141 let local_user_view =
142 get_local_user_view_from_jwt(&request.auth, context.pool(), context.secret()).await?;
143 let community = Community::read(context.pool(), request.community_id).await?;
144 UndoFollow::send(&local_user_view.person.into(), &community.into(), context).await