]> Untitled Git - lemmy.git/blob - server/src/api/comment.rs
Spanish translations
[lemmy.git] / server / src / api / comment.rs
1 use super::*;
2
3 #[derive(Serialize, Deserialize)]
4 pub struct CreateComment {
5   content: String,
6   parent_id: Option<i32>,
7   edit_id: Option<i32>,
8   pub post_id: i32,
9   auth: String,
10 }
11
12 #[derive(Serialize, Deserialize)]
13 pub struct EditComment {
14   content: String,
15   parent_id: Option<i32>,
16   edit_id: i32,
17   creator_id: i32,
18   pub post_id: i32,
19   removed: Option<bool>,
20   deleted: Option<bool>,
21   reason: Option<String>,
22   read: Option<bool>,
23   auth: String,
24 }
25
26 #[derive(Serialize, Deserialize)]
27 pub struct SaveComment {
28   comment_id: i32,
29   save: bool,
30   auth: String,
31 }
32
33 #[derive(Serialize, Deserialize, Clone)]
34 pub struct CommentResponse {
35   op: String,
36   pub comment: CommentView,
37 }
38
39 #[derive(Serialize, Deserialize)]
40 pub struct CreateCommentLike {
41   comment_id: i32,
42   pub post_id: i32,
43   score: i16,
44   auth: String,
45 }
46
47 impl Perform<CommentResponse> for Oper<CreateComment> {
48   fn perform(&self) -> Result<CommentResponse, Error> {
49     let data: &CreateComment = &self.data;
50     let conn = establish_connection();
51
52     let claims = match Claims::decode(&data.auth) {
53       Ok(claims) => claims.claims,
54       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
55     };
56
57     let user_id = claims.id;
58
59     // Check for a community ban
60     let post = Post::read(&conn, data.post_id)?;
61     if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
62       return Err(APIError::err(&self.op, "community_ban"))?;
63     }
64
65     // Check for a site ban
66     if UserView::read(&conn, user_id)?.banned {
67       return Err(APIError::err(&self.op, "site_ban"))?;
68     }
69
70     let content_slurs_removed = remove_slurs(&data.content.to_owned());
71
72     let comment_form = CommentForm {
73       content: content_slurs_removed,
74       parent_id: data.parent_id.to_owned(),
75       post_id: data.post_id,
76       creator_id: user_id,
77       removed: None,
78       deleted: None,
79       read: None,
80       updated: None,
81     };
82
83     let inserted_comment = match Comment::create(&conn, &comment_form) {
84       Ok(comment) => comment,
85       Err(_e) => return Err(APIError::err(&self.op, "couldnt_create_comment"))?,
86     };
87
88     // You like your own comment by default
89     let like_form = CommentLikeForm {
90       comment_id: inserted_comment.id,
91       post_id: data.post_id,
92       user_id: user_id,
93       score: 1,
94     };
95
96     let _inserted_like = match CommentLike::like(&conn, &like_form) {
97       Ok(like) => like,
98       Err(_e) => return Err(APIError::err(&self.op, "couldnt_like_comment"))?,
99     };
100
101     let comment_view = CommentView::read(&conn, inserted_comment.id, Some(user_id))?;
102
103     Ok(CommentResponse {
104       op: self.op.to_string(),
105       comment: comment_view,
106     })
107   }
108 }
109
110 impl Perform<CommentResponse> for Oper<EditComment> {
111   fn perform(&self) -> Result<CommentResponse, Error> {
112     let data: &EditComment = &self.data;
113     let conn = establish_connection();
114
115     let claims = match Claims::decode(&data.auth) {
116       Ok(claims) => claims.claims,
117       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
118     };
119
120     let user_id = claims.id;
121
122     let orig_comment = CommentView::read(&conn, data.edit_id, None)?;
123
124     // You are allowed to mark the comment as read even if you're banned.
125     if data.read.is_none() {
126       // Verify its the creator or a mod, or an admin
127       let mut editors: Vec<i32> = vec![data.creator_id];
128       editors.append(
129         &mut CommunityModeratorView::for_community(&conn, orig_comment.community_id)?
130           .into_iter()
131           .map(|m| m.user_id)
132           .collect(),
133       );
134       editors.append(&mut UserView::admins(&conn)?.into_iter().map(|a| a.id).collect());
135
136       if !editors.contains(&user_id) {
137         return Err(APIError::err(&self.op, "no_comment_edit_allowed"))?;
138       }
139
140       // Check for a community ban
141       if CommunityUserBanView::get(&conn, user_id, orig_comment.community_id).is_ok() {
142         return Err(APIError::err(&self.op, "community_ban"))?;
143       }
144
145       // Check for a site ban
146       if UserView::read(&conn, user_id)?.banned {
147         return Err(APIError::err(&self.op, "site_ban"))?;
148       }
149     }
150
151     let content_slurs_removed = remove_slurs(&data.content.to_owned());
152
153     let comment_form = CommentForm {
154       content: content_slurs_removed,
155       parent_id: data.parent_id,
156       post_id: data.post_id,
157       creator_id: data.creator_id,
158       removed: data.removed.to_owned(),
159       deleted: data.deleted.to_owned(),
160       read: data.read.to_owned(),
161       updated: if data.read.is_some() {
162         orig_comment.updated
163       } else {
164         Some(naive_now())
165       },
166     };
167
168     let _updated_comment = match Comment::update(&conn, data.edit_id, &comment_form) {
169       Ok(comment) => comment,
170       Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment"))?,
171     };
172
173     // Mod tables
174     if let Some(removed) = data.removed.to_owned() {
175       let form = ModRemoveCommentForm {
176         mod_user_id: user_id,
177         comment_id: data.edit_id,
178         removed: Some(removed),
179         reason: data.reason.to_owned(),
180       };
181       ModRemoveComment::create(&conn, &form)?;
182     }
183
184     let comment_view = CommentView::read(&conn, data.edit_id, Some(user_id))?;
185
186     Ok(CommentResponse {
187       op: self.op.to_string(),
188       comment: comment_view,
189     })
190   }
191 }
192
193 impl Perform<CommentResponse> for Oper<SaveComment> {
194   fn perform(&self) -> Result<CommentResponse, Error> {
195     let data: &SaveComment = &self.data;
196     let conn = establish_connection();
197
198     let claims = match Claims::decode(&data.auth) {
199       Ok(claims) => claims.claims,
200       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
201     };
202
203     let user_id = claims.id;
204
205     let comment_saved_form = CommentSavedForm {
206       comment_id: data.comment_id,
207       user_id: user_id,
208     };
209
210     if data.save {
211       match CommentSaved::save(&conn, &comment_saved_form) {
212         Ok(comment) => comment,
213         Err(_e) => return Err(APIError::err(&self.op, "couldnt_save_comment"))?,
214       };
215     } else {
216       match CommentSaved::unsave(&conn, &comment_saved_form) {
217         Ok(comment) => comment,
218         Err(_e) => return Err(APIError::err(&self.op, "couldnt_save_comment"))?,
219       };
220     }
221
222     let comment_view = CommentView::read(&conn, data.comment_id, Some(user_id))?;
223
224     Ok(CommentResponse {
225       op: self.op.to_string(),
226       comment: comment_view,
227     })
228   }
229 }
230
231 impl Perform<CommentResponse> for Oper<CreateCommentLike> {
232   fn perform(&self) -> Result<CommentResponse, Error> {
233     let data: &CreateCommentLike = &self.data;
234     let conn = establish_connection();
235
236     let claims = match Claims::decode(&data.auth) {
237       Ok(claims) => claims.claims,
238       Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
239     };
240
241     let user_id = claims.id;
242
243     // Check for a community ban
244     let post = Post::read(&conn, data.post_id)?;
245     if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
246       return Err(APIError::err(&self.op, "community_ban"))?;
247     }
248
249     // Check for a site ban
250     if UserView::read(&conn, user_id)?.banned {
251       return Err(APIError::err(&self.op, "site_ban"))?;
252     }
253
254     let like_form = CommentLikeForm {
255       comment_id: data.comment_id,
256       post_id: data.post_id,
257       user_id: user_id,
258       score: data.score,
259     };
260
261     // Remove any likes first
262     CommentLike::remove(&conn, &like_form)?;
263
264     // Only add the like if the score isnt 0
265     let do_add = &like_form.score != &0 && (&like_form.score == &1 || &like_form.score == &-1);
266     if do_add {
267       let _inserted_like = match CommentLike::like(&conn, &like_form) {
268         Ok(like) => like,
269         Err(_e) => return Err(APIError::err(&self.op, "couldnt_like_comment"))?,
270       };
271     }
272
273     // Have to refetch the comment to get the current state
274     let liked_comment = CommentView::read(&conn, data.comment_id, Some(user_id))?;
275
276     Ok(CommentResponse {
277       op: self.op.to_string(),
278       comment: liked_comment,
279     })
280   }
281 }