]> Untitled Git - lemmy.git/blob - server/src/db/community_view.rs
Merge remote-tracking branch 'upstream/master'
[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       query = query.filter(name.ilike(fuzzy_search(&search_term)));
184     };
185
186     // The view lets you pass a null user_id, if you're not logged in
187     match self.sort {
188       SortType::Hot => {
189         query = query
190           .order_by(hot_rank.desc())
191           .then_order_by(number_of_subscribers.desc())
192           .filter(user_id.is_null())
193       }
194       SortType::New => query = query.order_by(published.desc()).filter(user_id.is_null()),
195       SortType::TopAll => match self.from_user_id {
196         Some(from_user_id) => {
197           query = query
198             .filter(user_id.eq(from_user_id))
199             .order_by((subscribed.asc(), number_of_subscribers.desc()))
200         }
201         None => {
202           query = query
203             .order_by(number_of_subscribers.desc())
204             .filter(user_id.is_null())
205         }
206       },
207       _ => (),
208     };
209
210     if !self.show_nsfw {
211       query = query.filter(nsfw.eq(false));
212     };
213
214     let (limit, offset) = limit_and_offset(self.page, self.limit);
215     query
216       .limit(limit)
217       .offset(offset)
218       .filter(removed.eq(false))
219       .filter(deleted.eq(false))
220       .load::<CommunityView>(self.conn)
221   }
222 }
223
224 impl CommunityView {
225   pub fn read(
226     conn: &PgConnection,
227     from_community_id: i32,
228     from_user_id: Option<i32>,
229   ) -> Result<Self, Error> {
230     use super::community_view::community_view::dsl::*;
231
232     let mut query = community_view.into_boxed();
233
234     query = query.filter(id.eq(from_community_id));
235
236     // The view lets you pass a null user_id, if you're not logged in
237     if let Some(from_user_id) = from_user_id {
238       query = query.filter(user_id.eq(from_user_id));
239     } else {
240       query = query.filter(user_id.is_null());
241     };
242
243     query.first::<Self>(conn)
244   }
245 }
246
247 #[derive(
248   Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
249 )]
250 #[table_name = "community_moderator_view"]
251 pub struct CommunityModeratorView {
252   pub id: i32,
253   pub community_id: i32,
254   pub user_id: i32,
255   pub published: chrono::NaiveDateTime,
256   pub user_name: String,
257   pub avatar: Option<String>,
258   pub community_name: String,
259 }
260
261 impl CommunityModeratorView {
262   pub fn for_community(conn: &PgConnection, from_community_id: i32) -> Result<Vec<Self>, Error> {
263     use super::community_view::community_moderator_view::dsl::*;
264     community_moderator_view
265       .filter(community_id.eq(from_community_id))
266       .load::<Self>(conn)
267   }
268
269   pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result<Vec<Self>, Error> {
270     use super::community_view::community_moderator_view::dsl::*;
271     community_moderator_view
272       .filter(user_id.eq(from_user_id))
273       .load::<Self>(conn)
274   }
275 }
276
277 #[derive(
278   Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
279 )]
280 #[table_name = "community_follower_view"]
281 pub struct CommunityFollowerView {
282   pub id: i32,
283   pub community_id: i32,
284   pub user_id: i32,
285   pub published: chrono::NaiveDateTime,
286   pub user_name: String,
287   pub avatar: Option<String>,
288   pub community_name: String,
289 }
290
291 impl CommunityFollowerView {
292   pub fn for_community(conn: &PgConnection, from_community_id: i32) -> Result<Vec<Self>, Error> {
293     use super::community_view::community_follower_view::dsl::*;
294     community_follower_view
295       .filter(community_id.eq(from_community_id))
296       .load::<Self>(conn)
297   }
298
299   pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result<Vec<Self>, Error> {
300     use super::community_view::community_follower_view::dsl::*;
301     community_follower_view
302       .filter(user_id.eq(from_user_id))
303       .load::<Self>(conn)
304   }
305 }
306
307 #[derive(
308   Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
309 )]
310 #[table_name = "community_user_ban_view"]
311 pub struct CommunityUserBanView {
312   pub id: i32,
313   pub community_id: i32,
314   pub user_id: i32,
315   pub published: chrono::NaiveDateTime,
316   pub user_name: String,
317   pub avatar: Option<String>,
318   pub community_name: String,
319 }
320
321 impl CommunityUserBanView {
322   pub fn for_community(conn: &PgConnection, from_community_id: i32) -> Result<Vec<Self>, Error> {
323     use super::community_view::community_user_ban_view::dsl::*;
324     community_user_ban_view
325       .filter(community_id.eq(from_community_id))
326       .load::<Self>(conn)
327   }
328
329   pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result<Vec<Self>, Error> {
330     use super::community_view::community_user_ban_view::dsl::*;
331     community_user_ban_view
332       .filter(user_id.eq(from_user_id))
333       .load::<Self>(conn)
334   }
335
336   pub fn get(
337     conn: &PgConnection,
338     from_user_id: i32,
339     from_community_id: i32,
340   ) -> Result<Self, Error> {
341     use super::community_view::community_user_ban_view::dsl::*;
342     community_user_ban_view
343       .filter(user_id.eq(from_user_id))
344       .filter(community_id.eq(from_community_id))
345       .first::<Self>(conn)
346   }
347 }