]> Untitled Git - lemmy.git/blob - src/apub/inbox/activities/delete.rs
routes.api: fix get_captcha endpoint (#1135)
[lemmy.git] / src / apub / inbox / activities / delete.rs
1 use crate::{
2   apub::{
3     fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
4     inbox::shared_inbox::{
5       announce_if_community_is_local,
6       get_user_from_activity,
7       receive_unhandled_activity,
8     },
9     ActorType,
10     FromApub,
11     GroupExt,
12     PageExt,
13   },
14   websocket::{
15     messages::{SendComment, SendCommunityRoomMessage, SendPost},
16     UserOperation,
17   },
18   LemmyContext,
19 };
20 use activitystreams::{activity::Delete, base::AnyBase, object::Note, prelude::*};
21 use actix_web::HttpResponse;
22 use anyhow::Context;
23 use lemmy_api_structs::{
24   blocking,
25   comment::CommentResponse,
26   community::CommunityResponse,
27   post::PostResponse,
28 };
29 use lemmy_db::{
30   comment::{Comment, CommentForm},
31   comment_view::CommentView,
32   community::{Community, CommunityForm},
33   community_view::CommunityView,
34   naive_now,
35   post::{Post, PostForm},
36   post_view::PostView,
37   Crud,
38 };
39 use lemmy_utils::{location_info, LemmyError};
40
41 pub async fn receive_delete(
42   activity: AnyBase,
43   context: &LemmyContext,
44 ) -> Result<HttpResponse, LemmyError> {
45   let delete = Delete::from_any_base(activity)?.context(location_info!())?;
46   match delete.object().as_single_kind_str() {
47     Some("Page") => receive_delete_post(delete, context).await,
48     Some("Note") => receive_delete_comment(delete, context).await,
49     Some("Group") => receive_delete_community(delete, context).await,
50     _ => receive_unhandled_activity(delete),
51   }
52 }
53
54 async fn receive_delete_post(
55   delete: Delete,
56   context: &LemmyContext,
57 ) -> Result<HttpResponse, LemmyError> {
58   let user = get_user_from_activity(&delete, context).await?;
59   let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
60     .context(location_info!())?;
61
62   let post_ap_id = PostForm::from_apub(&page, context, Some(user.actor_id()?))
63     .await?
64     .get_ap_id()?;
65
66   let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?;
67
68   let post_form = PostForm {
69     name: post.name.to_owned(),
70     url: post.url.to_owned(),
71     body: post.body.to_owned(),
72     creator_id: post.creator_id.to_owned(),
73     community_id: post.community_id,
74     removed: None,
75     deleted: Some(true),
76     nsfw: post.nsfw,
77     locked: None,
78     stickied: None,
79     updated: Some(naive_now()),
80     embed_title: post.embed_title,
81     embed_description: post.embed_description,
82     embed_html: post.embed_html,
83     thumbnail_url: post.thumbnail_url,
84     ap_id: Some(post.ap_id),
85     local: post.local,
86     published: None,
87   };
88   let post_id = post.id;
89   blocking(context.pool(), move |conn| {
90     Post::update(conn, post_id, &post_form)
91   })
92   .await??;
93
94   // Refetch the view
95   let post_id = post.id;
96   let post_view = blocking(context.pool(), move |conn| {
97     PostView::read(conn, post_id, None)
98   })
99   .await??;
100
101   let res = PostResponse { post: post_view };
102
103   context.chat_server().do_send(SendPost {
104     op: UserOperation::EditPost,
105     post: res,
106     websocket_id: None,
107   });
108
109   announce_if_community_is_local(delete, &user, context).await?;
110   Ok(HttpResponse::Ok().finish())
111 }
112
113 async fn receive_delete_comment(
114   delete: Delete,
115   context: &LemmyContext,
116 ) -> Result<HttpResponse, LemmyError> {
117   let user = get_user_from_activity(&delete, context).await?;
118   let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
119     .context(location_info!())?;
120
121   let comment_ap_id = CommentForm::from_apub(&note, context, Some(user.actor_id()?))
122     .await?
123     .get_ap_id()?;
124
125   let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?;
126
127   let comment_form = CommentForm {
128     content: comment.content.to_owned(),
129     parent_id: comment.parent_id,
130     post_id: comment.post_id,
131     creator_id: comment.creator_id,
132     removed: None,
133     deleted: Some(true),
134     read: None,
135     published: None,
136     updated: Some(naive_now()),
137     ap_id: Some(comment.ap_id),
138     local: comment.local,
139   };
140   let comment_id = comment.id;
141   blocking(context.pool(), move |conn| {
142     Comment::update(conn, comment_id, &comment_form)
143   })
144   .await??;
145
146   // Refetch the view
147   let comment_id = comment.id;
148   let comment_view = blocking(context.pool(), move |conn| {
149     CommentView::read(conn, comment_id, None)
150   })
151   .await??;
152
153   // TODO get those recipient actor ids from somewhere
154   let recipient_ids = vec![];
155   let res = CommentResponse {
156     comment: comment_view,
157     recipient_ids,
158     form_id: None,
159   };
160
161   context.chat_server().do_send(SendComment {
162     op: UserOperation::EditComment,
163     comment: res,
164     websocket_id: None,
165   });
166
167   announce_if_community_is_local(delete, &user, context).await?;
168   Ok(HttpResponse::Ok().finish())
169 }
170
171 async fn receive_delete_community(
172   delete: Delete,
173   context: &LemmyContext,
174 ) -> Result<HttpResponse, LemmyError> {
175   let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
176     .context(location_info!())?;
177   let user = get_user_from_activity(&delete, context).await?;
178
179   let community_actor_id = CommunityForm::from_apub(&group, context, Some(user.actor_id()?))
180     .await?
181     .actor_id
182     .context(location_info!())?;
183
184   let community = blocking(context.pool(), move |conn| {
185     Community::read_from_actor_id(conn, &community_actor_id)
186   })
187   .await??;
188
189   let community_form = CommunityForm {
190     name: community.name.to_owned(),
191     title: community.title.to_owned(),
192     description: community.description.to_owned(),
193     category_id: community.category_id, // Note: need to keep this due to foreign key constraint
194     creator_id: community.creator_id,   // Note: need to keep this due to foreign key constraint
195     removed: None,
196     published: None,
197     updated: Some(naive_now()),
198     deleted: Some(true),
199     nsfw: community.nsfw,
200     actor_id: Some(community.actor_id),
201     local: community.local,
202     private_key: community.private_key,
203     public_key: community.public_key,
204     last_refreshed_at: None,
205     icon: Some(community.icon.to_owned()),
206     banner: Some(community.banner.to_owned()),
207   };
208
209   let community_id = community.id;
210   blocking(context.pool(), move |conn| {
211     Community::update(conn, community_id, &community_form)
212   })
213   .await??;
214
215   let community_id = community.id;
216   let res = CommunityResponse {
217     community: blocking(context.pool(), move |conn| {
218       CommunityView::read(conn, community_id, None)
219     })
220     .await??,
221   };
222
223   let community_id = res.community.id;
224
225   context.chat_server().do_send(SendCommunityRoomMessage {
226     op: UserOperation::EditCommunity,
227     response: res,
228     community_id,
229     websocket_id: None,
230   });
231
232   announce_if_community_is_local(delete, &user, context).await?;
233   Ok(HttpResponse::Ok().finish())
234 }