]> Untitled Git - lemmy.git/blob - crates/api_crud/src/private_message/create.rs
Extract Activitypub logic into separate library (#2288)
[lemmy.git] / crates / api_crud / src / private_message / create.rs
1 use crate::PerformCrud;
2 use actix_web::web::Data;
3 use lemmy_api_common::{
4   person::{CreatePrivateMessage, PrivateMessageResponse},
5   utils::{
6     blocking,
7     check_person_block,
8     get_local_user_view_from_jwt,
9     get_user_lang,
10     send_email_to_user,
11   },
12 };
13 use lemmy_apub::{
14   generate_local_apub_endpoint,
15   protocol::activities::{
16     create_or_update::private_message::CreateOrUpdatePrivateMessage,
17     CreateOrUpdateType,
18   },
19   EndpointType,
20 };
21 use lemmy_db_schema::{
22   source::private_message::{PrivateMessage, PrivateMessageForm},
23   traits::Crud,
24 };
25 use lemmy_db_views::structs::LocalUserView;
26 use lemmy_utils::{error::LemmyError, utils::remove_slurs, ConnectionId};
27 use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
28
29 #[async_trait::async_trait(?Send)]
30 impl PerformCrud for CreatePrivateMessage {
31   type Response = PrivateMessageResponse;
32
33   #[tracing::instrument(skip(self, context, websocket_id))]
34   async fn perform(
35     &self,
36     context: &Data<LemmyContext>,
37     websocket_id: Option<ConnectionId>,
38   ) -> Result<PrivateMessageResponse, LemmyError> {
39     let data: &CreatePrivateMessage = self;
40     let local_user_view =
41       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
42
43     let content_slurs_removed =
44       remove_slurs(&data.content.to_owned(), &context.settings().slur_regex());
45
46     check_person_block(local_user_view.person.id, data.recipient_id, context.pool()).await?;
47
48     let private_message_form = PrivateMessageForm {
49       content: content_slurs_removed.to_owned(),
50       creator_id: local_user_view.person.id,
51       recipient_id: data.recipient_id,
52       ..PrivateMessageForm::default()
53     };
54
55     let inserted_private_message = match blocking(context.pool(), move |conn| {
56       PrivateMessage::create(conn, &private_message_form)
57     })
58     .await?
59     {
60       Ok(private_message) => private_message,
61       Err(e) => {
62         return Err(LemmyError::from_error_message(
63           e,
64           "couldnt_create_private_message",
65         ));
66       }
67     };
68
69     let inserted_private_message_id = inserted_private_message.id;
70     let protocol_and_hostname = context.settings().get_protocol_and_hostname();
71     let updated_private_message = blocking(
72       context.pool(),
73       move |conn| -> Result<PrivateMessage, LemmyError> {
74         let apub_id = generate_local_apub_endpoint(
75           EndpointType::PrivateMessage,
76           &inserted_private_message_id.to_string(),
77           &protocol_and_hostname,
78         )?;
79         Ok(PrivateMessage::update_ap_id(
80           conn,
81           inserted_private_message_id,
82           apub_id,
83         )?)
84       },
85     )
86     .await?
87     .map_err(|e| e.with_message("couldnt_create_private_message"))?;
88
89     CreateOrUpdatePrivateMessage::send(
90       updated_private_message.into(),
91       &local_user_view.person.into(),
92       CreateOrUpdateType::Create,
93       context,
94     )
95     .await?;
96
97     let res = send_pm_ws_message(
98       inserted_private_message.id,
99       UserOperationCrud::CreatePrivateMessage,
100       websocket_id,
101       context,
102     )
103     .await?;
104
105     // Send email to the local recipient, if one exists
106     if res.private_message_view.recipient.local {
107       let recipient_id = data.recipient_id;
108       let local_recipient = blocking(context.pool(), move |conn| {
109         LocalUserView::read_person(conn, recipient_id)
110       })
111       .await??;
112       let lang = get_user_lang(&local_recipient);
113       let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
114       send_email_to_user(
115         &local_recipient,
116         &lang.notification_private_message_subject(&local_recipient.person.name),
117         &lang.notification_private_message_body(
118           &inbox_link,
119           &content_slurs_removed,
120           &local_recipient.person.name,
121         ),
122         &context.settings(),
123       );
124     }
125
126     Ok(res)
127   }
128 }