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