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 traits::{ActivityHandler, Actor},
23 use lemmy_api_common::{
24 community::{BlockCommunity, BlockCommunityResponse},
25 context::LemmyContext,
26 utils::get_local_user_view_from_jwt,
28 use lemmy_db_schema::{
30 community::{Community, CommunityFollower, CommunityFollowerForm},
31 person::{PersonFollower, PersonFollowerForm},
33 traits::{Crud, Followable},
35 use lemmy_utils::error::LemmyError;
39 pub(in crate::activities::following) fn new(
41 community: &ApubCommunity,
42 context: &Data<LemmyContext>,
43 ) -> Result<Follow, LemmyError> {
45 actor: actor.id().into(),
46 object: community.id().into(),
47 kind: FollowType::Follow,
48 id: generate_activity_id(
50 &context.settings().get_protocol_and_hostname(),
55 #[tracing::instrument(skip_all)]
58 community: &ApubCommunity,
59 context: &Data<LemmyContext>,
60 ) -> Result<(), LemmyError> {
61 let community_follower_form = CommunityFollowerForm {
62 community_id: community.id,
66 CommunityFollower::follow(context.pool(), &community_follower_form)
70 let follow = Follow::new(actor, community, context)?;
71 let inbox = vec![community.shared_inbox_or_inbox()];
72 send_lemmy_activity(context, follow, actor, inbox, true).await
76 #[async_trait::async_trait]
77 impl ActivityHandler for Follow {
78 type DataType = LemmyContext;
79 type Error = LemmyError;
81 fn id(&self) -> &Url {
85 fn actor(&self) -> &Url {
89 #[tracing::instrument(skip_all)]
90 async fn verify(&self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
91 verify_person(&self.actor, context).await?;
92 let object = self.object.dereference(context).await?;
93 if let UserOrCommunity::Community(c) = object {
94 verify_person_in_community(&self.actor, &c, context).await?;
99 #[tracing::instrument(skip_all)]
100 async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
101 insert_activity(&self.id, &self, false, true, context).await?;
102 let actor = self.actor.dereference(context).await?;
103 let object = self.object.dereference(context).await?;
105 UserOrCommunity::User(u) => {
106 let form = PersonFollowerForm {
108 follower_id: actor.id,
111 PersonFollower::follow(context.pool(), &form).await?;
113 UserOrCommunity::Community(c) => {
114 let form = CommunityFollowerForm {
119 CommunityFollower::follow(context.pool(), &form).await?;
123 AcceptFollow::send(self, context).await
127 #[async_trait::async_trait]
128 impl SendActivity for BlockCommunity {
129 type Response = BlockCommunityResponse;
131 async fn send_activity(
133 _response: &Self::Response,
134 context: &Data<LemmyContext>,
135 ) -> Result<(), LemmyError> {
136 let local_user_view =
137 get_local_user_view_from_jwt(&request.auth, context.pool(), context.secret()).await?;
138 let community = Community::read(context.pool(), request.community_id).await?;
139 UndoFollow::send(&local_user_view.person.into(), &community.into(), context).await