2 use actix_web::web::Data;
3 use lemmy_api_common::{
4 community::{FollowCommunity, FollowCommunityResponse},
8 check_community_deleted_or_removed,
9 get_local_user_view_from_jwt,
13 objects::community::ApubCommunity,
14 protocol::activities::following::{
15 follow::FollowCommunity as FollowCommunityApub,
16 undo_follow::UndoFollowCommunity,
19 use lemmy_db_schema::{
20 source::community::{Community, CommunityFollower, CommunityFollowerForm},
21 traits::{Crud, Followable},
23 use lemmy_db_views_actor::structs::CommunityFollowerView;
24 use lemmy_utils::{ConnectionId, LemmyError};
25 use lemmy_websocket::LemmyContext;
27 #[async_trait::async_trait(?Send)]
28 impl Perform for FollowCommunity {
29 type Response = FollowCommunityResponse;
31 #[tracing::instrument(skip(context, _websocket_id))]
34 context: &Data<LemmyContext>,
35 _websocket_id: Option<ConnectionId>,
36 ) -> Result<Self::Response, LemmyError> {
37 let data: &FollowCommunity = self;
39 get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
41 let community_id = data.community_id;
42 let community: ApubCommunity = blocking(context.pool(), move |conn| {
43 Community::read(conn, community_id)
47 let community_follower_form = CommunityFollowerForm {
48 community_id: data.community_id,
49 person_id: local_user_view.person.id,
50 pending: false, // Don't worry, this form isn't used for remote follows
55 check_community_ban(local_user_view.person.id, community_id, context.pool()).await?;
56 check_community_deleted_or_removed(community_id, context.pool()).await?;
58 let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
59 blocking(context.pool(), follow)
61 .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
64 move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
65 blocking(context.pool(), unfollow)
67 .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
69 } else if data.follow {
70 // Dont actually add to the community followers here, because you need
71 // to wait for the accept
72 FollowCommunityApub::send(&local_user_view.person.clone().into(), &community, context)
75 UndoFollowCommunity::send(&local_user_view.person.clone().into(), &community, context)
77 let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
78 blocking(context.pool(), unfollow)
80 .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
83 let community_id = data.community_id;
84 let person_id = local_user_view.person.id;
85 let community_follower_view = blocking(context.pool(), move |conn| {
86 CommunityFollowerView::read(conn, community_id, person_id)
92 community_follower_view,