]> Untitled Git - lemmy.git/blob - crates/api/src/comment/like.rs
Split apart api files (#2216)
[lemmy.git] / crates / api / src / comment / like.rs
1 use crate::Perform;
2 use actix_web::web::Data;
3 use lemmy_api_common::{
4   blocking,
5   check_community_ban,
6   check_downvotes_enabled,
7   comment::{CommentResponse, CreateCommentLike},
8   get_local_user_view_from_jwt,
9 };
10 use lemmy_apub::{
11   fetcher::post_or_comment::PostOrComment,
12   protocol::activities::voting::{
13     undo_vote::UndoVote,
14     vote::{Vote, VoteType},
15   },
16 };
17 use lemmy_db_schema::{
18   newtypes::LocalUserId,
19   source::comment::{CommentLike, CommentLikeForm},
20   traits::Likeable,
21 };
22 use lemmy_db_views::{comment_view::CommentView, local_user_view::LocalUserView};
23 use lemmy_utils::{ConnectionId, LemmyError};
24 use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperation};
25 use std::convert::TryInto;
26
27 #[async_trait::async_trait(?Send)]
28 impl Perform for CreateCommentLike {
29   type Response = CommentResponse;
30
31   #[tracing::instrument(skip(context, websocket_id))]
32   async fn perform(
33     &self,
34     context: &Data<LemmyContext>,
35     websocket_id: Option<ConnectionId>,
36   ) -> Result<CommentResponse, LemmyError> {
37     let data: &CreateCommentLike = self;
38     let local_user_view =
39       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
40
41     let mut recipient_ids = Vec::<LocalUserId>::new();
42
43     // Don't do a downvote if site has downvotes disabled
44     check_downvotes_enabled(data.score, context.pool()).await?;
45
46     let comment_id = data.comment_id;
47     let orig_comment = blocking(context.pool(), move |conn| {
48       CommentView::read(conn, comment_id, None)
49     })
50     .await??;
51
52     check_community_ban(
53       local_user_view.person.id,
54       orig_comment.community.id,
55       context.pool(),
56     )
57     .await?;
58
59     // Add parent user to recipients
60     let recipient_id = orig_comment.get_recipient_id();
61     if let Ok(local_recipient) = blocking(context.pool(), move |conn| {
62       LocalUserView::read_person(conn, recipient_id)
63     })
64     .await?
65     {
66       recipient_ids.push(local_recipient.local_user.id);
67     }
68
69     let like_form = CommentLikeForm {
70       comment_id: data.comment_id,
71       post_id: orig_comment.post.id,
72       person_id: local_user_view.person.id,
73       score: data.score,
74     };
75
76     // Remove any likes first
77     let person_id = local_user_view.person.id;
78     blocking(context.pool(), move |conn| {
79       CommentLike::remove(conn, person_id, comment_id)
80     })
81     .await??;
82
83     // Only add the like if the score isnt 0
84     let comment = orig_comment.comment;
85     let object = PostOrComment::Comment(Box::new(comment.into()));
86     let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
87     if do_add {
88       let like_form2 = like_form.clone();
89       let like = move |conn: &'_ _| CommentLike::like(conn, &like_form2);
90       blocking(context.pool(), like)
91         .await?
92         .map_err(|e| LemmyError::from_error_message(e, "couldnt_like_comment"))?;
93
94       Vote::send(
95         &object,
96         &local_user_view.person.clone().into(),
97         orig_comment.community.id,
98         like_form.score.try_into()?,
99         context,
100       )
101       .await?;
102     } else {
103       // API doesn't distinguish between Undo/Like and Undo/Dislike
104       UndoVote::send(
105         &object,
106         &local_user_view.person.clone().into(),
107         orig_comment.community.id,
108         VoteType::Like,
109         context,
110       )
111       .await?;
112     }
113
114     send_comment_ws_message(
115       data.comment_id,
116       UserOperation::CreateCommentLike,
117       websocket_id,
118       None,
119       Some(local_user_view.person.id),
120       recipient_ids,
121       context,
122     )
123     .await
124   }
125 }