2 activity_lists::GroupInboxActivities,
4 community_featured::ApubCommunityFeatured,
5 community_moderators::ApubCommunityModerators,
6 community_outbox::ApubCommunityOutbox,
8 http::{create_apub_response, create_apub_tombstone_response},
9 objects::{community::ApubCommunity, person::ApubPerson},
10 protocol::collections::group_followers::GroupFollowers,
12 use activitypub_federation::{
13 actix_web::inbox::receive_activity,
15 protocol::context::WithContext,
16 traits::{Collection, Object},
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;
22 use serde::Deserialize;
24 #[derive(Deserialize)]
25 pub(crate) struct CommunityQuery {
26 community_name: String,
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)
40 if !community.deleted && !community.removed {
41 let apub = community.into_json(&context).await?;
43 Ok(create_apub_response(&apub))
45 Ok(create_apub_tombstone_response(community.actor_id.clone()))
49 /// Handler for all incoming receive to community inboxes.
50 #[tracing::instrument(skip_all)]
51 pub async fn community_inbox(
54 data: Data<LemmyContext>,
55 ) -> Result<HttpResponse, LemmyError> {
56 receive_activity::<WithContext<GroupInboxActivities>, ApubPerson, LemmyContext>(
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 Ok(create_apub_response(&followers))
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)
82 if community.deleted || community.removed {
83 return Err(LemmyError::from_message("deleted"));
85 let outbox = ApubCommunityOutbox::read_local(&community, &context).await?;
86 Ok(create_apub_response(&outbox))
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)
98 if community.deleted || community.removed {
99 return Err(LemmyError::from_message("deleted"));
101 let moderators = ApubCommunityModerators::read_local(&community, &context).await?;
102 Ok(create_apub_response(&moderators))
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)
114 if community.deleted || community.removed {
115 return Err(LemmyError::from_message("deleted"));
117 let featured = ApubCommunityFeatured::read_local(&community, &context).await?;
118 Ok(create_apub_response(&featured))