2 use actix_web::web::Data;
3 use lemmy_api_common::{
6 check_downvotes_enabled,
7 get_local_user_view_from_jwt,
11 use lemmy_apub::{ApubLikeableType, ApubObjectType};
12 use lemmy_db_queries::{source::post::Post_, Crud, Likeable, Saveable};
13 use lemmy_db_schema::source::{moderator::*, post::*};
14 use lemmy_db_views::post_view::PostView;
15 use lemmy_utils::{ApiError, ConnectionId, LemmyError};
16 use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperation};
18 #[async_trait::async_trait(?Send)]
19 impl Perform for CreatePostLike {
20 type Response = PostResponse;
24 context: &Data<LemmyContext>,
25 websocket_id: Option<ConnectionId>,
26 ) -> Result<PostResponse, LemmyError> {
27 let data: &CreatePostLike = &self;
28 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
30 // Don't do a downvote if site has downvotes disabled
31 check_downvotes_enabled(data.score, context.pool()).await?;
33 // Check for a community ban
34 let post_id = data.post_id;
35 let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
37 check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
39 let like_form = PostLikeForm {
40 post_id: data.post_id,
41 person_id: local_user_view.person.id,
45 // Remove any likes first
46 let person_id = local_user_view.person.id;
47 blocking(context.pool(), move |conn| {
48 PostLike::remove(conn, person_id, post_id)
52 // Only add the like if the score isnt 0
53 let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
55 let like_form2 = like_form.clone();
56 let like = move |conn: &'_ _| PostLike::like(conn, &like_form2);
57 if blocking(context.pool(), like).await?.is_err() {
58 return Err(ApiError::err("couldnt_like_post").into());
61 if like_form.score == 1 {
62 post.send_like(&local_user_view.person, context).await?;
63 } else if like_form.score == -1 {
64 post.send_dislike(&local_user_view.person, context).await?;
68 .send_undo_like(&local_user_view.person, context)
72 let post_id = data.post_id;
73 let person_id = local_user_view.person.id;
74 let post_view = blocking(context.pool(), move |conn| {
75 PostView::read(conn, post_id, Some(person_id))
78 .map_err(|_| ApiError::err("couldnt_find_post"))?;
80 let res = PostResponse { post_view };
82 context.chat_server().do_send(SendPost {
83 op: UserOperation::CreatePostLike,
92 #[async_trait::async_trait(?Send)]
93 impl Perform for LockPost {
94 type Response = PostResponse;
98 context: &Data<LemmyContext>,
99 websocket_id: Option<ConnectionId>,
100 ) -> Result<PostResponse, LemmyError> {
101 let data: &LockPost = &self;
102 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
104 let post_id = data.post_id;
105 let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
108 local_user_view.person.id,
109 orig_post.community_id,
114 // Verify that only the mods can lock
117 local_user_view.person.id,
118 orig_post.community_id,
123 let post_id = data.post_id;
124 let locked = data.locked;
125 let updated_post = blocking(context.pool(), move |conn| {
126 Post::update_locked(conn, post_id, locked)
131 let form = ModLockPostForm {
132 mod_person_id: local_user_view.person.id,
133 post_id: data.post_id,
134 locked: Some(locked),
136 blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
140 .send_update(&local_user_view.person, context)
144 let post_id = data.post_id;
145 let post_view = blocking(context.pool(), move |conn| {
146 PostView::read(conn, post_id, Some(local_user_view.person.id))
150 let res = PostResponse { post_view };
152 context.chat_server().do_send(SendPost {
153 op: UserOperation::LockPost,
162 #[async_trait::async_trait(?Send)]
163 impl Perform for StickyPost {
164 type Response = PostResponse;
168 context: &Data<LemmyContext>,
169 websocket_id: Option<ConnectionId>,
170 ) -> Result<PostResponse, LemmyError> {
171 let data: &StickyPost = &self;
172 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
174 let post_id = data.post_id;
175 let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
178 local_user_view.person.id,
179 orig_post.community_id,
184 // Verify that only the mods can sticky
187 local_user_view.person.id,
188 orig_post.community_id,
193 let post_id = data.post_id;
194 let stickied = data.stickied;
195 let updated_post = blocking(context.pool(), move |conn| {
196 Post::update_stickied(conn, post_id, stickied)
201 let form = ModStickyPostForm {
202 mod_person_id: local_user_view.person.id,
203 post_id: data.post_id,
204 stickied: Some(stickied),
206 blocking(context.pool(), move |conn| {
207 ModStickyPost::create(conn, &form)
212 // TODO stickied should pry work like locked for ease of use
214 .send_update(&local_user_view.person, context)
218 let post_id = data.post_id;
219 let post_view = blocking(context.pool(), move |conn| {
220 PostView::read(conn, post_id, Some(local_user_view.person.id))
224 let res = PostResponse { post_view };
226 context.chat_server().do_send(SendPost {
227 op: UserOperation::StickyPost,
236 #[async_trait::async_trait(?Send)]
237 impl Perform for SavePost {
238 type Response = PostResponse;
242 context: &Data<LemmyContext>,
243 _websocket_id: Option<ConnectionId>,
244 ) -> Result<PostResponse, LemmyError> {
245 let data: &SavePost = &self;
246 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
248 let post_saved_form = PostSavedForm {
249 post_id: data.post_id,
250 person_id: local_user_view.person.id,
254 let save = move |conn: &'_ _| PostSaved::save(conn, &post_saved_form);
255 if blocking(context.pool(), save).await?.is_err() {
256 return Err(ApiError::err("couldnt_save_post").into());
259 let unsave = move |conn: &'_ _| PostSaved::unsave(conn, &post_saved_form);
260 if blocking(context.pool(), unsave).await?.is_err() {
261 return Err(ApiError::err("couldnt_save_post").into());
265 let post_id = data.post_id;
266 let person_id = local_user_view.person.id;
267 let post_view = blocking(context.pool(), move |conn| {
268 PostView::read(conn, post_id, Some(person_id))
272 Ok(PostResponse { post_view })