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