3 community::announce::{AnnouncableActivities, AnnounceActivity},
4 following::accept::AcceptFollowCommunity,
6 create_or_update::CreateOrUpdatePrivateMessage,
7 delete::DeletePrivateMessage,
8 undo_delete::UndoDeletePrivateMessage,
11 context::lemmy_context,
15 create_apub_tombstone_response,
19 objects::person::ApubPerson,
21 use activitystreams::{
23 collection::{CollectionExt, OrderedCollection},
25 use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
26 use lemmy_api_common::blocking;
27 use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ToApub};
28 use lemmy_db_schema::source::person::Person;
29 use lemmy_utils::LemmyError;
30 use lemmy_websocket::LemmyContext;
32 use serde::{Deserialize, Serialize};
35 #[derive(Deserialize)]
36 pub struct PersonQuery {
40 /// Return the ActivityPub json representation of a local person over HTTP.
41 pub(crate) async fn get_apub_person_http(
42 info: web::Path<PersonQuery>,
43 context: web::Data<LemmyContext>,
44 ) -> Result<HttpResponse<Body>, LemmyError> {
45 let user_name = info.into_inner().user_name;
46 // TODO: this needs to be able to read deleted persons, so that it can send tombstones
47 let person: ApubPerson = blocking(context.pool(), move |conn| {
48 Person::find_by_name(conn, &user_name)
54 let apub = person.to_apub(context.pool()).await?;
56 Ok(create_apub_response(&apub))
58 Ok(create_apub_tombstone_response(&person.to_tombstone()?))
62 #[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
64 #[activity_handler(LemmyContext)]
65 pub enum PersonInboxActivities {
66 AcceptFollowCommunity(AcceptFollowCommunity),
67 /// Some activities can also be sent from user to user, eg a comment with mentions
68 AnnouncableActivities(AnnouncableActivities),
69 CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage),
70 DeletePrivateMessage(DeletePrivateMessage),
71 UndoDeletePrivateMessage(UndoDeletePrivateMessage),
72 AnnounceActivity(Box<AnnounceActivity>),
75 pub async fn person_inbox(
78 _path: web::Path<String>,
79 context: web::Data<LemmyContext>,
80 ) -> Result<HttpResponse, LemmyError> {
81 let unparsed = payload_to_string(payload).await?;
82 trace!("Received person inbox activity {}", unparsed);
83 let activity = serde_json::from_str::<PersonInboxActivities>(&unparsed)?;
84 receive_person_inbox(activity, request, &context).await
87 pub(in crate::http) async fn receive_person_inbox(
88 activity: PersonInboxActivities,
90 context: &LemmyContext,
91 ) -> Result<HttpResponse, LemmyError> {
92 receive_activity(request, activity, context).await
95 pub(crate) async fn get_apub_person_outbox(
96 info: web::Path<PersonQuery>,
97 context: web::Data<LemmyContext>,
98 ) -> Result<HttpResponse<Body>, LemmyError> {
99 let person = blocking(context.pool(), move |conn| {
100 Person::find_by_name(conn, &info.user_name)
103 // TODO: populate the person outbox
104 let mut collection = OrderedCollection::new();
106 .set_many_items(Vec::<Url>::new())
107 .set_many_contexts(lemmy_context())
108 .set_id(generate_outbox_url(&person.actor_id)?.into())
109 .set_total_items(0_u64);
110 Ok(create_apub_response(&collection))
113 pub(crate) async fn get_apub_person_inbox(
114 info: web::Path<PersonQuery>,
115 context: web::Data<LemmyContext>,
116 ) -> Result<HttpResponse<Body>, LemmyError> {
117 let person = blocking(context.pool(), move |conn| {
118 Person::find_by_name(conn, &info.user_name)
122 let mut collection = OrderedCollection::new();
124 .set_id(person.inbox_url.into())
125 .set_many_contexts(lemmy_context());
126 Ok(create_apub_response(&collection))