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