]> Untitled Git - lemmy.git/blob - crates/apub/src/http/community.rs
19793674c48389ae9b343ebe37d165096a98dc6f
[lemmy.git] / crates / apub / src / http / community.rs
1 use crate::{
2   activity_lists::GroupInboxActivities,
3   collections::{
4     community_featured::ApubCommunityFeatured,
5     community_moderators::ApubCommunityModerators,
6     community_outbox::ApubCommunityOutbox,
7   },
8   http::{create_apub_response, create_apub_tombstone_response},
9   objects::{community::ApubCommunity, person::ApubPerson},
10   protocol::collections::group_followers::GroupFollowers,
11 };
12 use activitypub_federation::{
13   actix_web::inbox::receive_activity,
14   config::Data,
15   protocol::context::WithContext,
16   traits::{Collection, Object},
17 };
18 use actix_web::{web, web::Bytes, HttpRequest, HttpResponse};
19 use lemmy_api_common::context::LemmyContext;
20 use lemmy_db_schema::{source::community::Community, traits::ApubActor};
21 use lemmy_utils::error::{LemmyError, LemmyErrorType};
22 use serde::Deserialize;
23
24 #[derive(Deserialize)]
25 pub(crate) struct CommunityQuery {
26   community_name: String,
27 }
28
29 /// Return the ActivityPub json representation of a local community over HTTP.
30 #[tracing::instrument(skip_all)]
31 pub(crate) async fn get_apub_community_http(
32   info: web::Path<CommunityQuery>,
33   context: Data<LemmyContext>,
34 ) -> Result<HttpResponse, LemmyError> {
35   let community: ApubCommunity =
36     Community::read_from_name(context.pool(), &info.community_name, true)
37       .await?
38       .into();
39
40   if !community.deleted && !community.removed {
41     let apub = community.into_json(&context).await?;
42
43     create_apub_response(&apub)
44   } else {
45     create_apub_tombstone_response(community.actor_id.clone())
46   }
47 }
48
49 /// Handler for all incoming receive to community inboxes.
50 #[tracing::instrument(skip_all)]
51 pub async fn community_inbox(
52   request: HttpRequest,
53   body: Bytes,
54   data: Data<LemmyContext>,
55 ) -> Result<HttpResponse, LemmyError> {
56   receive_activity::<WithContext<GroupInboxActivities>, ApubPerson, LemmyContext>(
57     request, body, &data,
58   )
59   .await
60 }
61
62 /// Returns an empty followers collection, only populating the size (for privacy).
63 pub(crate) async fn get_apub_community_followers(
64   info: web::Path<CommunityQuery>,
65   context: Data<LemmyContext>,
66 ) -> Result<HttpResponse, LemmyError> {
67   let community = Community::read_from_name(context.pool(), &info.community_name, false).await?;
68   let followers = GroupFollowers::new(community, &context).await?;
69   create_apub_response(&followers)
70 }
71
72 /// Returns the community outbox, which is populated by a maximum of 20 posts (but no other
73 /// activites like votes or comments).
74 pub(crate) async fn get_apub_community_outbox(
75   info: web::Path<CommunityQuery>,
76   context: Data<LemmyContext>,
77 ) -> Result<HttpResponse, LemmyError> {
78   let community: ApubCommunity =
79     Community::read_from_name(context.pool(), &info.community_name, false)
80       .await?
81       .into();
82   if community.deleted || community.removed {
83     return Err(LemmyErrorType::Deleted)?;
84   }
85   let outbox = ApubCommunityOutbox::read_local(&community, &context).await?;
86   create_apub_response(&outbox)
87 }
88
89 #[tracing::instrument(skip_all)]
90 pub(crate) async fn get_apub_community_moderators(
91   info: web::Path<CommunityQuery>,
92   context: Data<LemmyContext>,
93 ) -> Result<HttpResponse, LemmyError> {
94   let community: ApubCommunity =
95     Community::read_from_name(context.pool(), &info.community_name, false)
96       .await?
97       .into();
98   if community.deleted || community.removed {
99     return Err(LemmyErrorType::Deleted)?;
100   }
101   let moderators = ApubCommunityModerators::read_local(&community, &context).await?;
102   create_apub_response(&moderators)
103 }
104
105 /// Returns collection of featured (stickied) posts.
106 pub(crate) async fn get_apub_community_featured(
107   info: web::Path<CommunityQuery>,
108   context: Data<LemmyContext>,
109 ) -> Result<HttpResponse, LemmyError> {
110   let community: ApubCommunity =
111     Community::read_from_name(context.pool(), &info.community_name, false)
112       .await?
113       .into();
114   if community.deleted || community.removed {
115     return Err(LemmyErrorType::Deleted)?;
116   }
117   let featured = ApubCommunityFeatured::read_local(&community, &context).await?;
118   create_apub_response(&featured)
119 }