]> Untitled Git - lemmy.git/blob - src/apub/private_message.rs
routes.api: fix get_captcha endpoint (#1135)
[lemmy.git] / src / apub / private_message.rs
1 use crate::{
2   apub::{
3     activities::generate_activity_id,
4     activity_queue::send_activity,
5     check_actor_domain,
6     check_is_apub_id_valid,
7     create_tombstone,
8     fetcher::get_or_fetch_and_upsert_user,
9     insert_activity,
10     ActorType,
11     ApubObjectType,
12     FromApub,
13     ToApub,
14   },
15   DbPool,
16   LemmyContext,
17 };
18 use activitystreams::{
19   activity::{
20     kind::{CreateType, DeleteType, UndoType, UpdateType},
21     Create,
22     Delete,
23     Undo,
24     Update,
25   },
26   object::{kind::NoteType, Note, Tombstone},
27   prelude::*,
28 };
29 use anyhow::Context;
30 use lemmy_api_structs::blocking;
31 use lemmy_db::{
32   private_message::{PrivateMessage, PrivateMessageForm},
33   user::User_,
34   Crud,
35 };
36 use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
37 use url::Url;
38
39 #[async_trait::async_trait(?Send)]
40 impl ToApub for PrivateMessage {
41   type Response = Note;
42
43   async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> {
44     let mut private_message = Note::new();
45
46     let creator_id = self.creator_id;
47     let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??;
48
49     let recipient_id = self.recipient_id;
50     let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
51
52     private_message
53       .set_context(activitystreams::context())
54       .set_id(Url::parse(&self.ap_id.to_owned())?)
55       .set_published(convert_datetime(self.published))
56       .set_content(self.content.to_owned())
57       .set_to(recipient.actor_id)
58       .set_attributed_to(creator.actor_id);
59
60     if let Some(u) = self.updated {
61       private_message.set_updated(convert_datetime(u));
62     }
63
64     Ok(private_message)
65   }
66
67   fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
68     create_tombstone(self.deleted, &self.ap_id, self.updated, NoteType::Note)
69   }
70 }
71
72 #[async_trait::async_trait(?Send)]
73 impl FromApub for PrivateMessageForm {
74   type ApubType = Note;
75
76   /// Parse an ActivityPub note received from another instance into a Lemmy Private message
77   async fn from_apub(
78     note: &Note,
79     context: &LemmyContext,
80     expected_domain: Option<Url>,
81   ) -> Result<PrivateMessageForm, LemmyError> {
82     let creator_actor_id = note
83       .attributed_to()
84       .context(location_info!())?
85       .clone()
86       .single_xsd_any_uri()
87       .context(location_info!())?;
88
89     let creator = get_or_fetch_and_upsert_user(&creator_actor_id, context).await?;
90     let recipient_actor_id = note
91       .to()
92       .context(location_info!())?
93       .clone()
94       .single_xsd_any_uri()
95       .context(location_info!())?;
96     let recipient = get_or_fetch_and_upsert_user(&recipient_actor_id, context).await?;
97     let ap_id = note.id_unchecked().context(location_info!())?.to_string();
98     check_is_apub_id_valid(&Url::parse(&ap_id)?)?;
99
100     Ok(PrivateMessageForm {
101       creator_id: creator.id,
102       recipient_id: recipient.id,
103       content: note
104         .content()
105         .context(location_info!())?
106         .as_single_xsd_string()
107         .context(location_info!())?
108         .to_string(),
109       published: note.published().map(|u| u.to_owned().naive_local()),
110       updated: note.updated().map(|u| u.to_owned().naive_local()),
111       deleted: None,
112       read: None,
113       ap_id: Some(check_actor_domain(note, expected_domain)?),
114       local: false,
115     })
116   }
117 }
118
119 #[async_trait::async_trait(?Send)]
120 impl ApubObjectType for PrivateMessage {
121   /// Send out information about a newly created private message
122   async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
123     let note = self.to_apub(context.pool()).await?;
124
125     let recipient_id = self.recipient_id;
126     let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
127
128     let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?);
129     let to = recipient.get_inbox_url()?;
130     create
131       .set_context(activitystreams::context())
132       .set_id(generate_activity_id(CreateType::Create)?)
133       .set_to(to.clone());
134
135     insert_activity(creator.id, create.clone(), true, context.pool()).await?;
136
137     send_activity(context.activity_queue(), create, creator, vec![to])?;
138     Ok(())
139   }
140
141   /// Send out information about an edited post, to the followers of the community.
142   async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
143     let note = self.to_apub(context.pool()).await?;
144
145     let recipient_id = self.recipient_id;
146     let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
147
148     let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?);
149     let to = recipient.get_inbox_url()?;
150     update
151       .set_context(activitystreams::context())
152       .set_id(generate_activity_id(UpdateType::Update)?)
153       .set_to(to.clone());
154
155     insert_activity(creator.id, update.clone(), true, context.pool()).await?;
156
157     send_activity(context.activity_queue(), update, creator, vec![to])?;
158     Ok(())
159   }
160
161   async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
162     let note = self.to_apub(context.pool()).await?;
163
164     let recipient_id = self.recipient_id;
165     let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
166
167     let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
168     let to = recipient.get_inbox_url()?;
169     delete
170       .set_context(activitystreams::context())
171       .set_id(generate_activity_id(DeleteType::Delete)?)
172       .set_to(to.clone());
173
174     insert_activity(creator.id, delete.clone(), true, context.pool()).await?;
175
176     send_activity(context.activity_queue(), delete, creator, vec![to])?;
177     Ok(())
178   }
179
180   async fn send_undo_delete(
181     &self,
182     creator: &User_,
183     context: &LemmyContext,
184   ) -> Result<(), LemmyError> {
185     let note = self.to_apub(context.pool()).await?;
186
187     let recipient_id = self.recipient_id;
188     let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
189
190     let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
191     let to = recipient.get_inbox_url()?;
192     delete
193       .set_context(activitystreams::context())
194       .set_id(generate_activity_id(DeleteType::Delete)?)
195       .set_to(to.clone());
196
197     // Undo that fake activity
198     let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
199     undo
200       .set_context(activitystreams::context())
201       .set_id(generate_activity_id(UndoType::Undo)?)
202       .set_to(to.clone());
203
204     insert_activity(creator.id, undo.clone(), true, context.pool()).await?;
205
206     send_activity(context.activity_queue(), undo, creator, vec![to])?;
207     Ok(())
208   }
209
210   async fn send_remove(&self, _mod_: &User_, _context: &LemmyContext) -> Result<(), LemmyError> {
211     unimplemented!()
212   }
213
214   async fn send_undo_remove(
215     &self,
216     _mod_: &User_,
217     _context: &LemmyContext,
218   ) -> Result<(), LemmyError> {
219     unimplemented!()
220   }
221 }