]> Untitled Git - lemmy.git/blob - server/src/db/comment.rs
Adding emoji support.
[lemmy.git] / server / src / db / comment.rs
1 use crate::schema::{comment, comment_like, comment_saved};
2 use super::*;
3 use super::post::Post;
4
5 // WITH RECURSIVE MyTree AS (
6 //     SELECT * FROM comment WHERE parent_id IS NULL
7 //     UNION ALL
8 //     SELECT m.* FROM comment AS m JOIN MyTree AS t ON m.parent_id = t.id
9 // )
10 // SELECT * FROM MyTree;
11
12 #[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
13 #[belongs_to(Post)]
14 #[table_name="comment"]
15 pub struct Comment {
16   pub id: i32,
17   pub creator_id: i32,
18   pub post_id: i32,
19   pub parent_id: Option<i32>,
20   pub content: String,
21   pub removed: bool,
22   pub read: bool,
23   pub published: chrono::NaiveDateTime,
24   pub updated: Option<chrono::NaiveDateTime>,
25   pub deleted: bool,
26 }
27
28 #[derive(Insertable, AsChangeset, Clone)]
29 #[table_name="comment"]
30 pub struct CommentForm {
31   pub creator_id: i32,
32   pub post_id: i32,
33   pub parent_id: Option<i32>,
34   pub content: String,
35   pub removed: Option<bool>,
36   pub read: Option<bool>,
37   pub updated: Option<chrono::NaiveDateTime>,
38   pub deleted: Option<bool>,
39 }
40
41 impl Crud<CommentForm> for Comment {
42   fn read(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
43     use crate::schema::comment::dsl::*;
44     comment.find(comment_id)
45       .first::<Self>(conn)
46   }
47
48   fn delete(conn: &PgConnection, comment_id: i32) -> Result<usize, Error> {
49     use crate::schema::comment::dsl::*;
50     diesel::delete(comment.find(comment_id))
51       .execute(conn)
52   }
53
54   fn create(conn: &PgConnection, comment_form: &CommentForm) -> Result<Self, Error> {
55     use crate::schema::comment::dsl::*;
56     insert_into(comment)
57       .values(comment_form)
58       .get_result::<Self>(conn)
59   }
60
61   fn update(conn: &PgConnection, comment_id: i32, comment_form: &CommentForm) -> Result<Self, Error> {
62     use crate::schema::comment::dsl::*;
63     diesel::update(comment.find(comment_id))
64       .set(comment_form)
65       .get_result::<Self>(conn)
66   }
67 }
68
69 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Clone)]
70 #[belongs_to(Comment)]
71 #[table_name = "comment_like"]
72 pub struct CommentLike {
73   pub id: i32,
74   pub user_id: i32,
75   pub comment_id: i32,
76   pub post_id: i32,
77   pub score: i16,
78   pub published: chrono::NaiveDateTime,
79 }
80
81 #[derive(Insertable, AsChangeset, Clone)]
82 #[table_name="comment_like"]
83 pub struct CommentLikeForm {
84   pub user_id: i32,
85   pub comment_id: i32,
86   pub post_id: i32,
87   pub score: i16
88 }
89
90 impl Likeable <CommentLikeForm> for CommentLike {
91   fn read(conn: &PgConnection, comment_id_from: i32) -> Result<Vec<Self>, Error> {
92     use crate::schema::comment_like::dsl::*;
93     comment_like
94       .filter(comment_id.eq(comment_id_from))
95       .load::<Self>(conn) 
96   }
97
98   fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
99     use crate::schema::comment_like::dsl::*;
100     insert_into(comment_like)
101       .values(comment_like_form)
102       .get_result::<Self>(conn)
103   }
104   fn remove(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<usize, Error> {
105     use crate::schema::comment_like::dsl::*;
106     diesel::delete(
107       comment_like
108       .filter(comment_id.eq(comment_like_form.comment_id))
109       .filter(user_id.eq(comment_like_form.user_id)))
110       .execute(conn)
111   }
112 }
113
114 impl CommentLike {
115   pub fn from_post(conn: &PgConnection, post_id_from: i32) -> Result<Vec<Self>, Error> {
116     use crate::schema::comment_like::dsl::*;
117     comment_like
118       .filter(post_id.eq(post_id_from))
119       .load::<Self>(conn) 
120   }
121 }
122
123 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
124 #[belongs_to(Comment)]
125 #[table_name = "comment_saved"]
126 pub struct CommentSaved {
127   pub id: i32,
128   pub comment_id: i32,
129   pub user_id: i32,
130   pub published: chrono::NaiveDateTime,
131 }
132
133 #[derive(Insertable, AsChangeset, Clone)]
134 #[table_name="comment_saved"]
135 pub struct CommentSavedForm {
136   pub comment_id: i32,
137   pub user_id: i32,
138 }
139
140 impl Saveable <CommentSavedForm> for CommentSaved {
141   fn save(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<Self, Error> {
142     use crate::schema::comment_saved::dsl::*;
143     insert_into(comment_saved)
144       .values(comment_saved_form)
145       .get_result::<Self>(conn)
146   }
147   fn unsave(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<usize, Error> {
148     use crate::schema::comment_saved::dsl::*;
149     diesel::delete(comment_saved
150       .filter(comment_id.eq(comment_saved_form.comment_id))
151       .filter(user_id.eq(comment_saved_form.user_id)))
152       .execute(conn)
153   }
154 }
155
156 #[cfg(test)]
157 mod tests {
158   use super::*;
159   use super::super::post::*;
160   use super::super::community::*;
161   use super::super::user::*;
162  #[test]
163   fn test_crud() {
164     let conn = establish_connection();
165
166     let new_user = UserForm {
167       name: "terry".into(),
168       fedi_name: "rrf".into(),
169       preferred_username: None,
170       password_encrypted: "nope".into(),
171       email: None,
172       admin: false,
173       banned: false,
174       updated: None,
175       show_nsfw: false,
176     };
177
178     let inserted_user = User_::create(&conn, &new_user).unwrap();
179
180     let new_community = CommunityForm {
181       name: "test community".to_string(),
182       title: "nada".to_owned(),
183       description: None,
184       category_id: 1,
185       creator_id: inserted_user.id,
186       removed: None,
187       deleted: None,
188       updated: None,
189       nsfw: false,
190     };
191
192     let inserted_community = Community::create(&conn, &new_community).unwrap();
193     
194     let new_post = PostForm {
195       name: "A test post".into(),
196       creator_id: inserted_user.id,
197       url: None,
198       body: None,
199       community_id: inserted_community.id,
200       removed: None,
201       deleted: None,
202       locked: None,
203       updated: None,
204       nsfw: false,
205     };
206
207     let inserted_post = Post::create(&conn, &new_post).unwrap();
208
209     let comment_form = CommentForm {
210       content: "A test comment".into(),
211       creator_id: inserted_user.id,
212       post_id: inserted_post.id,
213       removed: None,
214       deleted: None,
215       read: None,
216       parent_id: None,
217       updated: None
218     };
219
220     let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
221
222     let expected_comment = Comment {
223       id: inserted_comment.id,
224       content: "A test comment".into(),
225       creator_id: inserted_user.id,
226       post_id: inserted_post.id,
227       removed: false,
228       deleted: false,
229       read: false,
230       parent_id: None,
231       published: inserted_comment.published,
232       updated: None
233     };
234     
235     let child_comment_form = CommentForm {
236       content: "A child comment".into(),
237       creator_id: inserted_user.id,
238       post_id: inserted_post.id,
239       parent_id: Some(inserted_comment.id),
240       removed: None,
241       deleted: None,
242       read: None,
243       updated: None
244     };
245
246     let inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap();
247
248     // Comment Like
249     let comment_like_form = CommentLikeForm {
250       comment_id: inserted_comment.id,
251       post_id: inserted_post.id,
252       user_id: inserted_user.id,
253       score: 1
254     };
255
256     let inserted_comment_like = CommentLike::like(&conn, &comment_like_form).unwrap();
257
258     let expected_comment_like = CommentLike {
259       id: inserted_comment_like.id,
260       comment_id: inserted_comment.id,
261       post_id: inserted_post.id,
262       user_id: inserted_user.id,
263       published: inserted_comment_like.published,
264       score: 1
265     };
266     
267     // Comment Saved
268     let comment_saved_form = CommentSavedForm {
269       comment_id: inserted_comment.id,
270       user_id: inserted_user.id,
271     };
272
273     let inserted_comment_saved = CommentSaved::save(&conn, &comment_saved_form).unwrap();
274
275     let expected_comment_saved = CommentSaved {
276       id: inserted_comment_saved.id,
277       comment_id: inserted_comment.id,
278       user_id: inserted_user.id,
279       published: inserted_comment_saved.published,
280     };
281
282     let read_comment = Comment::read(&conn, inserted_comment.id).unwrap();
283     let updated_comment = Comment::update(&conn, inserted_comment.id, &comment_form).unwrap();
284     let like_removed = CommentLike::remove(&conn, &comment_like_form).unwrap();
285     let saved_removed = CommentSaved::unsave(&conn, &comment_saved_form).unwrap();
286     let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
287     Comment::delete(&conn, inserted_child_comment.id).unwrap();
288     Post::delete(&conn, inserted_post.id).unwrap();
289     Community::delete(&conn, inserted_community.id).unwrap();
290     User_::delete(&conn, inserted_user.id).unwrap();
291
292     assert_eq!(expected_comment, read_comment);
293     assert_eq!(expected_comment, inserted_comment);
294     assert_eq!(expected_comment, updated_comment);
295     assert_eq!(expected_comment_like, inserted_comment_like);
296     assert_eq!(expected_comment_saved, inserted_comment_saved);
297     assert_eq!(expected_comment.id, inserted_child_comment.parent_id.unwrap());
298     assert_eq!(1, like_removed);
299     assert_eq!(1, saved_removed);
300     assert_eq!(1, num_deleted);
301
302   }
303 }