]> Untitled Git - lemmy.git/blob - crates/db_views_actor/src/person_view.rs
Diesel 2.0.0 upgrade (#2452)
[lemmy.git] / crates / db_views_actor / src / person_view.rs
1 use crate::structs::PersonViewSafe;
2 use diesel::{dsl::*, result::Error, *};
3 use lemmy_db_schema::{
4   aggregates::structs::PersonAggregates,
5   newtypes::PersonId,
6   schema::{person, person_aggregates},
7   source::person::{Person, PersonSafe},
8   traits::{ToSafe, ViewToVec},
9   utils::{fuzzy_search, limit_and_offset},
10   SortType,
11 };
12 use typed_builder::TypedBuilder;
13
14 type PersonViewSafeTuple = (PersonSafe, PersonAggregates);
15
16 impl PersonViewSafe {
17   pub fn read(conn: &mut PgConnection, person_id: PersonId) -> Result<Self, Error> {
18     let (person, counts) = person::table
19       .find(person_id)
20       .inner_join(person_aggregates::table)
21       .select((Person::safe_columns_tuple(), person_aggregates::all_columns))
22       .first::<PersonViewSafeTuple>(conn)?;
23     Ok(Self { person, counts })
24   }
25
26   pub fn admins(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
27     let admins = person::table
28       .inner_join(person_aggregates::table)
29       .select((Person::safe_columns_tuple(), person_aggregates::all_columns))
30       .filter(person::admin.eq(true))
31       .order_by(person::published)
32       .load::<PersonViewSafeTuple>(conn)?;
33
34     Ok(Self::from_tuple_to_vec(admins))
35   }
36
37   pub fn banned(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
38     let banned = person::table
39       .inner_join(person_aggregates::table)
40       .select((Person::safe_columns_tuple(), person_aggregates::all_columns))
41       .filter(
42         person::banned.eq(true).and(
43           person::ban_expires
44             .is_null()
45             .or(person::ban_expires.gt(now)),
46         ),
47       )
48       .load::<PersonViewSafeTuple>(conn)?;
49
50     Ok(Self::from_tuple_to_vec(banned))
51   }
52 }
53
54 #[derive(TypedBuilder)]
55 #[builder(field_defaults(default))]
56 pub struct PersonQuery<'a> {
57   #[builder(!default)]
58   conn: &'a mut PgConnection,
59   sort: Option<SortType>,
60   search_term: Option<String>,
61   page: Option<i64>,
62   limit: Option<i64>,
63 }
64
65 impl<'a> PersonQuery<'a> {
66   pub fn list(self) -> Result<Vec<PersonViewSafe>, Error> {
67     let mut query = person::table
68       .inner_join(person_aggregates::table)
69       .select((Person::safe_columns_tuple(), person_aggregates::all_columns))
70       .into_boxed();
71
72     if let Some(search_term) = self.search_term {
73       let searcher = fuzzy_search(&search_term);
74       query = query
75         .filter(person::name.ilike(searcher.to_owned()))
76         .or_filter(person::display_name.ilike(searcher));
77     }
78
79     query = match self.sort.unwrap_or(SortType::Hot) {
80       SortType::Hot => query
81         .order_by(person_aggregates::comment_score.desc())
82         .then_order_by(person::published.desc()),
83       SortType::Active => query
84         .order_by(person_aggregates::comment_score.desc())
85         .then_order_by(person::published.desc()),
86       SortType::New | SortType::MostComments | SortType::NewComments => {
87         query.order_by(person::published.desc())
88       }
89       SortType::Old => query.order_by(person::published.asc()),
90       SortType::TopAll => query.order_by(person_aggregates::comment_score.desc()),
91       SortType::TopYear => query
92         .filter(person::published.gt(now - 1.years()))
93         .order_by(person_aggregates::comment_score.desc()),
94       SortType::TopMonth => query
95         .filter(person::published.gt(now - 1.months()))
96         .order_by(person_aggregates::comment_score.desc()),
97       SortType::TopWeek => query
98         .filter(person::published.gt(now - 1.weeks()))
99         .order_by(person_aggregates::comment_score.desc()),
100       SortType::TopDay => query
101         .filter(person::published.gt(now - 1.days()))
102         .order_by(person_aggregates::comment_score.desc()),
103     };
104
105     let (limit, offset) = limit_and_offset(self.page, self.limit)?;
106     query = query.limit(limit).offset(offset);
107
108     let res = query.load::<PersonViewSafeTuple>(self.conn)?;
109
110     Ok(PersonViewSafe::from_tuple_to_vec(res))
111   }
112 }
113
114 impl ViewToVec for PersonViewSafe {
115   type DbTuple = PersonViewSafeTuple;
116   fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
117     items
118       .into_iter()
119       .map(|a| Self {
120         person: a.0,
121         counts: a.1,
122       })
123       .collect::<Vec<Self>>()
124   }
125 }