3 check_is_apub_id_valid,
4 extensions::signatures::verify,
5 fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_community},
11 use activitystreams::{
12 activity::{Accept, ActorAndObject, Create, Delete, Undo, Update},
17 use actix_web::{web, HttpRequest, HttpResponse};
21 user::PrivateMessageResponse,
22 websocket::{SendUserRoomMessage, UserOperation},
25 community::{CommunityFollower, CommunityFollowerForm},
27 private_message::{PrivateMessage, PrivateMessageForm},
28 private_message_view::PrivateMessageView,
33 use lemmy_utils::{location_info, LemmyError};
35 use serde::{Deserialize, Serialize};
38 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
39 #[serde(rename_all = "PascalCase")]
48 pub type AcceptedActivities = ActorAndObject<ValidTypes>;
50 /// Handler for all incoming activities to user inboxes.
51 pub async fn user_inbox(
53 input: web::Json<AcceptedActivities>,
54 path: web::Path<String>,
55 context: web::Data<LemmyContext>,
56 ) -> Result<HttpResponse, LemmyError> {
57 let activity = input.into_inner();
58 let username = path.into_inner();
59 debug!("User {} received activity: {:?}", &username, &activity);
61 let actor_uri = activity
63 .as_single_xsd_any_uri()
64 .context(location_info!())?;
66 check_is_apub_id_valid(actor_uri)?;
68 let actor = get_or_fetch_and_upsert_actor(actor_uri, &context).await?;
69 verify(&request, actor.as_ref())?;
71 let any_base = activity.clone().into_any_base()?;
72 let kind = activity.kind().context(location_info!())?;
73 let res = match kind {
74 ValidTypes::Accept => receive_accept(any_base, username, &context).await,
75 ValidTypes::Create => receive_create_private_message(any_base, &context).await,
76 ValidTypes::Update => receive_update_private_message(any_base, &context).await,
77 ValidTypes::Delete => receive_delete_private_message(any_base, &context).await,
78 ValidTypes::Undo => receive_undo_delete_private_message(any_base, &context).await,
81 insert_activity(actor.user_id(), activity.clone(), false, context.pool()).await?;
85 /// Handle accepted follows.
86 async fn receive_accept(
89 context: &LemmyContext,
90 ) -> Result<HttpResponse, LemmyError> {
91 let accept = Accept::from_any_base(activity)?.context(location_info!())?;
92 let community_uri = accept
96 .context(location_info!())?;
98 let community = get_or_fetch_and_upsert_community(&community_uri, context).await?;
100 let user = blocking(&context.pool(), move |conn| {
101 User_::read_from_name(conn, &username)
105 // Now you need to add this to the community follower
106 let community_follower_form = CommunityFollowerForm {
107 community_id: community.id,
111 // This will fail if they're already a follower
112 blocking(&context.pool(), move |conn| {
113 CommunityFollower::follow(conn, &community_follower_form).ok()
117 // TODO: make sure that we actually requested a follow
118 Ok(HttpResponse::Ok().finish())
121 async fn receive_create_private_message(
123 context: &LemmyContext,
124 ) -> Result<HttpResponse, LemmyError> {
125 let create = Create::from_any_base(activity)?.context(location_info!())?;
126 let note = Note::from_any_base(
130 .context(location_info!())?
133 .context(location_info!())?;
135 let domain = Some(create.id_unchecked().context(location_info!())?.to_owned());
136 let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?;
138 let inserted_private_message = blocking(&context.pool(), move |conn| {
139 PrivateMessage::create(conn, &private_message)
143 let message = blocking(&context.pool(), move |conn| {
144 PrivateMessageView::read(conn, inserted_private_message.id)
148 let res = PrivateMessageResponse { message };
150 let recipient_id = res.message.recipient_id;
152 context.chat_server().do_send(SendUserRoomMessage {
153 op: UserOperation::CreatePrivateMessage,
159 Ok(HttpResponse::Ok().finish())
162 async fn receive_update_private_message(
164 context: &LemmyContext,
165 ) -> Result<HttpResponse, LemmyError> {
166 let update = Update::from_any_base(activity)?.context(location_info!())?;
167 let note = Note::from_any_base(
171 .context(location_info!())?
174 .context(location_info!())?;
176 let domain = Some(update.id_unchecked().context(location_info!())?.to_owned());
177 let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?;
179 let private_message_ap_id = private_message_form
182 .context(location_info!())?
184 let private_message = blocking(&context.pool(), move |conn| {
185 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id)
189 let private_message_id = private_message.id;
190 blocking(&context.pool(), move |conn| {
191 PrivateMessage::update(conn, private_message_id, &private_message_form)
195 let private_message_id = private_message.id;
196 let message = blocking(&context.pool(), move |conn| {
197 PrivateMessageView::read(conn, private_message_id)
201 let res = PrivateMessageResponse { message };
203 let recipient_id = res.message.recipient_id;
205 context.chat_server().do_send(SendUserRoomMessage {
206 op: UserOperation::EditPrivateMessage,
212 Ok(HttpResponse::Ok().finish())
215 async fn receive_delete_private_message(
217 context: &LemmyContext,
218 ) -> Result<HttpResponse, LemmyError> {
219 let delete = Delete::from_any_base(activity)?.context(location_info!())?;
220 let note = Note::from_any_base(
224 .context(location_info!())?
227 .context(location_info!())?;
229 let domain = Some(delete.id_unchecked().context(location_info!())?.to_owned());
230 let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?;
232 let private_message_ap_id = private_message_form.ap_id.context(location_info!())?;
233 let private_message = blocking(&context.pool(), move |conn| {
234 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id)
238 let private_message_form = PrivateMessageForm {
239 content: private_message_form.content,
240 recipient_id: private_message.recipient_id,
241 creator_id: private_message.creator_id,
244 ap_id: Some(private_message.ap_id),
245 local: private_message.local,
247 updated: Some(naive_now()),
250 let private_message_id = private_message.id;
251 blocking(&context.pool(), move |conn| {
252 PrivateMessage::update(conn, private_message_id, &private_message_form)
256 let private_message_id = private_message.id;
257 let message = blocking(&context.pool(), move |conn| {
258 PrivateMessageView::read(&conn, private_message_id)
262 let res = PrivateMessageResponse { message };
264 let recipient_id = res.message.recipient_id;
266 context.chat_server().do_send(SendUserRoomMessage {
267 op: UserOperation::EditPrivateMessage,
273 Ok(HttpResponse::Ok().finish())
276 async fn receive_undo_delete_private_message(
278 context: &LemmyContext,
279 ) -> Result<HttpResponse, LemmyError> {
280 let undo = Undo::from_any_base(activity)?.context(location_info!())?;
281 let delete = Delete::from_any_base(undo.object().as_one().context(location_info!())?.to_owned())?
282 .context(location_info!())?;
283 let note = Note::from_any_base(
287 .context(location_info!())?
290 .context(location_info!())?;
292 let domain = Some(undo.id_unchecked().context(location_info!())?.to_owned());
293 let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?;
295 let private_message_ap_id = private_message
298 .context(location_info!())?
300 let private_message_id = blocking(&context.pool(), move |conn| {
301 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id).map(|pm| pm.id)
305 let private_message_form = PrivateMessageForm {
306 content: private_message.content,
307 recipient_id: private_message.recipient_id,
308 creator_id: private_message.creator_id,
309 deleted: Some(false),
311 ap_id: private_message.ap_id,
312 local: private_message.local,
314 updated: Some(naive_now()),
317 blocking(&context.pool(), move |conn| {
318 PrivateMessage::update(conn, private_message_id, &private_message_form)
322 let message = blocking(&context.pool(), move |conn| {
323 PrivateMessageView::read(&conn, private_message_id)
327 let res = PrivateMessageResponse { message };
329 let recipient_id = res.message.recipient_id;
331 context.chat_server().do_send(SendUserRoomMessage {
332 op: UserOperation::EditPrivateMessage,
338 Ok(HttpResponse::Ok().finish())