]> Untitled Git - lemmy.git/blob - server/src/db/comment.rs
Adding emoji support
[lemmy.git] / server / src / db / comment.rs
1 use 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 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 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 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 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 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 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 schema::comment_like::dsl::*;
106     diesel::delete(comment_like
107                    .filter(comment_id.eq(comment_like_form.comment_id))
108                    .filter(user_id.eq(comment_like_form.user_id)))
109       .execute(conn)
110   }
111 }
112
113 impl CommentLike {
114   pub fn from_post(conn: &PgConnection, post_id_from: i32) -> Result<Vec<Self>, Error> {
115     use schema::comment_like::dsl::*;
116     comment_like
117       .filter(post_id.eq(post_id_from))
118       .load::<Self>(conn) 
119   }
120 }
121
122 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
123 #[belongs_to(Comment)]
124 #[table_name = "comment_saved"]
125 pub struct CommentSaved {
126   pub id: i32,
127   pub comment_id: i32,
128   pub user_id: i32,
129   pub published: chrono::NaiveDateTime,
130 }
131
132 #[derive(Insertable, AsChangeset, Clone)]
133 #[table_name="comment_saved"]
134 pub struct CommentSavedForm {
135   pub comment_id: i32,
136   pub user_id: i32,
137 }
138
139 impl Saveable <CommentSavedForm> for CommentSaved {
140   fn save(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<Self, Error> {
141     use schema::comment_saved::dsl::*;
142     insert_into(comment_saved)
143       .values(comment_saved_form)
144       .get_result::<Self>(conn)
145   }
146   fn unsave(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<usize, Error> {
147     use schema::comment_saved::dsl::*;
148     diesel::delete(comment_saved
149       .filter(comment_id.eq(comment_saved_form.comment_id))
150       .filter(user_id.eq(comment_saved_form.user_id)))
151       .execute(conn)
152   }
153 }
154
155 #[cfg(test)]
156 mod tests {
157   use super::*;
158   use super::super::post::*;
159   use super::super::community::*;
160   use super::super::user::*;
161  #[test]
162   fn test_crud() {
163     let conn = establish_connection();
164
165     let new_user = UserForm {
166       name: "terry".into(),
167       fedi_name: "rrf".into(),
168       preferred_username: None,
169       password_encrypted: "nope".into(),
170       email: None,
171       admin: false,
172       banned: false,
173       updated: None
174     };
175
176     let inserted_user = User_::create(&conn, &new_user).unwrap();
177
178     let new_community = CommunityForm {
179       name: "test community".to_string(),
180       title: "nada".to_owned(),
181       description: None,
182       category_id: 1,
183       creator_id: inserted_user.id,
184       removed: None,
185       deleted: None,
186       updated: None
187     };
188
189     let inserted_community = Community::create(&conn, &new_community).unwrap();
190     
191     let new_post = PostForm {
192       name: "A test post".into(),
193       creator_id: inserted_user.id,
194       url: None,
195       body: None,
196       community_id: inserted_community.id,
197       removed: None,
198       deleted: None,
199       locked: None,
200       updated: None
201     };
202
203     let inserted_post = Post::create(&conn, &new_post).unwrap();
204
205     let comment_form = CommentForm {
206       content: "A test comment".into(),
207       creator_id: inserted_user.id,
208       post_id: inserted_post.id,
209       removed: None,
210       deleted: None,
211       read: None,
212       parent_id: None,
213       updated: None
214     };
215
216     let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
217
218     let expected_comment = Comment {
219       id: inserted_comment.id,
220       content: "A test comment".into(),
221       creator_id: inserted_user.id,
222       post_id: inserted_post.id,
223       removed: false,
224       deleted: false,
225       read: false,
226       parent_id: None,
227       published: inserted_comment.published,
228       updated: None
229     };
230     
231     let child_comment_form = CommentForm {
232       content: "A child comment".into(),
233       creator_id: inserted_user.id,
234       post_id: inserted_post.id,
235       parent_id: Some(inserted_comment.id),
236       removed: None,
237       deleted: None,
238       read: None,
239       updated: None
240     };
241
242     let inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap();
243
244     // Comment Like
245     let comment_like_form = CommentLikeForm {
246       comment_id: inserted_comment.id,
247       post_id: inserted_post.id,
248       user_id: inserted_user.id,
249       score: 1
250     };
251
252     let inserted_comment_like = CommentLike::like(&conn, &comment_like_form).unwrap();
253
254     let expected_comment_like = CommentLike {
255       id: inserted_comment_like.id,
256       comment_id: inserted_comment.id,
257       post_id: inserted_post.id,
258       user_id: inserted_user.id,
259       published: inserted_comment_like.published,
260       score: 1
261     };
262     
263     // Comment Saved
264     let comment_saved_form = CommentSavedForm {
265       comment_id: inserted_comment.id,
266       user_id: inserted_user.id,
267     };
268
269     let inserted_comment_saved = CommentSaved::save(&conn, &comment_saved_form).unwrap();
270
271     let expected_comment_saved = CommentSaved {
272       id: inserted_comment_saved.id,
273       comment_id: inserted_comment.id,
274       user_id: inserted_user.id,
275       published: inserted_comment_saved.published,
276     };
277
278     let read_comment = Comment::read(&conn, inserted_comment.id).unwrap();
279     let updated_comment = Comment::update(&conn, inserted_comment.id, &comment_form).unwrap();
280     let like_removed = CommentLike::remove(&conn, &comment_like_form).unwrap();
281     let saved_removed = CommentSaved::unsave(&conn, &comment_saved_form).unwrap();
282     let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
283     Comment::delete(&conn, inserted_child_comment.id).unwrap();
284     Post::delete(&conn, inserted_post.id).unwrap();
285     Community::delete(&conn, inserted_community.id).unwrap();
286     User_::delete(&conn, inserted_user.id).unwrap();
287
288     assert_eq!(expected_comment, read_comment);
289     assert_eq!(expected_comment, inserted_comment);
290     assert_eq!(expected_comment, updated_comment);
291     assert_eq!(expected_comment_like, inserted_comment_like);
292     assert_eq!(expected_comment_saved, inserted_comment_saved);
293     assert_eq!(expected_comment.id, inserted_child_comment.parent_id.unwrap());
294     assert_eq!(1, like_removed);
295     assert_eq!(1, saved_removed);
296     assert_eq!(1, num_deleted);
297
298   }
299 }