2 use actix_web::web::Data;
3 use lemmy_api_common::{
4 community::{CommunityResponse, FollowCommunity},
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::CommunityView;
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 = CommunityResponse;
31 #[tracing::instrument(skip(context, _websocket_id))]
34 context: &Data<LemmyContext>,
35 _websocket_id: Option<ConnectionId>,
36 ) -> Result<CommunityResponse, 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,
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 mut community_view = blocking(context.pool(), move |conn| {
86 CommunityView::read(conn, community_id, Some(person_id))
90 // TODO: this needs to return a "pending" state, until Accept is received from the remote server
91 // For now, just assume that remote follows are accepted.
92 // Otherwise, the subscribed will be null
94 community_view.subscribed = data.follow;
97 Ok(CommunityResponse { community_view })