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 = match blocking(context.pool(), move |conn| {
75 PostView::read(conn, post_id, Some(person_id))
80 Err(_e) => return Err(ApiError::err("couldnt_find_post").into()),
83 let res = PostResponse { post_view };
85 context.chat_server().do_send(SendPost {
86 op: UserOperation::CreatePostLike,
95 #[async_trait::async_trait(?Send)]
96 impl Perform for LockPost {
97 type Response = PostResponse;
101 context: &Data<LemmyContext>,
102 websocket_id: Option<ConnectionId>,
103 ) -> Result<PostResponse, LemmyError> {
104 let data: &LockPost = &self;
105 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
107 let post_id = data.post_id;
108 let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
111 local_user_view.person.id,
112 orig_post.community_id,
117 // Verify that only the mods can lock
120 local_user_view.person.id,
121 orig_post.community_id,
126 let post_id = data.post_id;
127 let locked = data.locked;
128 let updated_post = blocking(context.pool(), move |conn| {
129 Post::update_locked(conn, post_id, locked)
134 let form = ModLockPostForm {
135 mod_person_id: local_user_view.person.id,
136 post_id: data.post_id,
137 locked: Some(locked),
139 blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
143 .send_update(&local_user_view.person, context)
147 let post_id = data.post_id;
148 let post_view = blocking(context.pool(), move |conn| {
149 PostView::read(conn, post_id, Some(local_user_view.person.id))
153 let res = PostResponse { post_view };
155 context.chat_server().do_send(SendPost {
156 op: UserOperation::LockPost,
165 #[async_trait::async_trait(?Send)]
166 impl Perform for StickyPost {
167 type Response = PostResponse;
171 context: &Data<LemmyContext>,
172 websocket_id: Option<ConnectionId>,
173 ) -> Result<PostResponse, LemmyError> {
174 let data: &StickyPost = &self;
175 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
177 let post_id = data.post_id;
178 let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
181 local_user_view.person.id,
182 orig_post.community_id,
187 // Verify that only the mods can sticky
190 local_user_view.person.id,
191 orig_post.community_id,
196 let post_id = data.post_id;
197 let stickied = data.stickied;
198 let updated_post = blocking(context.pool(), move |conn| {
199 Post::update_stickied(conn, post_id, stickied)
204 let form = ModStickyPostForm {
205 mod_person_id: local_user_view.person.id,
206 post_id: data.post_id,
207 stickied: Some(stickied),
209 blocking(context.pool(), move |conn| {
210 ModStickyPost::create(conn, &form)
215 // TODO stickied should pry work like locked for ease of use
217 .send_update(&local_user_view.person, context)
221 let post_id = data.post_id;
222 let post_view = blocking(context.pool(), move |conn| {
223 PostView::read(conn, post_id, Some(local_user_view.person.id))
227 let res = PostResponse { post_view };
229 context.chat_server().do_send(SendPost {
230 op: UserOperation::StickyPost,
239 #[async_trait::async_trait(?Send)]
240 impl Perform for SavePost {
241 type Response = PostResponse;
245 context: &Data<LemmyContext>,
246 _websocket_id: Option<ConnectionId>,
247 ) -> Result<PostResponse, LemmyError> {
248 let data: &SavePost = &self;
249 let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
251 let post_saved_form = PostSavedForm {
252 post_id: data.post_id,
253 person_id: local_user_view.person.id,
257 let save = move |conn: &'_ _| PostSaved::save(conn, &post_saved_form);
258 if blocking(context.pool(), save).await?.is_err() {
259 return Err(ApiError::err("couldnt_save_post").into());
262 let unsave = move |conn: &'_ _| PostSaved::unsave(conn, &post_saved_form);
263 if blocking(context.pool(), unsave).await?.is_err() {
264 return Err(ApiError::err("couldnt_save_post").into());
268 let post_id = data.post_id;
269 let person_id = local_user_view.person.id;
270 let post_view = blocking(context.pool(), move |conn| {
271 PostView::read(conn, post_id, Some(person_id))
275 Ok(PostResponse { post_view })