1 use super::post_view::post_mview::BoxedQuery;
5 // The faked schema since diesel doesn't do views
10 url -> Nullable<Text>,
11 body -> Nullable<Text>,
16 published -> Timestamp,
17 updated -> Nullable<Timestamp>,
21 banned_from_community -> Bool,
23 creator_name -> Varchar,
24 creator_avatar -> Nullable<Text>,
25 community_name -> Varchar,
26 community_removed -> Bool,
27 community_deleted -> Bool,
28 community_nsfw -> Bool,
29 number_of_comments -> BigInt,
34 user_id -> Nullable<Int4>,
35 my_vote -> Nullable<Int4>,
36 subscribed -> Nullable<Bool>,
37 read -> Nullable<Bool>,
38 saved -> Nullable<Bool>,
43 Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
45 #[table_name = "post_view"]
49 pub url: Option<String>,
50 pub body: Option<String>,
52 pub community_id: i32,
55 pub published: chrono::NaiveDateTime,
56 pub updated: Option<chrono::NaiveDateTime>,
60 pub banned_from_community: bool,
62 pub creator_name: String,
63 pub creator_avatar: Option<String>,
64 pub community_name: String,
65 pub community_removed: bool,
66 pub community_deleted: bool,
67 pub community_nsfw: bool,
68 pub number_of_comments: i64,
73 pub user_id: Option<i32>,
74 pub my_vote: Option<i32>,
75 pub subscribed: Option<bool>,
76 pub read: Option<bool>,
77 pub saved: Option<bool>,
80 // The faked schema since diesel doesn't do views
85 url -> Nullable<Text>,
86 body -> Nullable<Text>,
91 published -> Timestamp,
92 updated -> Nullable<Timestamp>,
96 banned_from_community -> Bool,
98 creator_name -> Varchar,
99 creator_avatar -> Nullable<Text>,
100 community_name -> Varchar,
101 community_removed -> Bool,
102 community_deleted -> Bool,
103 community_nsfw -> Bool,
104 number_of_comments -> BigInt,
109 user_id -> Nullable<Int4>,
110 my_vote -> Nullable<Int4>,
111 subscribed -> Nullable<Bool>,
112 read -> Nullable<Bool>,
113 saved -> Nullable<Bool>,
117 pub struct PostQueryBuilder<'a> {
118 conn: &'a PgConnection,
119 query: BoxedQuery<'a, Pg>,
120 listing_type: ListingType,
122 my_user_id: Option<i32>,
123 for_creator_id: Option<i32>,
131 impl<'a> PostQueryBuilder<'a> {
132 pub fn create(conn: &'a PgConnection) -> Self {
133 use super::post_view::post_mview::dsl::*;
135 let query = post_mview.into_boxed();
141 for_creator_id: None,
142 listing_type: ListingType::All,
143 sort: &SortType::Hot,
152 pub fn listing_type(mut self, listing_type: ListingType) -> Self {
153 self.listing_type = listing_type;
157 pub fn sort(mut self, sort: &'a SortType) -> Self {
162 pub fn for_community_id<T: MaybeOptional<i32>>(mut self, for_community_id: T) -> Self {
163 use super::post_view::post_mview::dsl::*;
164 if let Some(for_community_id) = for_community_id.get_optional() {
165 self.query = self.query.filter(community_id.eq(for_community_id));
166 self.query = self.query.then_order_by(stickied.desc());
171 pub fn for_creator_id<T: MaybeOptional<i32>>(mut self, for_creator_id: T) -> Self {
172 if let Some(for_creator_id) = for_creator_id.get_optional() {
173 self.for_creator_id = Some(for_creator_id);
178 pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
179 use super::post_view::post_mview::dsl::*;
180 if let Some(search_term) = search_term.get_optional() {
181 self.query = self.query.filter(name.ilike(fuzzy_search(&search_term)));
186 pub fn url_search<T: MaybeOptional<String>>(mut self, url_search: T) -> Self {
187 use super::post_view::post_mview::dsl::*;
188 if let Some(url_search) = url_search.get_optional() {
189 self.query = self.query.filter(url.eq(url_search));
194 pub fn my_user_id<T: MaybeOptional<i32>>(mut self, my_user_id: T) -> Self {
195 self.my_user_id = my_user_id.get_optional();
199 pub fn show_nsfw(mut self, show_nsfw: bool) -> Self {
200 self.show_nsfw = show_nsfw;
204 pub fn saved_only(mut self, saved_only: bool) -> Self {
205 self.saved_only = saved_only;
209 pub fn unread_only(mut self, unread_only: bool) -> Self {
210 self.unread_only = unread_only;
214 pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
215 self.page = page.get_optional();
219 pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
220 self.limit = limit.get_optional();
224 pub fn list(self) -> Result<Vec<PostView>, Error> {
225 use super::post_view::post_mview::dsl::*;
227 let mut query = self.query;
229 if let ListingType::Subscribed = self.listing_type {
230 query = query.filter(subscribed.eq(true));
233 query = match self.sort {
234 SortType::Hot => query
235 .then_order_by(hot_rank.desc())
236 .then_order_by(published.desc()),
237 SortType::New => query.then_order_by(published.desc()),
238 SortType::TopAll => query.then_order_by(score.desc()),
239 SortType::TopYear => query
240 .filter(published.gt(now - 1.years()))
241 .then_order_by(score.desc()),
242 SortType::TopMonth => query
243 .filter(published.gt(now - 1.months()))
244 .then_order_by(score.desc()),
245 SortType::TopWeek => query
246 .filter(published.gt(now - 1.weeks()))
247 .then_order_by(score.desc()),
248 SortType::TopDay => query
249 .filter(published.gt(now - 1.days()))
250 .then_order_by(score.desc()),
253 // The view lets you pass a null user_id, if you're not logged in
254 query = if let Some(my_user_id) = self.my_user_id {
255 query.filter(user_id.eq(my_user_id))
257 query.filter(user_id.is_null())
260 // If its for a specific user, show the removed / deleted
261 if let Some(for_creator_id) = self.for_creator_id {
262 query = query.filter(creator_id.eq(for_creator_id));
265 .filter(removed.eq(false))
266 .filter(deleted.eq(false))
267 .filter(community_removed.eq(false))
268 .filter(community_deleted.eq(false));
273 .filter(nsfw.eq(false))
274 .filter(community_nsfw.eq(false));
277 // TODO these are wrong, bc they'll only show saved for your logged in user, not theirs
279 query = query.filter(saved.eq(true));
282 if self.unread_only {
283 query = query.filter(read.eq(false));
286 let (limit, offset) = limit_and_offset(self.page, self.limit);
290 .filter(removed.eq(false))
291 .filter(deleted.eq(false))
292 .filter(community_removed.eq(false))
293 .filter(community_deleted.eq(false));
295 query.load::<PostView>(self.conn)
303 my_user_id: Option<i32>,
304 ) -> Result<Self, Error> {
305 use super::post_view::post_view::dsl::*;
306 use diesel::prelude::*;
308 let mut query = post_view.into_boxed();
310 query = query.filter(id.eq(from_post_id));
312 if let Some(my_user_id) = my_user_id {
313 query = query.filter(user_id.eq(my_user_id));
315 query = query.filter(user_id.is_null());
318 query.first::<Self>(conn)
324 use super::super::community::*;
325 use super::super::post::*;
326 use super::super::user::*;
330 let conn = establish_unpooled_connection();
332 let user_name = "tegan".to_string();
333 let community_name = "test_community_3".to_string();
334 let post_name = "test post 3".to_string();
336 let new_user = UserForm {
337 name: user_name.to_owned(),
338 fedi_name: "rrf".into(),
339 preferred_username: None,
340 password_encrypted: "nope".into(),
342 matrix_user_id: None,
348 theme: "darkly".into(),
349 default_sort_type: SortType::Hot as i16,
350 default_listing_type: ListingType::Subscribed as i16,
351 lang: "browser".into(),
353 send_notifications_to_email: false,
356 let inserted_user = User_::create(&conn, &new_user).unwrap();
358 let new_community = CommunityForm {
359 name: community_name.to_owned(),
360 title: "nada".to_owned(),
362 creator_id: inserted_user.id,
370 let inserted_community = Community::create(&conn, &new_community).unwrap();
372 let new_post = PostForm {
373 name: post_name.to_owned(),
376 creator_id: inserted_user.id,
377 community_id: inserted_community.id,
386 let inserted_post = Post::create(&conn, &new_post).unwrap();
388 let post_like_form = PostLikeForm {
389 post_id: inserted_post.id,
390 user_id: inserted_user.id,
394 let inserted_post_like = PostLike::like(&conn, &post_like_form).unwrap();
396 let expected_post_like = PostLike {
397 id: inserted_post_like.id,
398 post_id: inserted_post.id,
399 user_id: inserted_user.id,
400 published: inserted_post_like.published,
404 let post_like_form = PostLikeForm {
405 post_id: inserted_post.id,
406 user_id: inserted_user.id,
410 // the non user version
411 let expected_post_listing_no_user = PostView {
414 id: inserted_post.id,
415 name: post_name.to_owned(),
418 creator_id: inserted_user.id,
419 creator_name: user_name.to_owned(),
420 creator_avatar: None,
422 banned_from_community: false,
423 community_id: inserted_community.id,
428 community_name: community_name.to_owned(),
429 community_removed: false,
430 community_deleted: false,
431 community_nsfw: false,
432 number_of_comments: 0,
437 published: inserted_post.published,
445 let expected_post_listing_with_user = PostView {
446 user_id: Some(inserted_user.id),
448 id: inserted_post.id,
456 creator_id: inserted_user.id,
457 creator_name: user_name,
458 creator_avatar: None,
460 banned_from_community: false,
461 community_id: inserted_community.id,
463 community_removed: false,
464 community_deleted: false,
465 community_nsfw: false,
466 number_of_comments: 0,
471 published: inserted_post.published,
479 let read_post_listings_with_user = PostQueryBuilder::create(&conn)
480 .listing_type(ListingType::Community)
481 .sort(&SortType::New)
482 .for_community_id(inserted_community.id)
483 .my_user_id(inserted_user.id)
487 let read_post_listings_no_user = PostQueryBuilder::create(&conn)
488 .listing_type(ListingType::Community)
489 .sort(&SortType::New)
490 .for_community_id(inserted_community.id)
494 let read_post_listing_no_user = PostView::read(&conn, inserted_post.id, None).unwrap();
495 let read_post_listing_with_user =
496 PostView::read(&conn, inserted_post.id, Some(inserted_user.id)).unwrap();
498 let like_removed = PostLike::remove(&conn, &post_like_form).unwrap();
499 let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
500 Community::delete(&conn, inserted_community.id).unwrap();
501 User_::delete(&conn, inserted_user.id).unwrap();
505 expected_post_listing_with_user,
506 read_post_listings_with_user[0]
508 assert_eq!(expected_post_listing_with_user, read_post_listing_with_user);
509 assert_eq!(1, read_post_listings_with_user.len());
512 assert_eq!(expected_post_listing_no_user, read_post_listings_no_user[0]);
513 assert_eq!(expected_post_listing_no_user, read_post_listing_no_user);
514 assert_eq!(1, read_post_listings_no_user.len());
516 // assert_eq!(expected_post, inserted_post);
517 // assert_eq!(expected_post, updated_post);
518 assert_eq!(expected_post_like, inserted_post_like);
519 assert_eq!(1, like_removed);
520 assert_eq!(1, num_deleted);