]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/create_or_update/private_message.rs
20310bc4114a089a3b0c37be3a1de3aedf7113de
[lemmy.git] / crates / apub / src / activities / create_or_update / private_message.rs
1 use crate::{
2   activities::{generate_activity_id, send_lemmy_activity, verify_person},
3   check_apub_id_valid,
4   fetch_local_site_data,
5   objects::{person::ApubPerson, private_message::ApubPrivateMessage},
6   protocol::activities::{
7     create_or_update::private_message::CreateOrUpdatePrivateMessage,
8     CreateOrUpdateType,
9   },
10   ActorType,
11 };
12 use activitypub_federation::{
13   core::object_id::ObjectId,
14   data::Data,
15   traits::{ActivityHandler, Actor, ApubObject},
16   utils::verify_domains_match,
17 };
18 use lemmy_api_common::utils::blocking;
19 use lemmy_db_schema::{source::person::Person, traits::Crud};
20 use lemmy_utils::error::LemmyError;
21 use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
22 use url::Url;
23
24 impl CreateOrUpdatePrivateMessage {
25   #[tracing::instrument(skip_all)]
26   pub async fn send(
27     private_message: ApubPrivateMessage,
28     actor: &ApubPerson,
29     kind: CreateOrUpdateType,
30     context: &LemmyContext,
31   ) -> Result<(), LemmyError> {
32     let recipient_id = private_message.recipient_id;
33     let recipient: ApubPerson =
34       blocking(context.pool(), move |conn| Person::read(conn, recipient_id))
35         .await??
36         .into();
37
38     let id = generate_activity_id(
39       kind.clone(),
40       &context.settings().get_protocol_and_hostname(),
41     )?;
42     let create_or_update = CreateOrUpdatePrivateMessage {
43       id: id.clone(),
44       actor: ObjectId::new(actor.actor_id()),
45       to: [ObjectId::new(recipient.actor_id())],
46       object: private_message.into_apub(context).await?,
47       kind,
48       unparsed: Default::default(),
49     };
50     let inbox = vec![recipient.shared_inbox_or_inbox()];
51     send_lemmy_activity(context, create_or_update, actor, inbox, true).await
52   }
53 }
54
55 #[async_trait::async_trait(?Send)]
56 impl ActivityHandler for CreateOrUpdatePrivateMessage {
57   type DataType = LemmyContext;
58   type Error = LemmyError;
59
60   fn id(&self) -> &Url {
61     &self.id
62   }
63
64   fn actor(&self) -> &Url {
65     self.actor.inner()
66   }
67
68   #[tracing::instrument(skip_all)]
69   async fn verify(
70     &self,
71     context: &Data<LemmyContext>,
72     request_counter: &mut i32,
73   ) -> Result<(), LemmyError> {
74     let local_site_data = blocking(context.pool(), fetch_local_site_data).await??;
75     check_apub_id_valid(self.id(), &local_site_data, context.settings())
76       .map_err(LemmyError::from_message)?;
77
78     verify_person(&self.actor, context, request_counter).await?;
79     verify_domains_match(self.actor.inner(), self.object.id.inner())?;
80     verify_domains_match(self.to[0].inner(), self.object.to[0].inner())?;
81     ApubPrivateMessage::verify(&self.object, self.actor.inner(), context, request_counter).await?;
82     Ok(())
83   }
84
85   #[tracing::instrument(skip_all)]
86   async fn receive(
87     self,
88     context: &Data<LemmyContext>,
89     request_counter: &mut i32,
90   ) -> Result<(), LemmyError> {
91     let private_message =
92       ApubPrivateMessage::from_apub(self.object, context, request_counter).await?;
93
94     let notif_type = match self.kind {
95       CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
96       CreateOrUpdateType::Update => UserOperationCrud::EditPrivateMessage,
97     };
98     send_pm_ws_message(private_message.id, notif_type, None, context).await?;
99
100     Ok(())
101   }
102 }