use super::user_view::user_mview::BoxedQuery; use crate::db::{fuzzy_search, limit_and_offset, MaybeOptional, SortType}; use diesel::{dsl::*, pg::Pg, result::Error, *}; use serde::{Deserialize, Serialize}; table! { user_view (id) { id -> Int4, actor_id -> Text, name -> Varchar, avatar -> Nullable, email -> Nullable, matrix_user_id -> Nullable, bio -> Nullable, local -> Bool, admin -> Bool, banned -> Bool, show_avatars -> Bool, send_notifications_to_email -> Bool, published -> Timestamp, number_of_posts -> BigInt, post_score -> BigInt, number_of_comments -> BigInt, comment_score -> BigInt, } } table! { user_mview (id) { id -> Int4, actor_id -> Text, name -> Varchar, avatar -> Nullable, email -> Nullable, matrix_user_id -> Nullable, bio -> Nullable, local -> Bool, admin -> Bool, banned -> Bool, show_avatars -> Bool, send_notifications_to_email -> Bool, published -> Timestamp, number_of_posts -> BigInt, post_score -> BigInt, number_of_comments -> BigInt, comment_score -> BigInt, } } #[derive( Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone, )] #[table_name = "user_view"] pub struct UserView { pub id: i32, pub actor_id: String, pub name: String, pub avatar: Option, pub email: Option, pub matrix_user_id: Option, pub bio: Option, pub local: bool, pub admin: bool, pub banned: bool, pub show_avatars: bool, pub send_notifications_to_email: bool, pub published: chrono::NaiveDateTime, pub number_of_posts: i64, pub post_score: i64, pub number_of_comments: i64, pub comment_score: i64, } pub struct UserQueryBuilder<'a> { conn: &'a PgConnection, query: BoxedQuery<'a, Pg>, sort: &'a SortType, page: Option, limit: Option, } impl<'a> UserQueryBuilder<'a> { pub fn create(conn: &'a PgConnection) -> Self { use super::user_view::user_mview::dsl::*; let query = user_mview.into_boxed(); UserQueryBuilder { conn, query, sort: &SortType::Hot, page: None, limit: None, } } pub fn sort(mut self, sort: &'a SortType) -> Self { self.sort = sort; self } pub fn search_term>(mut self, search_term: T) -> Self { use super::user_view::user_mview::dsl::*; if let Some(search_term) = search_term.get_optional() { self.query = self.query.filter(name.ilike(fuzzy_search(&search_term))); } self } pub fn page>(mut self, page: T) -> Self { self.page = page.get_optional(); self } pub fn limit>(mut self, limit: T) -> Self { self.limit = limit.get_optional(); self } pub fn list(self) -> Result, Error> { use super::user_view::user_mview::dsl::*; let mut query = self.query; query = match self.sort { SortType::Hot => query .order_by(comment_score.desc()) .then_order_by(published.desc()), SortType::New => query.order_by(published.desc()), SortType::TopAll => query.order_by(comment_score.desc()), SortType::TopYear => query .filter(published.gt(now - 1.years())) .order_by(comment_score.desc()), SortType::TopMonth => query .filter(published.gt(now - 1.months())) .order_by(comment_score.desc()), SortType::TopWeek => query .filter(published.gt(now - 1.weeks())) .order_by(comment_score.desc()), SortType::TopDay => query .filter(published.gt(now - 1.days())) .order_by(comment_score.desc()), }; let (limit, offset) = limit_and_offset(self.page, self.limit); query = query.limit(limit).offset(offset); query.load::(self.conn) } } impl UserView { pub fn read(conn: &PgConnection, from_user_id: i32) -> Result { use super::user_view::user_mview::dsl::*; user_mview.find(from_user_id).first::(conn) } pub fn admins(conn: &PgConnection) -> Result, Error> { use super::user_view::user_mview::dsl::*; user_mview.filter(admin.eq(true)).load::(conn) } pub fn banned(conn: &PgConnection) -> Result, Error> { use super::user_view::user_mview::dsl::*; user_mview.filter(banned.eq(true)).load::(conn) } }