]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/receive/post.rs
Refactor activitypub code
[lemmy.git] / crates / apub / src / activities / receive / post.rs
1 use crate::{
2   activities::receive::get_actor_as_user,
3   inbox::receive_for_community::verify_mod_activity,
4   objects::FromApub,
5   ActorType,
6   PageExt,
7 };
8 use activitystreams::{
9   activity::{Announce, Create, Dislike, Like, Update},
10   prelude::*,
11 };
12 use anyhow::Context;
13 use lemmy_api_structs::{blocking, post::PostResponse};
14 use lemmy_db_queries::{source::post::Post_, ApubObject, Crud, Likeable};
15 use lemmy_db_schema::{
16   source::{
17     community::Community,
18     post::{Post, PostLike, PostLikeForm},
19   },
20   DbUrl,
21 };
22 use lemmy_db_views::post_view::PostView;
23 use lemmy_utils::{location_info, LemmyError};
24 use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperation};
25
26 pub(crate) async fn receive_create_post(
27   create: Create,
28   context: &LemmyContext,
29   request_counter: &mut i32,
30 ) -> Result<(), LemmyError> {
31   let user = get_actor_as_user(&create, context, request_counter).await?;
32   let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
33     .context(location_info!())?;
34
35   let post = Post::from_apub(&page, context, user.actor_id(), request_counter, false).await?;
36
37   // Refetch the view
38   let post_id = post.id;
39   let post_view = blocking(context.pool(), move |conn| {
40     PostView::read(conn, post_id, None)
41   })
42   .await??;
43
44   let res = PostResponse { post_view };
45
46   context.chat_server().do_send(SendPost {
47     op: UserOperation::CreatePost,
48     post: res,
49     websocket_id: None,
50   });
51
52   Ok(())
53 }
54
55 pub(crate) async fn receive_update_post(
56   update: Update,
57   announce: Option<Announce>,
58   context: &LemmyContext,
59   request_counter: &mut i32,
60 ) -> Result<(), LemmyError> {
61   let user = get_actor_as_user(&update, context, request_counter).await?;
62   let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
63     .context(location_info!())?;
64
65   let post_id: DbUrl = page
66     .id_unchecked()
67     .context(location_info!())?
68     .to_owned()
69     .into();
70   let old_post = blocking(context.pool(), move |conn| {
71     Post::read_from_apub_id(conn, &post_id)
72   })
73   .await??;
74
75   // If sticked or locked state was changed, make sure the actor is a mod
76   let stickied = page.ext_one.stickied.context(location_info!())?;
77   let locked = !page.ext_one.comments_enabled.context(location_info!())?;
78   let mut is_mod_action = false;
79   if stickied != old_post.stickied || locked != old_post.locked {
80     let community = blocking(context.pool(), move |conn| {
81       Community::read(conn, old_post.community_id)
82     })
83     .await??;
84     verify_mod_activity(&update, announce, &community, context).await?;
85     is_mod_action = true;
86   }
87
88   let post = Post::from_apub(
89     &page,
90     context,
91     user.actor_id(),
92     request_counter,
93     is_mod_action,
94   )
95   .await?;
96
97   let post_id = post.id;
98   // Refetch the view
99   let post_view = blocking(context.pool(), move |conn| {
100     PostView::read(conn, post_id, None)
101   })
102   .await??;
103
104   let res = PostResponse { post_view };
105
106   context.chat_server().do_send(SendPost {
107     op: UserOperation::EditPost,
108     post: res,
109     websocket_id: None,
110   });
111
112   Ok(())
113 }
114
115 pub(crate) async fn receive_like_post(
116   like: Like,
117   post: Post,
118   context: &LemmyContext,
119   request_counter: &mut i32,
120 ) -> Result<(), LemmyError> {
121   let user = get_actor_as_user(&like, context, request_counter).await?;
122
123   let post_id = post.id;
124   let like_form = PostLikeForm {
125     post_id,
126     user_id: user.id,
127     score: 1,
128   };
129   let user_id = user.id;
130   blocking(context.pool(), move |conn| {
131     PostLike::remove(conn, user_id, post_id)?;
132     PostLike::like(conn, &like_form)
133   })
134   .await??;
135
136   // Refetch the view
137   let post_view = blocking(context.pool(), move |conn| {
138     PostView::read(conn, post_id, None)
139   })
140   .await??;
141
142   let res = PostResponse { post_view };
143
144   context.chat_server().do_send(SendPost {
145     op: UserOperation::CreatePostLike,
146     post: res,
147     websocket_id: None,
148   });
149
150   Ok(())
151 }
152
153 pub(crate) async fn receive_dislike_post(
154   dislike: Dislike,
155   post: Post,
156   context: &LemmyContext,
157   request_counter: &mut i32,
158 ) -> Result<(), LemmyError> {
159   let user = get_actor_as_user(&dislike, context, request_counter).await?;
160
161   let post_id = post.id;
162   let like_form = PostLikeForm {
163     post_id,
164     user_id: user.id,
165     score: -1,
166   };
167   let user_id = user.id;
168   blocking(context.pool(), move |conn| {
169     PostLike::remove(conn, user_id, post_id)?;
170     PostLike::like(conn, &like_form)
171   })
172   .await??;
173
174   // Refetch the view
175   let post_view = blocking(context.pool(), move |conn| {
176     PostView::read(conn, post_id, None)
177   })
178   .await??;
179
180   let res = PostResponse { post_view };
181
182   context.chat_server().do_send(SendPost {
183     op: UserOperation::CreatePostLike,
184     post: res,
185     websocket_id: None,
186   });
187
188   Ok(())
189 }
190
191 pub(crate) async fn receive_delete_post(
192   context: &LemmyContext,
193   post: Post,
194 ) -> Result<(), LemmyError> {
195   let deleted_post = blocking(context.pool(), move |conn| {
196     Post::update_deleted(conn, post.id, true)
197   })
198   .await??;
199
200   // Refetch the view
201   let post_id = deleted_post.id;
202   let post_view = blocking(context.pool(), move |conn| {
203     PostView::read(conn, post_id, None)
204   })
205   .await??;
206
207   let res = PostResponse { post_view };
208   context.chat_server().do_send(SendPost {
209     op: UserOperation::EditPost,
210     post: res,
211     websocket_id: None,
212   });
213
214   Ok(())
215 }
216
217 pub(crate) async fn receive_remove_post(
218   context: &LemmyContext,
219   post: Post,
220 ) -> Result<(), LemmyError> {
221   let removed_post = blocking(context.pool(), move |conn| {
222     Post::update_removed(conn, post.id, true)
223   })
224   .await??;
225
226   // Refetch the view
227   let post_id = removed_post.id;
228   let post_view = blocking(context.pool(), move |conn| {
229     PostView::read(conn, post_id, None)
230   })
231   .await??;
232
233   let res = PostResponse { post_view };
234   context.chat_server().do_send(SendPost {
235     op: UserOperation::EditPost,
236     post: res,
237     websocket_id: None,
238   });
239
240   Ok(())
241 }