use crate::{ activities::receive::announce_if_community_is_local, fetcher::get_or_fetch_and_insert_post, inbox::shared_inbox::get_user_from_activity, ActorType, FromApub, PageExt, }; use activitystreams::{activity::*, prelude::*}; use actix_web::HttpResponse; use anyhow::Context; use lemmy_db::{ naive_now, post::{Post, PostForm, PostLike}, post_view::PostView, Crud, Likeable, }; use lemmy_structs::{blocking, post::PostResponse}; use lemmy_utils::{location_info, LemmyError}; use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperation}; pub(crate) async fn receive_undo_like_post( undo: Undo, like: &Like, context: &LemmyContext, ) -> Result { let user = get_user_from_activity(like, context).await?; let page = PageExt::from_any_base(like.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; let post = PostForm::from_apub(&page, context, None).await?; let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, context) .await? .id; let user_id = user.id; blocking(context.pool(), move |conn| { PostLike::remove(conn, user_id, post_id) }) .await??; // Refetch the view let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, post_id, None) }) .await??; let res = PostResponse { post: post_view }; context.chat_server().do_send(SendPost { op: UserOperation::CreatePostLike, post: res, websocket_id: None, }); announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } pub(crate) async fn receive_undo_dislike_post( undo: Undo, dislike: &Dislike, context: &LemmyContext, ) -> Result { let user = get_user_from_activity(dislike, context).await?; let page = PageExt::from_any_base( dislike .object() .to_owned() .one() .context(location_info!())?, )? .context(location_info!())?; let post = PostForm::from_apub(&page, context, None).await?; let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, context) .await? .id; let user_id = user.id; blocking(context.pool(), move |conn| { PostLike::remove(conn, user_id, post_id) }) .await??; // Refetch the view let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, post_id, None) }) .await??; let res = PostResponse { post: post_view }; context.chat_server().do_send(SendPost { op: UserOperation::CreatePostLike, post: res, websocket_id: None, }); announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } pub(crate) async fn receive_undo_delete_post( undo: Undo, delete: &Delete, context: &LemmyContext, ) -> Result { let user = get_user_from_activity(delete, context).await?; let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; let post_ap_id = PostForm::from_apub(&page, context, Some(user.actor_id()?)) .await? .get_ap_id()?; let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; let post_form = PostForm { name: post.name.to_owned(), url: post.url.to_owned(), body: post.body.to_owned(), creator_id: post.creator_id.to_owned(), community_id: post.community_id, removed: None, deleted: Some(false), nsfw: post.nsfw, locked: None, stickied: None, updated: Some(naive_now()), embed_title: post.embed_title, embed_description: post.embed_description, embed_html: post.embed_html, thumbnail_url: post.thumbnail_url, ap_id: Some(post.ap_id), local: post.local, published: None, }; let post_id = post.id; blocking(context.pool(), move |conn| { Post::update(conn, post_id, &post_form) }) .await??; // Refetch the view let post_id = post.id; let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, post_id, None) }) .await??; let res = PostResponse { post: post_view }; context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, websocket_id: None, }); announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } pub(crate) async fn receive_undo_remove_post( undo: Undo, remove: &Remove, context: &LemmyContext, ) -> Result { let mod_ = get_user_from_activity(remove, context).await?; let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; let post_ap_id = PostForm::from_apub(&page, context, None) .await? .get_ap_id()?; let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; let post_form = PostForm { name: post.name.to_owned(), url: post.url.to_owned(), body: post.body.to_owned(), creator_id: post.creator_id.to_owned(), community_id: post.community_id, removed: Some(false), deleted: None, nsfw: post.nsfw, locked: None, stickied: None, updated: Some(naive_now()), embed_title: post.embed_title, embed_description: post.embed_description, embed_html: post.embed_html, thumbnail_url: post.thumbnail_url, ap_id: Some(post.ap_id), local: post.local, published: None, }; let post_id = post.id; blocking(context.pool(), move |conn| { Post::update(conn, post_id, &post_form) }) .await??; // Refetch the view let post_id = post.id; let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, post_id, None) }) .await??; let res = PostResponse { post: post_view }; context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, websocket_id: None, }); announce_if_community_is_local(undo, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) }