]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/receive/comment.rs
Split api crate into api_structs and api
[lemmy.git] / crates / apub / src / activities / receive / comment.rs
1 use crate::{activities::receive::get_actor_as_person, objects::FromApub, ActorType, NoteExt};
2 use activitystreams::{
3   activity::{ActorAndObjectRefExt, Create, Dislike, Like, Update},
4   base::ExtendsExt,
5 };
6 use anyhow::Context;
7 use lemmy_api_common::{blocking, comment::CommentResponse, send_local_notifs};
8 use lemmy_db_queries::{source::comment::Comment_, Crud, Likeable};
9 use lemmy_db_schema::source::{
10   comment::{Comment, CommentLike, CommentLikeForm},
11   post::Post,
12 };
13 use lemmy_db_views::comment_view::CommentView;
14 use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError};
15 use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation};
16
17 pub(crate) async fn receive_create_comment(
18   create: Create,
19   context: &LemmyContext,
20   request_counter: &mut i32,
21 ) -> Result<(), LemmyError> {
22   let person = get_actor_as_person(&create, context, request_counter).await?;
23   let note = NoteExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
24     .context(location_info!())?;
25
26   let comment =
27     Comment::from_apub(&note, context, person.actor_id(), request_counter, false).await?;
28
29   let post_id = comment.post_id;
30   let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
31
32   // Note:
33   // Although mentions could be gotten from the post tags (they are included there), or the ccs,
34   // Its much easier to scrape them from the comment body, since the API has to do that
35   // anyway.
36   let mentions = scrape_text_for_mentions(&comment.content);
37   let recipient_ids = send_local_notifs(
38     mentions,
39     comment.clone(),
40     person,
41     post,
42     context.pool(),
43     true,
44   )
45   .await?;
46
47   // Refetch the view
48   let comment_view = blocking(context.pool(), move |conn| {
49     CommentView::read(conn, comment.id, None)
50   })
51   .await??;
52
53   let res = CommentResponse {
54     comment_view,
55     recipient_ids,
56     form_id: None,
57   };
58
59   context.chat_server().do_send(SendComment {
60     op: UserOperation::CreateComment,
61     comment: res,
62     websocket_id: None,
63   });
64
65   Ok(())
66 }
67
68 pub(crate) async fn receive_update_comment(
69   update: Update,
70   context: &LemmyContext,
71   request_counter: &mut i32,
72 ) -> Result<(), LemmyError> {
73   let note = NoteExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
74     .context(location_info!())?;
75   let person = get_actor_as_person(&update, context, request_counter).await?;
76
77   let comment =
78     Comment::from_apub(&note, context, person.actor_id(), request_counter, false).await?;
79
80   let comment_id = comment.id;
81   let post_id = comment.post_id;
82   let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
83
84   let mentions = scrape_text_for_mentions(&comment.content);
85   let recipient_ids =
86     send_local_notifs(mentions, comment, person, post, context.pool(), false).await?;
87
88   // Refetch the view
89   let comment_view = blocking(context.pool(), move |conn| {
90     CommentView::read(conn, comment_id, None)
91   })
92   .await??;
93
94   let res = CommentResponse {
95     comment_view,
96     recipient_ids,
97     form_id: None,
98   };
99
100   context.chat_server().do_send(SendComment {
101     op: UserOperation::EditComment,
102     comment: res,
103     websocket_id: None,
104   });
105
106   Ok(())
107 }
108
109 pub(crate) async fn receive_like_comment(
110   like: Like,
111   comment: Comment,
112   context: &LemmyContext,
113   request_counter: &mut i32,
114 ) -> Result<(), LemmyError> {
115   let person = get_actor_as_person(&like, context, request_counter).await?;
116
117   let comment_id = comment.id;
118   let like_form = CommentLikeForm {
119     comment_id,
120     post_id: comment.post_id,
121     person_id: person.id,
122     score: 1,
123   };
124   let person_id = person.id;
125   blocking(context.pool(), move |conn| {
126     CommentLike::remove(conn, person_id, comment_id)?;
127     CommentLike::like(conn, &like_form)
128   })
129   .await??;
130
131   // Refetch the view
132   let comment_view = blocking(context.pool(), move |conn| {
133     CommentView::read(conn, comment_id, None)
134   })
135   .await??;
136
137   // TODO get those recipient actor ids from somewhere
138   let recipient_ids = vec![];
139   let res = CommentResponse {
140     comment_view,
141     recipient_ids,
142     form_id: None,
143   };
144
145   context.chat_server().do_send(SendComment {
146     op: UserOperation::CreateCommentLike,
147     comment: res,
148     websocket_id: None,
149   });
150
151   Ok(())
152 }
153
154 pub(crate) async fn receive_dislike_comment(
155   dislike: Dislike,
156   comment: Comment,
157   context: &LemmyContext,
158   request_counter: &mut i32,
159 ) -> Result<(), LemmyError> {
160   let person = get_actor_as_person(&dislike, context, request_counter).await?;
161
162   let comment_id = comment.id;
163   let like_form = CommentLikeForm {
164     comment_id,
165     post_id: comment.post_id,
166     person_id: person.id,
167     score: -1,
168   };
169   let person_id = person.id;
170   blocking(context.pool(), move |conn| {
171     CommentLike::remove(conn, person_id, comment_id)?;
172     CommentLike::like(conn, &like_form)
173   })
174   .await??;
175
176   // Refetch the view
177   let comment_view = blocking(context.pool(), move |conn| {
178     CommentView::read(conn, comment_id, None)
179   })
180   .await??;
181
182   // TODO get those recipient actor ids from somewhere
183   let recipient_ids = vec![];
184   let res = CommentResponse {
185     comment_view,
186     recipient_ids,
187     form_id: None,
188   };
189
190   context.chat_server().do_send(SendComment {
191     op: UserOperation::CreateCommentLike,
192     comment: res,
193     websocket_id: None,
194   });
195
196   Ok(())
197 }
198
199 pub(crate) async fn receive_delete_comment(
200   context: &LemmyContext,
201   comment: Comment,
202 ) -> Result<(), LemmyError> {
203   let deleted_comment = blocking(context.pool(), move |conn| {
204     Comment::update_deleted(conn, comment.id, true)
205   })
206   .await??;
207
208   // Refetch the view
209   let comment_id = deleted_comment.id;
210   let comment_view = blocking(context.pool(), move |conn| {
211     CommentView::read(conn, comment_id, None)
212   })
213   .await??;
214
215   // TODO get those recipient actor ids from somewhere
216   let recipient_ids = vec![];
217   let res = CommentResponse {
218     comment_view,
219     recipient_ids,
220     form_id: None,
221   };
222   context.chat_server().do_send(SendComment {
223     op: UserOperation::EditComment,
224     comment: res,
225     websocket_id: None,
226   });
227
228   Ok(())
229 }
230
231 pub(crate) async fn receive_remove_comment(
232   context: &LemmyContext,
233   comment: Comment,
234 ) -> Result<(), LemmyError> {
235   let removed_comment = blocking(context.pool(), move |conn| {
236     Comment::update_removed(conn, comment.id, true)
237   })
238   .await??;
239
240   // Refetch the view
241   let comment_id = removed_comment.id;
242   let comment_view = blocking(context.pool(), move |conn| {
243     CommentView::read(conn, comment_id, None)
244   })
245   .await??;
246
247   // TODO get those recipient actor ids from somewhere
248   let recipient_ids = vec![];
249   let res = CommentResponse {
250     comment_view,
251     recipient_ids,
252     form_id: None,
253   };
254   context.chat_server().do_send(SendComment {
255     op: UserOperation::EditComment,
256     comment: res,
257     websocket_id: None,
258   });
259
260   Ok(())
261 }