3 check_is_apub_id_valid,
4 extensions::signatures::verify,
5 fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_community},
9 websocket::{messages::SendUserRoomMessage, UserOperation},
12 use activitystreams::{
13 activity::{Accept, ActorAndObject, Create, Delete, Undo, Update},
18 use actix_web::{web, HttpRequest, HttpResponse};
20 use lemmy_api_structs::{blocking, user::PrivateMessageResponse};
22 community::{CommunityFollower, CommunityFollowerForm},
24 private_message::{PrivateMessage, PrivateMessageForm},
25 private_message_view::PrivateMessageView,
30 use lemmy_utils::{location_info, LemmyError};
32 use serde::{Deserialize, Serialize};
35 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
36 #[serde(rename_all = "PascalCase")]
45 pub type AcceptedActivities = ActorAndObject<ValidTypes>;
47 /// Handler for all incoming activities to user inboxes.
48 pub async fn user_inbox(
50 input: web::Json<AcceptedActivities>,
51 path: web::Path<String>,
52 context: web::Data<LemmyContext>,
53 ) -> Result<HttpResponse, LemmyError> {
54 let activity = input.into_inner();
55 let username = path.into_inner();
56 debug!("User {} received activity: {:?}", &username, &activity);
58 let actor_uri = activity
60 .as_single_xsd_any_uri()
61 .context(location_info!())?;
63 check_is_apub_id_valid(actor_uri)?;
65 let actor = get_or_fetch_and_upsert_actor(actor_uri, &context).await?;
66 verify(&request, actor.as_ref())?;
68 let any_base = activity.clone().into_any_base()?;
69 let kind = activity.kind().context(location_info!())?;
70 let res = match kind {
71 ValidTypes::Accept => receive_accept(any_base, username, &context).await,
72 ValidTypes::Create => receive_create_private_message(any_base, &context).await,
73 ValidTypes::Update => receive_update_private_message(any_base, &context).await,
74 ValidTypes::Delete => receive_delete_private_message(any_base, &context).await,
75 ValidTypes::Undo => receive_undo_delete_private_message(any_base, &context).await,
78 insert_activity(actor.user_id(), activity.clone(), false, context.pool()).await?;
82 /// Handle accepted follows.
83 async fn receive_accept(
86 context: &LemmyContext,
87 ) -> Result<HttpResponse, LemmyError> {
88 let accept = Accept::from_any_base(activity)?.context(location_info!())?;
89 let community_uri = accept
93 .context(location_info!())?;
95 let community = get_or_fetch_and_upsert_community(&community_uri, context).await?;
97 let user = blocking(&context.pool(), move |conn| {
98 User_::read_from_name(conn, &username)
102 // Now you need to add this to the community follower
103 let community_follower_form = CommunityFollowerForm {
104 community_id: community.id,
108 // This will fail if they're already a follower
109 blocking(&context.pool(), move |conn| {
110 CommunityFollower::follow(conn, &community_follower_form).ok()
114 // TODO: make sure that we actually requested a follow
115 Ok(HttpResponse::Ok().finish())
118 async fn receive_create_private_message(
120 context: &LemmyContext,
121 ) -> Result<HttpResponse, LemmyError> {
122 let create = Create::from_any_base(activity)?.context(location_info!())?;
123 let note = Note::from_any_base(
127 .context(location_info!())?
130 .context(location_info!())?;
132 let domain = Some(create.id_unchecked().context(location_info!())?.to_owned());
133 let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?;
135 let inserted_private_message = blocking(&context.pool(), move |conn| {
136 PrivateMessage::create(conn, &private_message)
140 let message = blocking(&context.pool(), move |conn| {
141 PrivateMessageView::read(conn, inserted_private_message.id)
145 let res = PrivateMessageResponse { message };
147 let recipient_id = res.message.recipient_id;
149 context.chat_server().do_send(SendUserRoomMessage {
150 op: UserOperation::CreatePrivateMessage,
156 Ok(HttpResponse::Ok().finish())
159 async fn receive_update_private_message(
161 context: &LemmyContext,
162 ) -> Result<HttpResponse, LemmyError> {
163 let update = Update::from_any_base(activity)?.context(location_info!())?;
164 let note = Note::from_any_base(
168 .context(location_info!())?
171 .context(location_info!())?;
173 let domain = Some(update.id_unchecked().context(location_info!())?.to_owned());
174 let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?;
176 let private_message_ap_id = private_message_form
179 .context(location_info!())?
181 let private_message = blocking(&context.pool(), move |conn| {
182 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id)
186 let private_message_id = private_message.id;
187 blocking(&context.pool(), move |conn| {
188 PrivateMessage::update(conn, private_message_id, &private_message_form)
192 let private_message_id = private_message.id;
193 let message = blocking(&context.pool(), move |conn| {
194 PrivateMessageView::read(conn, private_message_id)
198 let res = PrivateMessageResponse { message };
200 let recipient_id = res.message.recipient_id;
202 context.chat_server().do_send(SendUserRoomMessage {
203 op: UserOperation::EditPrivateMessage,
209 Ok(HttpResponse::Ok().finish())
212 async fn receive_delete_private_message(
214 context: &LemmyContext,
215 ) -> Result<HttpResponse, LemmyError> {
216 let delete = Delete::from_any_base(activity)?.context(location_info!())?;
217 let note = Note::from_any_base(
221 .context(location_info!())?
224 .context(location_info!())?;
226 let domain = Some(delete.id_unchecked().context(location_info!())?.to_owned());
227 let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?;
229 let private_message_ap_id = private_message_form.ap_id.context(location_info!())?;
230 let private_message = blocking(&context.pool(), move |conn| {
231 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id)
235 let private_message_form = PrivateMessageForm {
236 content: private_message_form.content,
237 recipient_id: private_message.recipient_id,
238 creator_id: private_message.creator_id,
241 ap_id: Some(private_message.ap_id),
242 local: private_message.local,
244 updated: Some(naive_now()),
247 let private_message_id = private_message.id;
248 blocking(&context.pool(), move |conn| {
249 PrivateMessage::update(conn, private_message_id, &private_message_form)
253 let private_message_id = private_message.id;
254 let message = blocking(&context.pool(), move |conn| {
255 PrivateMessageView::read(&conn, private_message_id)
259 let res = PrivateMessageResponse { message };
261 let recipient_id = res.message.recipient_id;
263 context.chat_server().do_send(SendUserRoomMessage {
264 op: UserOperation::EditPrivateMessage,
270 Ok(HttpResponse::Ok().finish())
273 async fn receive_undo_delete_private_message(
275 context: &LemmyContext,
276 ) -> Result<HttpResponse, LemmyError> {
277 let undo = Undo::from_any_base(activity)?.context(location_info!())?;
278 let delete = Delete::from_any_base(undo.object().as_one().context(location_info!())?.to_owned())?
279 .context(location_info!())?;
280 let note = Note::from_any_base(
284 .context(location_info!())?
287 .context(location_info!())?;
289 let domain = Some(undo.id_unchecked().context(location_info!())?.to_owned());
290 let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?;
292 let private_message_ap_id = private_message
295 .context(location_info!())?
297 let private_message_id = blocking(&context.pool(), move |conn| {
298 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id).map(|pm| pm.id)
302 let private_message_form = PrivateMessageForm {
303 content: private_message.content,
304 recipient_id: private_message.recipient_id,
305 creator_id: private_message.creator_id,
306 deleted: Some(false),
308 ap_id: private_message.ap_id,
309 local: private_message.local,
311 updated: Some(naive_now()),
314 blocking(&context.pool(), move |conn| {
315 PrivateMessage::update(conn, private_message_id, &private_message_form)
319 let message = blocking(&context.pool(), move |conn| {
320 PrivateMessageView::read(&conn, private_message_id)
324 let res = PrivateMessageResponse { message };
326 let recipient_id = res.message.recipient_id;
328 context.chat_server().do_send(SendUserRoomMessage {
329 op: UserOperation::EditPrivateMessage,
335 Ok(HttpResponse::Ok().finish())