2 api::{comment::CommentResponse, community::CommunityResponse, post::PostResponse},
4 fetcher::{get_or_fetch_and_insert_remote_comment, get_or_fetch_and_insert_remote_post},
6 announce_if_community_is_local, get_user_from_activity, receive_unhandled_activity,
8 ActorType, FromApub, GroupExt, PageExt,
11 routes::ChatServerParam,
13 server::{SendComment, SendCommunityRoomMessage, SendPost},
18 use activitystreams_new::{activity::*, base::AnyBase, object::Note, prelude::*};
19 use actix_web::{client::Client, HttpResponse};
21 comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
22 comment_view::CommentView,
23 community::{Community, CommunityForm},
24 community_view::CommunityView,
26 post::{Post, PostForm, PostLike, PostLikeForm},
31 pub async fn receive_undo(
35 chat_server: ChatServerParam,
36 ) -> Result<HttpResponse, LemmyError> {
37 let undo = Undo::from_any_base(activity)?.unwrap();
38 match undo.object().as_single_kind_str() {
39 Some("Delete") => receive_undo_delete(undo, client, pool, chat_server).await,
40 Some("Remove") => receive_undo_remove(undo, client, pool, chat_server).await,
41 Some("Like") => receive_undo_like(undo, client, pool, chat_server).await,
42 Some("Dislike") => receive_undo_dislike(undo, client, pool, chat_server).await,
43 // TODO: handle undo_dislike?
44 _ => receive_unhandled_activity(undo),
48 async fn receive_undo_delete(
52 chat_server: ChatServerParam,
53 ) -> Result<HttpResponse, LemmyError> {
54 let delete = Delete::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
55 let type_ = delete.object().as_single_kind_str().unwrap();
57 "Note" => receive_undo_delete_comment(undo, &delete, client, pool, chat_server).await,
58 "Page" => receive_undo_delete_post(undo, &delete, client, pool, chat_server).await,
59 "Group" => receive_undo_delete_community(undo, &delete, client, pool, chat_server).await,
60 d => Err(format_err!("Undo Delete type {} not supported", d).into()),
64 async fn receive_undo_remove(
68 chat_server: ChatServerParam,
69 ) -> Result<HttpResponse, LemmyError> {
70 let remove = Remove::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
72 let type_ = remove.object().as_single_kind_str().unwrap();
74 "Note" => receive_undo_remove_comment(undo, &remove, client, pool, chat_server).await,
75 "Page" => receive_undo_remove_post(undo, &remove, client, pool, chat_server).await,
76 "Group" => receive_undo_remove_community(undo, &remove, client, pool, chat_server).await,
77 d => Err(format_err!("Undo Delete type {} not supported", d).into()),
81 async fn receive_undo_like(
85 chat_server: ChatServerParam,
86 ) -> Result<HttpResponse, LemmyError> {
87 let like = Like::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
89 let type_ = like.object().as_single_kind_str().unwrap();
91 "Note" => receive_undo_like_comment(undo, &like, client, pool, chat_server).await,
92 "Page" => receive_undo_like_post(undo, &like, client, pool, chat_server).await,
93 d => Err(format_err!("Undo Delete type {} not supported", d).into()),
97 async fn receive_undo_dislike(
101 _chat_server: ChatServerParam,
102 ) -> Result<HttpResponse, LemmyError> {
103 let dislike = Dislike::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
105 let type_ = dislike.object().as_single_kind_str().unwrap();
106 Err(format_err!("Undo Delete type {} not supported", type_).into())
109 async fn receive_undo_delete_comment(
114 chat_server: ChatServerParam,
115 ) -> Result<HttpResponse, LemmyError> {
116 let user = get_user_from_activity(delete, client, pool).await?;
117 let note = Note::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
119 let comment_ap_id = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?)
123 let comment = get_or_fetch_and_insert_remote_comment(&comment_ap_id, client, pool).await?;
125 let comment_form = CommentForm {
126 content: comment.content.to_owned(),
127 parent_id: comment.parent_id,
128 post_id: comment.post_id,
129 creator_id: comment.creator_id,
131 deleted: Some(false),
134 updated: Some(naive_now()),
135 ap_id: comment.ap_id,
136 local: comment.local,
138 let comment_id = comment.id;
139 blocking(pool, move |conn| {
140 Comment::update(conn, comment_id, &comment_form)
145 let comment_id = comment.id;
147 blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??;
149 // TODO get those recipient actor ids from somewhere
150 let recipient_ids = vec![];
151 let res = CommentResponse {
152 comment: comment_view,
157 chat_server.do_send(SendComment {
158 op: UserOperation::EditComment,
163 announce_if_community_is_local(undo, &user, client, pool).await?;
164 Ok(HttpResponse::Ok().finish())
167 async fn receive_undo_remove_comment(
172 chat_server: ChatServerParam,
173 ) -> Result<HttpResponse, LemmyError> {
174 let mod_ = get_user_from_activity(remove, client, pool).await?;
175 let note = Note::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
177 let comment_ap_id = CommentForm::from_apub(¬e, client, pool, &mod_.actor_id()?)
181 let comment = get_or_fetch_and_insert_remote_comment(&comment_ap_id, client, pool).await?;
183 let comment_form = CommentForm {
184 content: comment.content.to_owned(),
185 parent_id: comment.parent_id,
186 post_id: comment.post_id,
187 creator_id: comment.creator_id,
188 removed: Some(false),
192 updated: Some(naive_now()),
193 ap_id: comment.ap_id,
194 local: comment.local,
196 let comment_id = comment.id;
197 blocking(pool, move |conn| {
198 Comment::update(conn, comment_id, &comment_form)
203 let comment_id = comment.id;
205 blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??;
207 // TODO get those recipient actor ids from somewhere
208 let recipient_ids = vec![];
209 let res = CommentResponse {
210 comment: comment_view,
215 chat_server.do_send(SendComment {
216 op: UserOperation::EditComment,
221 announce_if_community_is_local(undo, &mod_, client, pool).await?;
222 Ok(HttpResponse::Ok().finish())
225 async fn receive_undo_delete_post(
230 chat_server: ChatServerParam,
231 ) -> Result<HttpResponse, LemmyError> {
232 let user = get_user_from_activity(delete, client, pool).await?;
233 let page = PageExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
235 let post_ap_id = PostForm::from_apub(&page, client, pool, &user.actor_id()?)
239 let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?;
241 let post_form = PostForm {
242 name: post.name.to_owned(),
243 url: post.url.to_owned(),
244 body: post.body.to_owned(),
245 creator_id: post.creator_id.to_owned(),
246 community_id: post.community_id,
248 deleted: Some(false),
252 updated: Some(naive_now()),
253 embed_title: post.embed_title,
254 embed_description: post.embed_description,
255 embed_html: post.embed_html,
256 thumbnail_url: post.thumbnail_url,
261 let post_id = post.id;
262 blocking(pool, move |conn| Post::update(conn, post_id, &post_form)).await??;
265 let post_id = post.id;
266 let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??;
268 let res = PostResponse { post: post_view };
270 chat_server.do_send(SendPost {
271 op: UserOperation::EditPost,
276 announce_if_community_is_local(undo, &user, client, pool).await?;
277 Ok(HttpResponse::Ok().finish())
280 async fn receive_undo_remove_post(
285 chat_server: ChatServerParam,
286 ) -> Result<HttpResponse, LemmyError> {
287 let mod_ = get_user_from_activity(remove, client, pool).await?;
288 let page = PageExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
290 let post_ap_id = PostForm::from_apub(&page, client, pool, &mod_.actor_id()?)
294 let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?;
296 let post_form = PostForm {
297 name: post.name.to_owned(),
298 url: post.url.to_owned(),
299 body: post.body.to_owned(),
300 creator_id: post.creator_id.to_owned(),
301 community_id: post.community_id,
302 removed: Some(false),
307 updated: Some(naive_now()),
308 embed_title: post.embed_title,
309 embed_description: post.embed_description,
310 embed_html: post.embed_html,
311 thumbnail_url: post.thumbnail_url,
316 let post_id = post.id;
317 blocking(pool, move |conn| Post::update(conn, post_id, &post_form)).await??;
320 let post_id = post.id;
321 let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??;
323 let res = PostResponse { post: post_view };
325 chat_server.do_send(SendPost {
326 op: UserOperation::EditPost,
331 announce_if_community_is_local(undo, &mod_, client, pool).await?;
332 Ok(HttpResponse::Ok().finish())
335 async fn receive_undo_delete_community(
340 chat_server: ChatServerParam,
341 ) -> Result<HttpResponse, LemmyError> {
342 let user = get_user_from_activity(delete, client, pool).await?;
343 let group = GroupExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
345 let community_actor_id = CommunityForm::from_apub(&group, client, pool, &user.actor_id()?)
349 let community = blocking(pool, move |conn| {
350 Community::read_from_actor_id(conn, &community_actor_id)
354 let community_form = CommunityForm {
355 name: community.name.to_owned(),
356 title: community.title.to_owned(),
357 description: community.description.to_owned(),
358 category_id: community.category_id, // Note: need to keep this due to foreign key constraint
359 creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint
362 updated: Some(naive_now()),
363 deleted: Some(false),
364 nsfw: community.nsfw,
365 actor_id: community.actor_id,
366 local: community.local,
367 private_key: community.private_key,
368 public_key: community.public_key,
369 last_refreshed_at: None,
372 let community_id = community.id;
373 blocking(pool, move |conn| {
374 Community::update(conn, community_id, &community_form)
378 let community_id = community.id;
379 let res = CommunityResponse {
380 community: blocking(pool, move |conn| {
381 CommunityView::read(conn, community_id, None)
386 let community_id = res.community.id;
388 chat_server.do_send(SendCommunityRoomMessage {
389 op: UserOperation::EditCommunity,
395 announce_if_community_is_local(undo, &user, client, pool).await?;
396 Ok(HttpResponse::Ok().finish())
399 async fn receive_undo_remove_community(
404 chat_server: ChatServerParam,
405 ) -> Result<HttpResponse, LemmyError> {
406 let mod_ = get_user_from_activity(remove, client, pool).await?;
407 let group = GroupExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
409 let community_actor_id = CommunityForm::from_apub(&group, client, pool, &mod_.actor_id()?)
413 let community = blocking(pool, move |conn| {
414 Community::read_from_actor_id(conn, &community_actor_id)
418 let community_form = CommunityForm {
419 name: community.name.to_owned(),
420 title: community.title.to_owned(),
421 description: community.description.to_owned(),
422 category_id: community.category_id, // Note: need to keep this due to foreign key constraint
423 creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint
424 removed: Some(false),
426 updated: Some(naive_now()),
428 nsfw: community.nsfw,
429 actor_id: community.actor_id,
430 local: community.local,
431 private_key: community.private_key,
432 public_key: community.public_key,
433 last_refreshed_at: None,
436 let community_id = community.id;
437 blocking(pool, move |conn| {
438 Community::update(conn, community_id, &community_form)
442 let community_id = community.id;
443 let res = CommunityResponse {
444 community: blocking(pool, move |conn| {
445 CommunityView::read(conn, community_id, None)
450 let community_id = res.community.id;
452 chat_server.do_send(SendCommunityRoomMessage {
453 op: UserOperation::EditCommunity,
459 announce_if_community_is_local(undo, &mod_, client, pool).await?;
460 Ok(HttpResponse::Ok().finish())
463 async fn receive_undo_like_comment(
468 chat_server: ChatServerParam,
469 ) -> Result<HttpResponse, LemmyError> {
470 let user = get_user_from_activity(like, client, pool).await?;
471 let note = Note::from_any_base(like.object().to_owned().one().unwrap())?.unwrap();
473 let comment = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?).await?;
475 let comment_id = get_or_fetch_and_insert_remote_comment(&comment.get_ap_id()?, client, pool)
479 let like_form = CommentLikeForm {
481 post_id: comment.post_id,
485 blocking(pool, move |conn| CommentLike::remove(conn, &like_form)).await??;
489 blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??;
491 // TODO get those recipient actor ids from somewhere
492 let recipient_ids = vec![];
493 let res = CommentResponse {
494 comment: comment_view,
499 chat_server.do_send(SendComment {
500 op: UserOperation::CreateCommentLike,
505 announce_if_community_is_local(undo, &user, client, pool).await?;
506 Ok(HttpResponse::Ok().finish())
509 async fn receive_undo_like_post(
514 chat_server: ChatServerParam,
515 ) -> Result<HttpResponse, LemmyError> {
516 let user = get_user_from_activity(like, client, pool).await?;
517 let page = PageExt::from_any_base(like.object().to_owned().one().unwrap())?.unwrap();
519 let post = PostForm::from_apub(&page, client, pool, &user.actor_id()?).await?;
521 let post_id = get_or_fetch_and_insert_remote_post(&post.get_ap_id()?, client, pool)
525 let like_form = PostLikeForm {
530 blocking(pool, move |conn| PostLike::remove(conn, &like_form)).await??;
533 let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??;
535 let res = PostResponse { post: post_view };
537 chat_server.do_send(SendPost {
538 op: UserOperation::CreatePostLike,
543 announce_if_community_is_local(undo, &user, client, pool).await?;
544 Ok(HttpResponse::Ok().finish())