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