]> Untitled Git - lemmy.git/blob - server/src/db/community_view.rs
Merge branch 'admin_settings' into dev
[lemmy.git] / server / src / db / community_view.rs
1 use super::community_view::community_mview::BoxedQuery;
2 use super::*;
3 use diesel::pg::Pg;
4
5 table! {
6   community_view (id) {
7     id -> Int4,
8     name -> Varchar,
9     title -> Varchar,
10     description -> Nullable<Text>,
11     category_id -> Int4,
12     creator_id -> Int4,
13     removed -> Bool,
14     published -> Timestamp,
15     updated -> Nullable<Timestamp>,
16     deleted -> Bool,
17     nsfw -> Bool,
18     creator_name -> Varchar,
19     creator_avatar -> Nullable<Text>,
20     category_name -> Varchar,
21     number_of_subscribers -> BigInt,
22     number_of_posts -> BigInt,
23     number_of_comments -> BigInt,
24     hot_rank -> Int4,
25     user_id -> Nullable<Int4>,
26     subscribed -> Nullable<Bool>,
27   }
28 }
29
30 table! {
31   community_mview (id) {
32     id -> Int4,
33     name -> Varchar,
34     title -> Varchar,
35     description -> Nullable<Text>,
36     category_id -> Int4,
37     creator_id -> Int4,
38     removed -> Bool,
39     published -> Timestamp,
40     updated -> Nullable<Timestamp>,
41     deleted -> Bool,
42     nsfw -> Bool,
43     creator_name -> Varchar,
44     creator_avatar -> Nullable<Text>,
45     category_name -> Varchar,
46     number_of_subscribers -> BigInt,
47     number_of_posts -> BigInt,
48     number_of_comments -> BigInt,
49     hot_rank -> Int4,
50     user_id -> Nullable<Int4>,
51     subscribed -> Nullable<Bool>,
52   }
53 }
54
55 table! {
56   community_moderator_view (id) {
57     id -> Int4,
58     community_id -> Int4,
59     user_id -> Int4,
60     published -> Timestamp,
61     user_name -> Varchar,
62     avatar -> Nullable<Text>,
63     community_name -> Varchar,
64   }
65 }
66
67 table! {
68   community_follower_view (id) {
69     id -> Int4,
70     community_id -> Int4,
71     user_id -> Int4,
72     published -> Timestamp,
73     user_name -> Varchar,
74     avatar -> Nullable<Text>,
75     community_name -> Varchar,
76   }
77 }
78
79 table! {
80   community_user_ban_view (id) {
81     id -> Int4,
82     community_id -> Int4,
83     user_id -> Int4,
84     published -> Timestamp,
85     user_name -> Varchar,
86     avatar -> Nullable<Text>,
87     community_name -> Varchar,
88   }
89 }
90
91 #[derive(
92   Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
93 )]
94 #[table_name = "community_view"]
95 pub struct CommunityView {
96   pub id: i32,
97   pub name: String,
98   pub title: String,
99   pub description: Option<String>,
100   pub category_id: i32,
101   pub creator_id: i32,
102   pub removed: bool,
103   pub published: chrono::NaiveDateTime,
104   pub updated: Option<chrono::NaiveDateTime>,
105   pub deleted: bool,
106   pub nsfw: bool,
107   pub creator_name: String,
108   pub creator_avatar: Option<String>,
109   pub category_name: String,
110   pub number_of_subscribers: i64,
111   pub number_of_posts: i64,
112   pub number_of_comments: i64,
113   pub hot_rank: i32,
114   pub user_id: Option<i32>,
115   pub subscribed: Option<bool>,
116 }
117
118 pub struct CommunityQueryBuilder<'a> {
119   conn: &'a PgConnection,
120   query: BoxedQuery<'a, Pg>,
121   sort: &'a SortType,
122   from_user_id: Option<i32>,
123   show_nsfw: bool,
124   search_term: Option<String>,
125   page: Option<i64>,
126   limit: Option<i64>,
127 }
128
129 impl<'a> CommunityQueryBuilder<'a> {
130   pub fn create(conn: &'a PgConnection) -> Self {
131     use super::community_view::community_mview::dsl::*;
132
133     let query = community_mview.into_boxed();
134
135     CommunityQueryBuilder {
136       conn,
137       query,
138       sort: &SortType::Hot,
139       from_user_id: None,
140       show_nsfw: true,
141       search_term: None,
142       page: None,
143       limit: None,
144     }
145   }
146
147   pub fn sort(mut self, sort: &'a SortType) -> Self {
148     self.sort = sort;
149     self
150   }
151
152   pub fn for_user<T: MaybeOptional<i32>>(mut self, from_user_id: T) -> Self {
153     self.from_user_id = from_user_id.get_optional();
154     self
155   }
156
157   pub fn show_nsfw(mut self, show_nsfw: bool) -> Self {
158     self.show_nsfw = show_nsfw;
159     self
160   }
161
162   pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
163     self.search_term = search_term.get_optional();
164     self
165   }
166
167   pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
168     self.page = page.get_optional();
169     self
170   }
171
172   pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
173     self.limit = limit.get_optional();
174     self
175   }
176
177   pub fn list(self) -> Result<Vec<CommunityView>, Error> {
178     use super::community_view::community_mview::dsl::*;
179
180     let mut query = self.query;
181
182     if let Some(search_term) = self.search_term {
183       let searcher = fuzzy_search(&search_term);
184       query = query
185         .filter(name.ilike(searcher.to_owned()))
186         .or_filter(title.ilike(searcher.to_owned()))
187         .or_filter(description.ilike(searcher));
188     };
189
190     // The view lets you pass a null user_id, if you're not logged in
191     match self.sort {
192       SortType::Hot => {
193         query = query
194           .order_by(hot_rank.desc())
195           .then_order_by(number_of_subscribers.desc())
196           .filter(user_id.is_null())
197       }
198       SortType::New => query = query.order_by(published.desc()).filter(user_id.is_null()),
199       SortType::TopAll => match self.from_user_id {
200         Some(from_user_id) => {
201           query = query
202             .filter(user_id.eq(from_user_id))
203             .order_by((subscribed.asc(), number_of_subscribers.desc()))
204         }
205         None => {
206           query = query
207             .order_by(number_of_subscribers.desc())
208             .filter(user_id.is_null())
209         }
210       },
211       _ => (),
212     };
213
214     if !self.show_nsfw {
215       query = query.filter(nsfw.eq(false));
216     };
217
218     let (limit, offset) = limit_and_offset(self.page, self.limit);
219     query
220       .limit(limit)
221       .offset(offset)
222       .filter(removed.eq(false))
223       .filter(deleted.eq(false))
224       .load::<CommunityView>(self.conn)
225   }
226 }
227
228 impl CommunityView {
229   pub fn read(
230     conn: &PgConnection,
231     from_community_id: i32,
232     from_user_id: Option<i32>,
233   ) -> Result<Self, Error> {
234     use super::community_view::community_mview::dsl::*;
235
236     let mut query = community_mview.into_boxed();
237
238     query = query.filter(id.eq(from_community_id));
239
240     // The view lets you pass a null user_id, if you're not logged in
241     if let Some(from_user_id) = from_user_id {
242       query = query.filter(user_id.eq(from_user_id));
243     } else {
244       query = query.filter(user_id.is_null());
245     };
246
247     query.first::<Self>(conn)
248   }
249 }
250
251 #[derive(
252   Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
253 )]
254 #[table_name = "community_moderator_view"]
255 pub struct CommunityModeratorView {
256   pub id: i32,
257   pub community_id: i32,
258   pub user_id: i32,
259   pub published: chrono::NaiveDateTime,
260   pub user_name: String,
261   pub avatar: Option<String>,
262   pub community_name: String,
263 }
264
265 impl CommunityModeratorView {
266   pub fn for_community(conn: &PgConnection, from_community_id: i32) -> Result<Vec<Self>, Error> {
267     use super::community_view::community_moderator_view::dsl::*;
268     community_moderator_view
269       .filter(community_id.eq(from_community_id))
270       .load::<Self>(conn)
271   }
272
273   pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result<Vec<Self>, Error> {
274     use super::community_view::community_moderator_view::dsl::*;
275     community_moderator_view
276       .filter(user_id.eq(from_user_id))
277       .load::<Self>(conn)
278   }
279 }
280
281 #[derive(
282   Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
283 )]
284 #[table_name = "community_follower_view"]
285 pub struct CommunityFollowerView {
286   pub id: i32,
287   pub community_id: i32,
288   pub user_id: i32,
289   pub published: chrono::NaiveDateTime,
290   pub user_name: String,
291   pub avatar: Option<String>,
292   pub community_name: String,
293 }
294
295 impl CommunityFollowerView {
296   pub fn for_community(conn: &PgConnection, from_community_id: i32) -> Result<Vec<Self>, Error> {
297     use super::community_view::community_follower_view::dsl::*;
298     community_follower_view
299       .filter(community_id.eq(from_community_id))
300       .load::<Self>(conn)
301   }
302
303   pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result<Vec<Self>, Error> {
304     use super::community_view::community_follower_view::dsl::*;
305     community_follower_view
306       .filter(user_id.eq(from_user_id))
307       .load::<Self>(conn)
308   }
309 }
310
311 #[derive(
312   Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
313 )]
314 #[table_name = "community_user_ban_view"]
315 pub struct CommunityUserBanView {
316   pub id: i32,
317   pub community_id: i32,
318   pub user_id: i32,
319   pub published: chrono::NaiveDateTime,
320   pub user_name: String,
321   pub avatar: Option<String>,
322   pub community_name: String,
323 }
324
325 impl CommunityUserBanView {
326   pub fn for_community(conn: &PgConnection, from_community_id: i32) -> Result<Vec<Self>, Error> {
327     use super::community_view::community_user_ban_view::dsl::*;
328     community_user_ban_view
329       .filter(community_id.eq(from_community_id))
330       .load::<Self>(conn)
331   }
332
333   pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result<Vec<Self>, Error> {
334     use super::community_view::community_user_ban_view::dsl::*;
335     community_user_ban_view
336       .filter(user_id.eq(from_user_id))
337       .load::<Self>(conn)
338   }
339
340   pub fn get(
341     conn: &PgConnection,
342     from_user_id: i32,
343     from_community_id: i32,
344   ) -> Result<Self, Error> {
345     use super::community_view::community_user_ban_view::dsl::*;
346     community_user_ban_view
347       .filter(user_id.eq(from_user_id))
348       .filter(community_id.eq(from_community_id))
349       .first::<Self>(conn)
350   }
351 }