]> Untitled Git - lemmy.git/blob - crates/db_views_actor/src/person_mention_view.rs
Make functions work with both connection and pool (#3420)
[lemmy.git] / crates / db_views_actor / src / person_mention_view.rs
1 use crate::structs::PersonMentionView;
2 use diesel::{
3   dsl::now,
4   result::Error,
5   BoolExpressionMethods,
6   ExpressionMethods,
7   JoinOnDsl,
8   NullableExpressionMethods,
9   QueryDsl,
10 };
11 use diesel_async::RunQueryDsl;
12 use lemmy_db_schema::{
13   aggregates::structs::CommentAggregates,
14   newtypes::{PersonId, PersonMentionId},
15   schema::{
16     comment,
17     comment_aggregates,
18     comment_like,
19     comment_saved,
20     community,
21     community_follower,
22     community_person_ban,
23     person,
24     person_block,
25     person_mention,
26     post,
27   },
28   source::{
29     comment::{Comment, CommentSaved},
30     community::{Community, CommunityFollower, CommunityPersonBan},
31     person::Person,
32     person_block::PersonBlock,
33     person_mention::PersonMention,
34     post::Post,
35   },
36   traits::JoinView,
37   utils::{get_conn, limit_and_offset, DbPool},
38   CommentSortType,
39 };
40 use typed_builder::TypedBuilder;
41
42 type PersonMentionViewTuple = (
43   PersonMention,
44   Comment,
45   Person,
46   Post,
47   Community,
48   Person,
49   CommentAggregates,
50   Option<CommunityPersonBan>,
51   Option<CommunityFollower>,
52   Option<CommentSaved>,
53   Option<PersonBlock>,
54   Option<i16>,
55 );
56
57 impl PersonMentionView {
58   pub async fn read(
59     pool: &mut DbPool<'_>,
60     person_mention_id: PersonMentionId,
61     my_person_id: Option<PersonId>,
62   ) -> Result<Self, Error> {
63     let conn = &mut get_conn(pool).await?;
64     let person_alias_1 = diesel::alias!(person as person1);
65
66     // The left join below will return None in this case
67     let person_id_join = my_person_id.unwrap_or(PersonId(-1));
68
69     let (
70       person_mention,
71       comment,
72       creator,
73       post,
74       community,
75       recipient,
76       counts,
77       creator_banned_from_community,
78       follower,
79       saved,
80       creator_blocked,
81       my_vote,
82     ) = person_mention::table
83       .find(person_mention_id)
84       .inner_join(comment::table)
85       .inner_join(person::table.on(comment::creator_id.eq(person::id)))
86       .inner_join(post::table.on(comment::post_id.eq(post::id)))
87       .inner_join(community::table.on(post::community_id.eq(community::id)))
88       .inner_join(person_alias_1)
89       .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id)))
90       .left_join(
91         community_person_ban::table.on(
92           community::id
93             .eq(community_person_ban::community_id)
94             .and(community_person_ban::person_id.eq(comment::creator_id)),
95         ),
96       )
97       .left_join(
98         community_follower::table.on(
99           post::community_id
100             .eq(community_follower::community_id)
101             .and(community_follower::person_id.eq(person_id_join)),
102         ),
103       )
104       .left_join(
105         comment_saved::table.on(
106           comment::id
107             .eq(comment_saved::comment_id)
108             .and(comment_saved::person_id.eq(person_id_join)),
109         ),
110       )
111       .left_join(
112         person_block::table.on(
113           comment::creator_id
114             .eq(person_block::target_id)
115             .and(person_block::person_id.eq(person_id_join)),
116         ),
117       )
118       .left_join(
119         comment_like::table.on(
120           comment::id
121             .eq(comment_like::comment_id)
122             .and(comment_like::person_id.eq(person_id_join)),
123         ),
124       )
125       .select((
126         person_mention::all_columns,
127         comment::all_columns,
128         person::all_columns,
129         post::all_columns,
130         community::all_columns,
131         person_alias_1.fields(person::all_columns),
132         comment_aggregates::all_columns,
133         community_person_ban::all_columns.nullable(),
134         community_follower::all_columns.nullable(),
135         comment_saved::all_columns.nullable(),
136         person_block::all_columns.nullable(),
137         comment_like::score.nullable(),
138       ))
139       .first::<PersonMentionViewTuple>(conn)
140       .await?;
141
142     Ok(PersonMentionView {
143       person_mention,
144       comment,
145       creator,
146       post,
147       community,
148       recipient,
149       counts,
150       creator_banned_from_community: creator_banned_from_community.is_some(),
151       subscribed: CommunityFollower::to_subscribed_type(&follower),
152       saved: saved.is_some(),
153       creator_blocked: creator_blocked.is_some(),
154       my_vote,
155     })
156   }
157
158   /// Gets the number of unread mentions
159   pub async fn get_unread_mentions(
160     pool: &mut DbPool<'_>,
161     my_person_id: PersonId,
162   ) -> Result<i64, Error> {
163     use diesel::dsl::count;
164     let conn = &mut get_conn(pool).await?;
165
166     person_mention::table
167       .inner_join(comment::table)
168       .filter(person_mention::recipient_id.eq(my_person_id))
169       .filter(person_mention::read.eq(false))
170       .filter(comment::deleted.eq(false))
171       .filter(comment::removed.eq(false))
172       .select(count(person_mention::id))
173       .first::<i64>(conn)
174       .await
175   }
176 }
177
178 #[derive(TypedBuilder)]
179 #[builder(field_defaults(default))]
180 pub struct PersonMentionQuery<'a, 'b: 'a> {
181   #[builder(!default)]
182   pool: &'a mut DbPool<'b>,
183   my_person_id: Option<PersonId>,
184   recipient_id: Option<PersonId>,
185   sort: Option<CommentSortType>,
186   unread_only: Option<bool>,
187   show_bot_accounts: Option<bool>,
188   page: Option<i64>,
189   limit: Option<i64>,
190 }
191
192 impl<'a, 'b: 'a> PersonMentionQuery<'a, 'b> {
193   pub async fn list(self) -> Result<Vec<PersonMentionView>, Error> {
194     let conn = &mut get_conn(self.pool).await?;
195
196     let person_alias_1 = diesel::alias!(person as person1);
197
198     // The left join below will return None in this case
199     let person_id_join = self.my_person_id.unwrap_or(PersonId(-1));
200
201     let mut query = person_mention::table
202       .inner_join(comment::table)
203       .inner_join(person::table.on(comment::creator_id.eq(person::id)))
204       .inner_join(post::table.on(comment::post_id.eq(post::id)))
205       .inner_join(community::table.on(post::community_id.eq(community::id)))
206       .inner_join(person_alias_1)
207       .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id)))
208       .left_join(
209         community_person_ban::table.on(
210           community::id
211             .eq(community_person_ban::community_id)
212             .and(community_person_ban::person_id.eq(comment::creator_id))
213             .and(
214               community_person_ban::expires
215                 .is_null()
216                 .or(community_person_ban::expires.gt(now)),
217             ),
218         ),
219       )
220       .left_join(
221         community_follower::table.on(
222           post::community_id
223             .eq(community_follower::community_id)
224             .and(community_follower::person_id.eq(person_id_join)),
225         ),
226       )
227       .left_join(
228         comment_saved::table.on(
229           comment::id
230             .eq(comment_saved::comment_id)
231             .and(comment_saved::person_id.eq(person_id_join)),
232         ),
233       )
234       .left_join(
235         person_block::table.on(
236           comment::creator_id
237             .eq(person_block::target_id)
238             .and(person_block::person_id.eq(person_id_join)),
239         ),
240       )
241       .left_join(
242         comment_like::table.on(
243           comment::id
244             .eq(comment_like::comment_id)
245             .and(comment_like::person_id.eq(person_id_join)),
246         ),
247       )
248       .select((
249         person_mention::all_columns,
250         comment::all_columns,
251         person::all_columns,
252         post::all_columns,
253         community::all_columns,
254         person_alias_1.fields(person::all_columns),
255         comment_aggregates::all_columns,
256         community_person_ban::all_columns.nullable(),
257         community_follower::all_columns.nullable(),
258         comment_saved::all_columns.nullable(),
259         person_block::all_columns.nullable(),
260         comment_like::score.nullable(),
261       ))
262       .into_boxed();
263
264     if let Some(recipient_id) = self.recipient_id {
265       query = query.filter(person_mention::recipient_id.eq(recipient_id));
266     }
267
268     if self.unread_only.unwrap_or(false) {
269       query = query.filter(person_mention::read.eq(false));
270     }
271
272     if !self.show_bot_accounts.unwrap_or(true) {
273       query = query.filter(person::bot_account.eq(false));
274     };
275
276     query = match self.sort.unwrap_or(CommentSortType::Hot) {
277       CommentSortType::Hot => query.then_order_by(comment_aggregates::hot_rank.desc()),
278       CommentSortType::New => query.then_order_by(comment::published.desc()),
279       CommentSortType::Old => query.then_order_by(comment::published.asc()),
280       CommentSortType::Top => query.order_by(comment_aggregates::score.desc()),
281     };
282
283     let (limit, offset) = limit_and_offset(self.page, self.limit)?;
284
285     let res = query
286       .limit(limit)
287       .offset(offset)
288       .load::<PersonMentionViewTuple>(conn)
289       .await?;
290
291     Ok(res.into_iter().map(PersonMentionView::from_tuple).collect())
292   }
293 }
294
295 impl JoinView for PersonMentionView {
296   type JoinTuple = PersonMentionViewTuple;
297   fn from_tuple(a: Self::JoinTuple) -> Self {
298     Self {
299       person_mention: a.0,
300       comment: a.1,
301       creator: a.2,
302       post: a.3,
303       community: a.4,
304       recipient: a.5,
305       counts: a.6,
306       creator_banned_from_community: a.7.is_some(),
307       subscribed: CommunityFollower::to_subscribed_type(&a.8),
308       saved: a.9.is_some(),
309       creator_blocked: a.10.is_some(),
310       my_vote: a.11,
311     }
312   }
313 }