2 use actix_web::web::Data;
3 use lemmy_api_common::{
6 check_downvotes_enabled,
7 get_local_user_view_from_jwt,
12 use lemmy_apub::{ApubLikeableType, ApubObjectType};
13 use lemmy_db_queries::{source::post::Post_, Crud, Likeable, Saveable};
14 use lemmy_db_schema::source::{moderator::*, post::*};
15 use lemmy_db_views::post_view::PostView;
16 use lemmy_utils::{ApiError, ConnectionId, LemmyError};
17 use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperation};
19 #[async_trait::async_trait(?Send)]
20 impl Perform for CreatePostLike {
21 type Response = PostResponse;
25 context: &Data<LemmyContext>,
26 websocket_id: Option<ConnectionId>,
27 ) -> Result<PostResponse, LemmyError> {
28 let data: &CreatePostLike = &self;
29 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
31 // Don't do a downvote if site has downvotes disabled
32 check_downvotes_enabled(data.score, context.pool()).await?;
34 // Check for a community ban
35 let post_id = data.post_id;
36 let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
38 check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
40 let like_form = PostLikeForm {
41 post_id: data.post_id,
42 person_id: local_user_view.person.id,
46 // Remove any likes first
47 let person_id = local_user_view.person.id;
48 blocking(context.pool(), move |conn| {
49 PostLike::remove(conn, person_id, post_id)
53 // Only add the like if the score isnt 0
54 let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
56 let like_form2 = like_form.clone();
57 let like = move |conn: &'_ _| PostLike::like(conn, &like_form2);
58 if blocking(context.pool(), like).await?.is_err() {
59 return Err(ApiError::err("couldnt_like_post").into());
62 if like_form.score == 1 {
63 post.send_like(&local_user_view.person, context).await?;
64 } else if like_form.score == -1 {
65 post.send_dislike(&local_user_view.person, context).await?;
69 .send_undo_like(&local_user_view.person, context)
73 // Mark the post as read
74 mark_post_as_read(person_id, post_id, context.pool()).await?;
76 let post_id = data.post_id;
77 let person_id = local_user_view.person.id;
78 let post_view = blocking(context.pool(), move |conn| {
79 PostView::read(conn, post_id, Some(person_id))
82 .map_err(|_| ApiError::err("couldnt_find_post"))?;
84 let res = PostResponse { post_view };
86 context.chat_server().do_send(SendPost {
87 op: UserOperation::CreatePostLike,
96 #[async_trait::async_trait(?Send)]
97 impl Perform for LockPost {
98 type Response = PostResponse;
102 context: &Data<LemmyContext>,
103 websocket_id: Option<ConnectionId>,
104 ) -> Result<PostResponse, LemmyError> {
105 let data: &LockPost = &self;
106 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
108 let post_id = data.post_id;
109 let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
112 local_user_view.person.id,
113 orig_post.community_id,
118 // Verify that only the mods can lock
121 local_user_view.person.id,
122 orig_post.community_id,
127 let post_id = data.post_id;
128 let locked = data.locked;
129 let updated_post = blocking(context.pool(), move |conn| {
130 Post::update_locked(conn, post_id, locked)
135 let form = ModLockPostForm {
136 mod_person_id: local_user_view.person.id,
137 post_id: data.post_id,
138 locked: Some(locked),
140 blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
144 .send_update(&local_user_view.person, context)
148 let post_id = data.post_id;
149 let post_view = blocking(context.pool(), move |conn| {
150 PostView::read(conn, post_id, Some(local_user_view.person.id))
154 let res = PostResponse { post_view };
156 context.chat_server().do_send(SendPost {
157 op: UserOperation::LockPost,
166 #[async_trait::async_trait(?Send)]
167 impl Perform for StickyPost {
168 type Response = PostResponse;
172 context: &Data<LemmyContext>,
173 websocket_id: Option<ConnectionId>,
174 ) -> Result<PostResponse, LemmyError> {
175 let data: &StickyPost = &self;
176 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
178 let post_id = data.post_id;
179 let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
182 local_user_view.person.id,
183 orig_post.community_id,
188 // Verify that only the mods can sticky
191 local_user_view.person.id,
192 orig_post.community_id,
197 let post_id = data.post_id;
198 let stickied = data.stickied;
199 let updated_post = blocking(context.pool(), move |conn| {
200 Post::update_stickied(conn, post_id, stickied)
205 let form = ModStickyPostForm {
206 mod_person_id: local_user_view.person.id,
207 post_id: data.post_id,
208 stickied: Some(stickied),
210 blocking(context.pool(), move |conn| {
211 ModStickyPost::create(conn, &form)
216 // TODO stickied should pry work like locked for ease of use
218 .send_update(&local_user_view.person, context)
222 let post_id = data.post_id;
223 let post_view = blocking(context.pool(), move |conn| {
224 PostView::read(conn, post_id, Some(local_user_view.person.id))
228 let res = PostResponse { post_view };
230 context.chat_server().do_send(SendPost {
231 op: UserOperation::StickyPost,
240 #[async_trait::async_trait(?Send)]
241 impl Perform for SavePost {
242 type Response = PostResponse;
246 context: &Data<LemmyContext>,
247 _websocket_id: Option<ConnectionId>,
248 ) -> Result<PostResponse, LemmyError> {
249 let data: &SavePost = &self;
250 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
252 let post_saved_form = PostSavedForm {
253 post_id: data.post_id,
254 person_id: local_user_view.person.id,
258 let save = move |conn: &'_ _| PostSaved::save(conn, &post_saved_form);
259 if blocking(context.pool(), save).await?.is_err() {
260 return Err(ApiError::err("couldnt_save_post").into());
263 let unsave = move |conn: &'_ _| PostSaved::unsave(conn, &post_saved_form);
264 if blocking(context.pool(), unsave).await?.is_err() {
265 return Err(ApiError::err("couldnt_save_post").into());
269 let post_id = data.post_id;
270 let person_id = local_user_view.person.id;
271 let post_view = blocking(context.pool(), move |conn| {
272 PostView::read(conn, post_id, Some(person_id))
276 // Mark the post as read
277 mark_post_as_read(person_id, post_id, context.pool()).await?;
279 Ok(PostResponse { post_view })