]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/create_or_update/private_message.rs
Add SendActivity trait so that api crates compile in parallel with lemmy_apub
[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   SendActivity,
10 };
11 use activitypub_federation::{
12   core::object_id::ObjectId,
13   data::Data,
14   traits::{ActivityHandler, Actor, ApubObject},
15   utils::verify_domains_match,
16 };
17 use lemmy_api_common::{
18   context::LemmyContext,
19   private_message::{CreatePrivateMessage, EditPrivateMessage, PrivateMessageResponse},
20   websocket::{send::send_pm_ws_message, UserOperationCrud},
21 };
22 use lemmy_db_schema::{
23   newtypes::PersonId,
24   source::{person::Person, private_message::PrivateMessage},
25   traits::Crud,
26 };
27 use lemmy_utils::error::LemmyError;
28 use url::Url;
29
30 #[async_trait::async_trait(?Send)]
31 impl SendActivity for CreatePrivateMessage {
32   type Response = PrivateMessageResponse;
33
34   async fn send_activity(
35     _request: &Self,
36     response: &Self::Response,
37     context: &LemmyContext,
38   ) -> Result<(), LemmyError> {
39     CreateOrUpdateChatMessage::send(
40       &response.private_message_view.private_message,
41       response.private_message_view.creator.id,
42       CreateOrUpdateType::Create,
43       context,
44     )
45     .await
46   }
47 }
48 #[async_trait::async_trait(?Send)]
49 impl SendActivity for EditPrivateMessage {
50   type Response = PrivateMessageResponse;
51
52   async fn send_activity(
53     _request: &Self,
54     response: &Self::Response,
55     context: &LemmyContext,
56   ) -> Result<(), LemmyError> {
57     CreateOrUpdateChatMessage::send(
58       &response.private_message_view.private_message,
59       response.private_message_view.creator.id,
60       CreateOrUpdateType::Update,
61       context,
62     )
63     .await
64   }
65 }
66
67 impl CreateOrUpdateChatMessage {
68   #[tracing::instrument(skip_all)]
69   async fn send(
70     private_message: &PrivateMessage,
71     sender_id: PersonId,
72     kind: CreateOrUpdateType,
73     context: &LemmyContext,
74   ) -> Result<(), LemmyError> {
75     let recipient_id = private_message.recipient_id;
76     let sender: ApubPerson = Person::read(context.pool(), sender_id).await?.into();
77     let recipient: ApubPerson = Person::read(context.pool(), recipient_id).await?.into();
78
79     let id = generate_activity_id(
80       kind.clone(),
81       &context.settings().get_protocol_and_hostname(),
82     )?;
83     let create_or_update = CreateOrUpdateChatMessage {
84       id: id.clone(),
85       actor: ObjectId::new(sender.actor_id()),
86       to: [ObjectId::new(recipient.actor_id())],
87       object: ApubPrivateMessage(private_message.clone())
88         .into_apub(context)
89         .await?,
90       kind,
91     };
92     let inbox = vec![recipient.shared_inbox_or_inbox()];
93     send_lemmy_activity(context, create_or_update, &sender, inbox, true).await
94   }
95 }
96
97 #[async_trait::async_trait(?Send)]
98 impl ActivityHandler for CreateOrUpdateChatMessage {
99   type DataType = LemmyContext;
100   type Error = LemmyError;
101
102   fn id(&self) -> &Url {
103     &self.id
104   }
105
106   fn actor(&self) -> &Url {
107     self.actor.inner()
108   }
109
110   #[tracing::instrument(skip_all)]
111   async fn verify(
112     &self,
113     context: &Data<LemmyContext>,
114     request_counter: &mut i32,
115   ) -> Result<(), LemmyError> {
116     verify_person(&self.actor, context, request_counter).await?;
117     verify_domains_match(self.actor.inner(), self.object.id.inner())?;
118     verify_domains_match(self.to[0].inner(), self.object.to[0].inner())?;
119     ApubPrivateMessage::verify(&self.object, self.actor.inner(), context, request_counter).await?;
120     Ok(())
121   }
122
123   #[tracing::instrument(skip_all)]
124   async fn receive(
125     self,
126     context: &Data<LemmyContext>,
127     request_counter: &mut i32,
128   ) -> Result<(), LemmyError> {
129     let private_message =
130       ApubPrivateMessage::from_apub(self.object, context, request_counter).await?;
131
132     let notif_type = match self.kind {
133       CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
134       CreateOrUpdateType::Update => UserOperationCrud::EditPrivateMessage,
135     };
136     send_pm_ws_message(private_message.id, notif_type, None, context).await?;
137
138     Ok(())
139   }
140 }