2 api::{comment::CommentResponse, community::CommunityResponse, post::PostResponse},
3 apub::inbox::shared_inbox::{get_user_from_activity, receive_unhandled_activity},
5 fetcher::{get_or_fetch_and_insert_remote_comment, get_or_fetch_and_insert_remote_post},
12 routes::ChatServerParam,
14 server::{SendComment, SendCommunityRoomMessage, SendPost},
20 use activitystreams_new::{activity::*, object::Note, prelude::*};
21 use actix_web::{client::Client, HttpResponse};
23 comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
24 comment_view::CommentView,
25 community::{Community, CommunityForm},
26 community_view::CommunityView,
28 post::{Post, PostForm, PostLike, PostLikeForm},
33 use activitystreams_new::base::AnyBase;
34 use crate::apub::inbox::shared_inbox::announce_if_community_is_local;
36 pub async fn receive_undo(
40 chat_server: ChatServerParam,
41 ) -> Result<HttpResponse, LemmyError> {
42 let undo = Undo::from_any_base(activity)?.unwrap();
43 match undo.object().as_single_kind_str() {
44 Some("Delete") => receive_undo_delete(undo, client, pool, chat_server).await,
45 Some("Remove") => receive_undo_remove(undo, client, pool, chat_server).await,
46 Some("Like") => receive_undo_like(undo, client, pool, chat_server).await,
47 Some("Dislike") => receive_undo_dislike(undo, client, pool, chat_server).await,
48 // TODO: handle undo_dislike?
49 _ => receive_unhandled_activity(undo),
53 async fn receive_undo_delete(
57 chat_server: ChatServerParam,
58 ) -> Result<HttpResponse, LemmyError> {
59 let delete = Delete::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
60 let type_ = delete.object().as_single_kind_str().unwrap();
62 "Note" => receive_undo_delete_comment(undo, &delete, client, pool, chat_server).await,
63 "Page" => receive_undo_delete_post(undo, &delete, client, pool, chat_server).await,
64 "Group" => receive_undo_delete_community(undo, &delete, client, pool, chat_server).await,
65 d => Err(format_err!("Undo Delete type {} not supported", d).into()),
69 async fn receive_undo_remove(
73 chat_server: ChatServerParam,
74 ) -> Result<HttpResponse, LemmyError> {
75 let remove = Remove::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
77 let type_ = remove.object().as_single_kind_str().unwrap();
79 "Note" => receive_undo_remove_comment(undo, &remove, client, pool, chat_server).await,
80 "Page" => receive_undo_remove_post(undo, &remove, client, pool, chat_server).await,
81 "Group" => receive_undo_remove_community(undo, &remove, client, pool, chat_server).await,
82 d => Err(format_err!("Undo Delete type {} not supported", d).into()),
86 async fn receive_undo_like(
90 chat_server: ChatServerParam,
91 ) -> Result<HttpResponse, LemmyError> {
92 let like = Like::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
94 let type_ = like.object().as_single_kind_str().unwrap();
96 "Note" => receive_undo_like_comment(undo, &like, client, pool, chat_server).await,
97 "Page" => receive_undo_like_post(undo, &like, client, pool, chat_server).await,
98 d => Err(format_err!("Undo Delete type {} not supported", d).into()),
102 async fn receive_undo_dislike(
106 chat_server: ChatServerParam,
107 ) -> Result<HttpResponse, LemmyError> {
108 let dislike = Dislike::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
110 let type_ = dislike.object().as_single_kind_str().unwrap();
112 // TODO: handle dislike
113 d => Err(format_err!("Undo Delete type {} not supported", d).into()),
117 async fn receive_undo_delete_comment(
122 chat_server: ChatServerParam,
123 ) -> Result<HttpResponse, LemmyError> {
124 let user = get_user_from_activity(delete, client, pool).await?;
125 let note = Note::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
127 let comment_ap_id = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?)
131 let comment = get_or_fetch_and_insert_remote_comment(&comment_ap_id, client, pool).await?;
133 let comment_form = CommentForm {
134 content: comment.content.to_owned(),
135 parent_id: comment.parent_id,
136 post_id: comment.post_id,
137 creator_id: comment.creator_id,
139 deleted: Some(false),
142 updated: Some(naive_now()),
143 ap_id: comment.ap_id,
144 local: comment.local,
146 let comment_id = comment.id;
147 blocking(pool, move |conn| {
148 Comment::update(conn, comment_id, &comment_form)
153 let comment_id = comment.id;
155 blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??;
157 // TODO get those recipient actor ids from somewhere
158 let recipient_ids = vec![];
159 let res = CommentResponse {
160 comment: comment_view,
164 chat_server.do_send(SendComment {
165 op: UserOperation::EditComment,
170 announce_if_community_is_local(undo, &user, client, pool).await?;
171 Ok(HttpResponse::Ok().finish())
174 async fn receive_undo_remove_comment(
179 chat_server: ChatServerParam,
180 ) -> Result<HttpResponse, LemmyError> {
181 let mod_ = get_user_from_activity(remove, client, pool).await?;
182 let note = Note::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
184 let comment_ap_id = CommentForm::from_apub(¬e, client, pool, &mod_.actor_id()?)
188 let comment = get_or_fetch_and_insert_remote_comment(&comment_ap_id, client, pool).await?;
190 let comment_form = CommentForm {
191 content: comment.content.to_owned(),
192 parent_id: comment.parent_id,
193 post_id: comment.post_id,
194 creator_id: comment.creator_id,
195 removed: Some(false),
199 updated: Some(naive_now()),
200 ap_id: comment.ap_id,
201 local: comment.local,
203 let comment_id = comment.id;
204 blocking(pool, move |conn| {
205 Comment::update(conn, comment_id, &comment_form)
210 let comment_id = comment.id;
212 blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??;
214 // TODO get those recipient actor ids from somewhere
215 let recipient_ids = vec![];
216 let res = CommentResponse {
217 comment: comment_view,
221 chat_server.do_send(SendComment {
222 op: UserOperation::EditComment,
227 announce_if_community_is_local(undo, &mod_, client, pool).await?;
228 Ok(HttpResponse::Ok().finish())
231 async fn receive_undo_delete_post(
236 chat_server: ChatServerParam,
237 ) -> Result<HttpResponse, LemmyError> {
238 let user = get_user_from_activity(delete, client, pool).await?;
239 let page = PageExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
241 let post_ap_id = PostForm::from_apub(&page, client, pool, &user.actor_id()?)
245 let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?;
247 let post_form = PostForm {
248 name: post.name.to_owned(),
249 url: post.url.to_owned(),
250 body: post.body.to_owned(),
251 creator_id: post.creator_id.to_owned(),
252 community_id: post.community_id,
254 deleted: Some(false),
258 updated: Some(naive_now()),
259 embed_title: post.embed_title,
260 embed_description: post.embed_description,
261 embed_html: post.embed_html,
262 thumbnail_url: post.thumbnail_url,
267 let post_id = post.id;
268 blocking(pool, move |conn| Post::update(conn, post_id, &post_form)).await??;
271 let post_id = post.id;
272 let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??;
274 let res = PostResponse { post: post_view };
276 chat_server.do_send(SendPost {
277 op: UserOperation::EditPost,
282 announce_if_community_is_local(undo, &user, client, pool).await?;
283 Ok(HttpResponse::Ok().finish())
286 async fn receive_undo_remove_post(
291 chat_server: ChatServerParam,
292 ) -> Result<HttpResponse, LemmyError> {
293 let mod_ = get_user_from_activity(remove, client, pool).await?;
294 let page = PageExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
296 let post_ap_id = PostForm::from_apub(&page, client, pool, &mod_.actor_id()?)
300 let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?;
302 let post_form = PostForm {
303 name: post.name.to_owned(),
304 url: post.url.to_owned(),
305 body: post.body.to_owned(),
306 creator_id: post.creator_id.to_owned(),
307 community_id: post.community_id,
308 removed: Some(false),
313 updated: Some(naive_now()),
314 embed_title: post.embed_title,
315 embed_description: post.embed_description,
316 embed_html: post.embed_html,
317 thumbnail_url: post.thumbnail_url,
322 let post_id = post.id;
323 blocking(pool, move |conn| Post::update(conn, post_id, &post_form)).await??;
326 let post_id = post.id;
327 let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??;
329 let res = PostResponse { post: post_view };
331 chat_server.do_send(SendPost {
332 op: UserOperation::EditPost,
337 announce_if_community_is_local(undo, &mod_, client, pool).await?;
338 Ok(HttpResponse::Ok().finish())
341 async fn receive_undo_delete_community(
346 chat_server: ChatServerParam,
347 ) -> Result<HttpResponse, LemmyError> {
348 let user = get_user_from_activity(delete, client, pool).await?;
349 let group = GroupExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
351 let community_actor_id = CommunityForm::from_apub(&group, client, pool, &user.actor_id()?)
355 let community = blocking(pool, move |conn| {
356 Community::read_from_actor_id(conn, &community_actor_id)
360 let community_form = CommunityForm {
361 name: community.name.to_owned(),
362 title: community.title.to_owned(),
363 description: community.description.to_owned(),
364 category_id: community.category_id, // Note: need to keep this due to foreign key constraint
365 creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint
368 updated: Some(naive_now()),
369 deleted: Some(false),
370 nsfw: community.nsfw,
371 actor_id: community.actor_id,
372 local: community.local,
373 private_key: community.private_key,
374 public_key: community.public_key,
375 last_refreshed_at: None,
378 let community_id = community.id;
379 blocking(pool, move |conn| {
380 Community::update(conn, community_id, &community_form)
384 let community_id = community.id;
385 let res = CommunityResponse {
386 community: blocking(pool, move |conn| {
387 CommunityView::read(conn, community_id, None)
392 let community_id = res.community.id;
394 chat_server.do_send(SendCommunityRoomMessage {
395 op: UserOperation::EditCommunity,
401 announce_if_community_is_local(undo, &user, client, pool).await?;
402 Ok(HttpResponse::Ok().finish())
405 async fn receive_undo_remove_community(
410 chat_server: ChatServerParam,
411 ) -> Result<HttpResponse, LemmyError> {
412 let mod_ = get_user_from_activity(remove, client, pool).await?;
413 let group = GroupExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
415 let community_actor_id = CommunityForm::from_apub(&group, client, pool, &mod_.actor_id()?)
419 let community = blocking(pool, move |conn| {
420 Community::read_from_actor_id(conn, &community_actor_id)
424 let community_form = CommunityForm {
425 name: community.name.to_owned(),
426 title: community.title.to_owned(),
427 description: community.description.to_owned(),
428 category_id: community.category_id, // Note: need to keep this due to foreign key constraint
429 creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint
430 removed: Some(false),
432 updated: Some(naive_now()),
434 nsfw: community.nsfw,
435 actor_id: community.actor_id,
436 local: community.local,
437 private_key: community.private_key,
438 public_key: community.public_key,
439 last_refreshed_at: None,
442 let community_id = community.id;
443 blocking(pool, move |conn| {
444 Community::update(conn, community_id, &community_form)
448 let community_id = community.id;
449 let res = CommunityResponse {
450 community: blocking(pool, move |conn| {
451 CommunityView::read(conn, community_id, None)
456 let community_id = res.community.id;
458 chat_server.do_send(SendCommunityRoomMessage {
459 op: UserOperation::EditCommunity,
465 announce_if_community_is_local(undo, &mod_, client, pool).await?;
466 Ok(HttpResponse::Ok().finish())
469 async fn receive_undo_like_comment(
474 chat_server: ChatServerParam,
475 ) -> Result<HttpResponse, LemmyError> {
476 let user = get_user_from_activity(like, client, pool).await?;
477 let note = Note::from_any_base(like.object().to_owned().one().unwrap())?.unwrap();
479 let comment = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?).await?;
481 let comment_id = get_or_fetch_and_insert_remote_comment(&comment.get_ap_id()?, client, pool)
485 let like_form = CommentLikeForm {
487 post_id: comment.post_id,
491 blocking(pool, move |conn| CommentLike::remove(conn, &like_form)).await??;
495 blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??;
497 // TODO get those recipient actor ids from somewhere
498 let recipient_ids = vec![];
499 let res = CommentResponse {
500 comment: comment_view,
504 chat_server.do_send(SendComment {
505 op: UserOperation::CreateCommentLike,
510 announce_if_community_is_local(undo, &user, client, pool).await?;
511 Ok(HttpResponse::Ok().finish())
514 async fn receive_undo_like_post(
519 chat_server: ChatServerParam,
520 ) -> Result<HttpResponse, LemmyError> {
521 let user = get_user_from_activity(like, client, pool).await?;
522 let page = PageExt::from_any_base(like.object().to_owned().one().unwrap())?.unwrap();
524 let post = PostForm::from_apub(&page, client, pool, &user.actor_id()?).await?;
526 let post_id = get_or_fetch_and_insert_remote_post(&post.get_ap_id()?, client, pool)
530 let like_form = PostLikeForm {
535 blocking(pool, move |conn| PostLike::remove(conn, &like_form)).await??;
538 let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??;
540 let res = PostResponse { post: post_view };
542 chat_server.do_send(SendPost {
543 op: UserOperation::CreatePostLike,
548 announce_if_community_is_local(undo, &user, client, pool).await?;
549 Ok(HttpResponse::Ok().finish())