]> Untitled Git - lemmy.git/blob - crates/db_queries/src/source/post.rs
Add show_read_posts filter. Fixes #1561
[lemmy.git] / crates / db_queries / src / source / post.rs
1 use crate::{ApubObject, Crud, Likeable, Readable, Saveable};
2 use diesel::{dsl::*, result::Error, *};
3 use lemmy_db_schema::{
4   naive_now,
5   source::post::{
6     Post,
7     PostForm,
8     PostLike,
9     PostLikeForm,
10     PostRead,
11     PostReadForm,
12     PostSaved,
13     PostSavedForm,
14   },
15   CommunityId,
16   DbUrl,
17   PersonId,
18   PostId,
19 };
20
21 impl Crud<PostForm, PostId> for Post {
22   fn read(conn: &PgConnection, post_id: PostId) -> Result<Self, Error> {
23     use lemmy_db_schema::schema::post::dsl::*;
24     post.find(post_id).first::<Self>(conn)
25   }
26
27   fn delete(conn: &PgConnection, post_id: PostId) -> Result<usize, Error> {
28     use lemmy_db_schema::schema::post::dsl::*;
29     diesel::delete(post.find(post_id)).execute(conn)
30   }
31
32   fn create(conn: &PgConnection, new_post: &PostForm) -> Result<Self, Error> {
33     use lemmy_db_schema::schema::post::dsl::*;
34     insert_into(post).values(new_post).get_result::<Self>(conn)
35   }
36
37   fn update(conn: &PgConnection, post_id: PostId, new_post: &PostForm) -> Result<Self, Error> {
38     use lemmy_db_schema::schema::post::dsl::*;
39     diesel::update(post.find(post_id))
40       .set(new_post)
41       .get_result::<Self>(conn)
42   }
43 }
44
45 pub trait Post_ {
46   //fn read(conn: &PgConnection, post_id: i32) -> Result<Post, Error>;
47   fn list_for_community(
48     conn: &PgConnection,
49     the_community_id: CommunityId,
50   ) -> Result<Vec<Post>, Error>;
51   fn update_ap_id(conn: &PgConnection, post_id: PostId, apub_id: DbUrl) -> Result<Post, Error>;
52   fn permadelete_for_creator(
53     conn: &PgConnection,
54     for_creator_id: PersonId,
55   ) -> Result<Vec<Post>, Error>;
56   fn update_deleted(conn: &PgConnection, post_id: PostId, new_deleted: bool)
57     -> Result<Post, Error>;
58   fn update_removed(conn: &PgConnection, post_id: PostId, new_removed: bool)
59     -> Result<Post, Error>;
60   fn update_removed_for_creator(
61     conn: &PgConnection,
62     for_creator_id: PersonId,
63     for_community_id: Option<CommunityId>,
64     new_removed: bool,
65   ) -> Result<Vec<Post>, Error>;
66   fn update_locked(conn: &PgConnection, post_id: PostId, new_locked: bool) -> Result<Post, Error>;
67   fn update_stickied(
68     conn: &PgConnection,
69     post_id: PostId,
70     new_stickied: bool,
71   ) -> Result<Post, Error>;
72   fn is_post_creator(person_id: PersonId, post_creator_id: PersonId) -> bool;
73 }
74
75 impl Post_ for Post {
76   fn list_for_community(
77     conn: &PgConnection,
78     the_community_id: CommunityId,
79   ) -> Result<Vec<Self>, Error> {
80     use lemmy_db_schema::schema::post::dsl::*;
81     post
82       .filter(community_id.eq(the_community_id))
83       .then_order_by(published.desc())
84       .then_order_by(stickied.desc())
85       .limit(20)
86       .load::<Self>(conn)
87   }
88
89   fn update_ap_id(conn: &PgConnection, post_id: PostId, apub_id: DbUrl) -> Result<Self, Error> {
90     use lemmy_db_schema::schema::post::dsl::*;
91
92     diesel::update(post.find(post_id))
93       .set(ap_id.eq(apub_id))
94       .get_result::<Self>(conn)
95   }
96
97   fn permadelete_for_creator(
98     conn: &PgConnection,
99     for_creator_id: PersonId,
100   ) -> Result<Vec<Self>, Error> {
101     use lemmy_db_schema::schema::post::dsl::*;
102
103     let perma_deleted = "*Permananently Deleted*";
104     let perma_deleted_url = "https://deleted.com";
105
106     diesel::update(post.filter(creator_id.eq(for_creator_id)))
107       .set((
108         name.eq(perma_deleted),
109         url.eq(perma_deleted_url),
110         body.eq(perma_deleted),
111         deleted.eq(true),
112         updated.eq(naive_now()),
113       ))
114       .get_results::<Self>(conn)
115   }
116
117   fn update_deleted(
118     conn: &PgConnection,
119     post_id: PostId,
120     new_deleted: bool,
121   ) -> Result<Self, Error> {
122     use lemmy_db_schema::schema::post::dsl::*;
123     diesel::update(post.find(post_id))
124       .set((deleted.eq(new_deleted), updated.eq(naive_now())))
125       .get_result::<Self>(conn)
126   }
127
128   fn update_removed(
129     conn: &PgConnection,
130     post_id: PostId,
131     new_removed: bool,
132   ) -> Result<Self, Error> {
133     use lemmy_db_schema::schema::post::dsl::*;
134     diesel::update(post.find(post_id))
135       .set((removed.eq(new_removed), updated.eq(naive_now())))
136       .get_result::<Self>(conn)
137   }
138
139   fn update_removed_for_creator(
140     conn: &PgConnection,
141     for_creator_id: PersonId,
142     for_community_id: Option<CommunityId>,
143     new_removed: bool,
144   ) -> Result<Vec<Self>, Error> {
145     use lemmy_db_schema::schema::post::dsl::*;
146
147     let mut update = diesel::update(post).into_boxed();
148     update = update.filter(creator_id.eq(for_creator_id));
149
150     if let Some(for_community_id) = for_community_id {
151       update = update.filter(community_id.eq(for_community_id));
152     }
153
154     update
155       .set((removed.eq(new_removed), updated.eq(naive_now())))
156       .get_results::<Self>(conn)
157   }
158
159   fn update_locked(conn: &PgConnection, post_id: PostId, new_locked: bool) -> Result<Self, Error> {
160     use lemmy_db_schema::schema::post::dsl::*;
161     diesel::update(post.find(post_id))
162       .set(locked.eq(new_locked))
163       .get_result::<Self>(conn)
164   }
165
166   fn update_stickied(
167     conn: &PgConnection,
168     post_id: PostId,
169     new_stickied: bool,
170   ) -> Result<Self, Error> {
171     use lemmy_db_schema::schema::post::dsl::*;
172     diesel::update(post.find(post_id))
173       .set(stickied.eq(new_stickied))
174       .get_result::<Self>(conn)
175   }
176
177   fn is_post_creator(person_id: PersonId, post_creator_id: PersonId) -> bool {
178     person_id == post_creator_id
179   }
180 }
181
182 impl ApubObject<PostForm> for Post {
183   fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
184     use lemmy_db_schema::schema::post::dsl::*;
185     post.filter(ap_id.eq(object_id)).first::<Self>(conn)
186   }
187
188   fn upsert(conn: &PgConnection, post_form: &PostForm) -> Result<Post, Error> {
189     use lemmy_db_schema::schema::post::dsl::*;
190     insert_into(post)
191       .values(post_form)
192       .on_conflict(ap_id)
193       .do_update()
194       .set(post_form)
195       .get_result::<Self>(conn)
196   }
197 }
198
199 impl Likeable<PostLikeForm, PostId> for PostLike {
200   fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<Self, Error> {
201     use lemmy_db_schema::schema::post_like::dsl::*;
202     insert_into(post_like)
203       .values(post_like_form)
204       .on_conflict((post_id, person_id))
205       .do_update()
206       .set(post_like_form)
207       .get_result::<Self>(conn)
208   }
209   fn remove(conn: &PgConnection, person_id: PersonId, post_id: PostId) -> Result<usize, Error> {
210     use lemmy_db_schema::schema::post_like::dsl;
211     diesel::delete(
212       dsl::post_like
213         .filter(dsl::post_id.eq(post_id))
214         .filter(dsl::person_id.eq(person_id)),
215     )
216     .execute(conn)
217   }
218 }
219
220 impl Saveable<PostSavedForm> for PostSaved {
221   fn save(conn: &PgConnection, post_saved_form: &PostSavedForm) -> Result<Self, Error> {
222     use lemmy_db_schema::schema::post_saved::dsl::*;
223     insert_into(post_saved)
224       .values(post_saved_form)
225       .on_conflict((post_id, person_id))
226       .do_update()
227       .set(post_saved_form)
228       .get_result::<Self>(conn)
229   }
230   fn unsave(conn: &PgConnection, post_saved_form: &PostSavedForm) -> Result<usize, Error> {
231     use lemmy_db_schema::schema::post_saved::dsl::*;
232     diesel::delete(
233       post_saved
234         .filter(post_id.eq(post_saved_form.post_id))
235         .filter(person_id.eq(post_saved_form.person_id)),
236     )
237     .execute(conn)
238   }
239 }
240
241 impl Readable<PostReadForm> for PostRead {
242   fn mark_as_read(conn: &PgConnection, post_read_form: &PostReadForm) -> Result<Self, Error> {
243     use lemmy_db_schema::schema::post_read::dsl::*;
244     insert_into(post_read)
245       .values(post_read_form)
246       .on_conflict((post_id, person_id))
247       .do_update()
248       .set(post_read_form)
249       .get_result::<Self>(conn)
250   }
251
252   fn mark_as_unread(conn: &PgConnection, post_read_form: &PostReadForm) -> Result<usize, Error> {
253     use lemmy_db_schema::schema::post_read::dsl::*;
254     diesel::delete(
255       post_read
256         .filter(post_id.eq(post_read_form.post_id))
257         .filter(person_id.eq(post_read_form.person_id)),
258     )
259     .execute(conn)
260   }
261 }
262
263 #[cfg(test)]
264 mod tests {
265   use crate::{establish_unpooled_connection, source::post::*};
266   use lemmy_db_schema::source::{
267     community::{Community, CommunityForm},
268     person::*,
269   };
270   use serial_test::serial;
271
272   #[test]
273   #[serial]
274   fn test_crud() {
275     let conn = establish_unpooled_connection();
276
277     let new_person = PersonForm {
278       name: "jim".into(),
279       ..PersonForm::default()
280     };
281
282     let inserted_person = Person::create(&conn, &new_person).unwrap();
283
284     let new_community = CommunityForm {
285       name: "test community_3".to_string(),
286       title: "nada".to_owned(),
287       ..CommunityForm::default()
288     };
289
290     let inserted_community = Community::create(&conn, &new_community).unwrap();
291
292     let new_post = PostForm {
293       name: "A test post".into(),
294       creator_id: inserted_person.id,
295       community_id: inserted_community.id,
296       ..PostForm::default()
297     };
298
299     let inserted_post = Post::create(&conn, &new_post).unwrap();
300
301     let expected_post = Post {
302       id: inserted_post.id,
303       name: "A test post".into(),
304       url: None,
305       body: None,
306       creator_id: inserted_person.id,
307       community_id: inserted_community.id,
308       published: inserted_post.published,
309       removed: false,
310       locked: false,
311       stickied: false,
312       nsfw: false,
313       deleted: false,
314       updated: None,
315       embed_title: None,
316       embed_description: None,
317       embed_html: None,
318       thumbnail_url: None,
319       ap_id: inserted_post.ap_id.to_owned(),
320       local: true,
321     };
322
323     // Post Like
324     let post_like_form = PostLikeForm {
325       post_id: inserted_post.id,
326       person_id: inserted_person.id,
327       score: 1,
328     };
329
330     let inserted_post_like = PostLike::like(&conn, &post_like_form).unwrap();
331
332     let expected_post_like = PostLike {
333       id: inserted_post_like.id,
334       post_id: inserted_post.id,
335       person_id: inserted_person.id,
336       published: inserted_post_like.published,
337       score: 1,
338     };
339
340     // Post Save
341     let post_saved_form = PostSavedForm {
342       post_id: inserted_post.id,
343       person_id: inserted_person.id,
344     };
345
346     let inserted_post_saved = PostSaved::save(&conn, &post_saved_form).unwrap();
347
348     let expected_post_saved = PostSaved {
349       id: inserted_post_saved.id,
350       post_id: inserted_post.id,
351       person_id: inserted_person.id,
352       published: inserted_post_saved.published,
353     };
354
355     // Post Read
356     let post_read_form = PostReadForm {
357       post_id: inserted_post.id,
358       person_id: inserted_person.id,
359     };
360
361     let inserted_post_read = PostRead::mark_as_read(&conn, &post_read_form).unwrap();
362
363     let expected_post_read = PostRead {
364       id: inserted_post_read.id,
365       post_id: inserted_post.id,
366       person_id: inserted_person.id,
367       published: inserted_post_read.published,
368     };
369
370     let read_post = Post::read(&conn, inserted_post.id).unwrap();
371     let updated_post = Post::update(&conn, inserted_post.id, &new_post).unwrap();
372     let like_removed = PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
373     let saved_removed = PostSaved::unsave(&conn, &post_saved_form).unwrap();
374     let read_removed = PostRead::mark_as_unread(&conn, &post_read_form).unwrap();
375     let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
376     Community::delete(&conn, inserted_community.id).unwrap();
377     Person::delete(&conn, inserted_person.id).unwrap();
378
379     assert_eq!(expected_post, read_post);
380     assert_eq!(expected_post, inserted_post);
381     assert_eq!(expected_post, updated_post);
382     assert_eq!(expected_post_like, inserted_post_like);
383     assert_eq!(expected_post_saved, inserted_post_saved);
384     assert_eq!(expected_post_read, inserted_post_read);
385     assert_eq!(1, like_removed);
386     assert_eq!(1, saved_removed);
387     assert_eq!(1, read_removed);
388     assert_eq!(1, num_deleted);
389   }
390 }