2 use actix_web::web::Data;
3 use lemmy_api_common::{
6 check_community_deleted_or_removed,
7 community::{CommunityResponse, FollowCommunity},
8 get_local_user_view_from_jwt,
11 objects::community::ApubCommunity,
12 protocol::activities::following::{
13 follow::FollowCommunity as FollowCommunityApub,
14 undo_follow::UndoFollowCommunity,
17 use lemmy_db_schema::{
18 source::community::{Community, CommunityFollower, CommunityFollowerForm},
19 traits::{Crud, Followable},
21 use lemmy_db_views_actor::community_view::CommunityView;
22 use lemmy_utils::{ConnectionId, LemmyError};
23 use lemmy_websocket::LemmyContext;
25 #[async_trait::async_trait(?Send)]
26 impl Perform for FollowCommunity {
27 type Response = CommunityResponse;
29 #[tracing::instrument(skip(context, _websocket_id))]
32 context: &Data<LemmyContext>,
33 _websocket_id: Option<ConnectionId>,
34 ) -> Result<CommunityResponse, LemmyError> {
35 let data: &FollowCommunity = self;
37 get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
39 let community_id = data.community_id;
40 let community: ApubCommunity = blocking(context.pool(), move |conn| {
41 Community::read(conn, community_id)
45 let community_follower_form = CommunityFollowerForm {
46 community_id: data.community_id,
47 person_id: local_user_view.person.id,
53 check_community_ban(local_user_view.person.id, community_id, context.pool()).await?;
54 check_community_deleted_or_removed(community_id, context.pool()).await?;
56 let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
57 blocking(context.pool(), follow)
59 .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
62 move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
63 blocking(context.pool(), unfollow)
65 .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
67 } else if data.follow {
68 // Dont actually add to the community followers here, because you need
69 // to wait for the accept
70 FollowCommunityApub::send(&local_user_view.person.clone().into(), &community, context)
73 UndoFollowCommunity::send(&local_user_view.person.clone().into(), &community, context)
75 let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
76 blocking(context.pool(), unfollow)
78 .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
81 let community_id = data.community_id;
82 let person_id = local_user_view.person.id;
83 let mut community_view = blocking(context.pool(), move |conn| {
84 CommunityView::read(conn, community_id, Some(person_id))
88 // TODO: this needs to return a "pending" state, until Accept is received from the remote server
89 // For now, just assume that remote follows are accepted.
90 // Otherwise, the subscribed will be null
92 community_view.subscribed = data.follow;
95 Ok(CommunityResponse { community_view })