1 use crate::structs::CommentReplyView;
2 use diesel::{dsl::*, result::Error, *};
4 aggregates::structs::CommentAggregates,
5 newtypes::{CommentReplyId, PersonId},
21 comment::{Comment, CommentSaved},
22 comment_reply::CommentReply,
23 community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe},
24 person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
25 person_block::PersonBlock,
28 traits::{MaybeOptional, ToSafe, ViewToVec},
29 utils::{functions::hot_rank, limit_and_offset},
33 type CommentReplyViewTuple = (
41 Option<CommunityPersonBan>,
42 Option<CommunityFollower>,
48 impl CommentReplyView {
51 comment_reply_id: CommentReplyId,
52 my_person_id: Option<PersonId>,
53 ) -> Result<Self, Error> {
54 // The left join below will return None in this case
55 let person_id_join = my_person_id.unwrap_or(PersonId(-1));
65 creator_banned_from_community,
70 ) = comment_reply::table
71 .find(comment_reply_id)
72 .inner_join(comment::table)
73 .inner_join(person::table.on(comment::creator_id.eq(person::id)))
74 .inner_join(post::table.on(comment::post_id.eq(post::id)))
75 .inner_join(community::table.on(post::community_id.eq(community::id)))
76 .inner_join(person_alias_1::table)
77 .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id)))
79 community_person_ban::table.on(
81 .eq(community_person_ban::community_id)
82 .and(community_person_ban::person_id.eq(comment::creator_id))
84 community_person_ban::expires
86 .or(community_person_ban::expires.gt(now)),
91 community_follower::table.on(
93 .eq(community_follower::community_id)
94 .and(community_follower::person_id.eq(person_id_join)),
98 comment_saved::table.on(
100 .eq(comment_saved::comment_id)
101 .and(comment_saved::person_id.eq(person_id_join)),
105 person_block::table.on(
107 .eq(person_block::target_id)
108 .and(person_block::person_id.eq(person_id_join)),
112 comment_like::table.on(
114 .eq(comment_like::comment_id)
115 .and(comment_like::person_id.eq(person_id_join)),
119 comment_reply::all_columns,
120 comment::all_columns,
121 Person::safe_columns_tuple(),
123 Community::safe_columns_tuple(),
124 PersonAlias1::safe_columns_tuple(),
125 comment_aggregates::all_columns,
126 community_person_ban::all_columns.nullable(),
127 community_follower::all_columns.nullable(),
128 comment_saved::all_columns.nullable(),
129 person_block::all_columns.nullable(),
130 comment_like::score.nullable(),
132 .first::<CommentReplyViewTuple>(conn)?;
134 Ok(CommentReplyView {
142 creator_banned_from_community: creator_banned_from_community.is_some(),
143 subscribed: CommunityFollower::to_subscribed_type(&follower),
144 saved: saved.is_some(),
145 creator_blocked: creator_blocked.is_some(),
150 /// Gets the number of unread replies
151 pub fn get_unread_replies(conn: &PgConnection, my_person_id: PersonId) -> Result<i64, Error> {
155 .filter(comment_reply::recipient_id.eq(my_person_id))
156 .filter(comment_reply::read.eq(false))
157 .select(count(comment_reply::id))
162 pub struct CommentReplyQueryBuilder<'a> {
163 conn: &'a PgConnection,
164 my_person_id: Option<PersonId>,
165 recipient_id: Option<PersonId>,
166 sort: Option<CommentSortType>,
167 unread_only: Option<bool>,
168 show_bot_accounts: Option<bool>,
173 impl<'a> CommentReplyQueryBuilder<'a> {
174 pub fn create(conn: &'a PgConnection) -> Self {
175 CommentReplyQueryBuilder {
181 show_bot_accounts: None,
187 pub fn sort<T: MaybeOptional<CommentSortType>>(mut self, sort: T) -> Self {
188 self.sort = sort.get_optional();
192 pub fn unread_only<T: MaybeOptional<bool>>(mut self, unread_only: T) -> Self {
193 self.unread_only = unread_only.get_optional();
197 pub fn show_bot_accounts<T: MaybeOptional<bool>>(mut self, show_bot_accounts: T) -> Self {
198 self.show_bot_accounts = show_bot_accounts.get_optional();
202 pub fn recipient_id<T: MaybeOptional<PersonId>>(mut self, recipient_id: T) -> Self {
203 self.recipient_id = recipient_id.get_optional();
207 pub fn my_person_id<T: MaybeOptional<PersonId>>(mut self, my_person_id: T) -> Self {
208 self.my_person_id = my_person_id.get_optional();
212 pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
213 self.page = page.get_optional();
217 pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
218 self.limit = limit.get_optional();
222 pub fn list(self) -> Result<Vec<CommentReplyView>, Error> {
225 // The left join below will return None in this case
226 let person_id_join = self.my_person_id.unwrap_or(PersonId(-1));
228 let mut query = comment_reply::table
229 .inner_join(comment::table)
230 .inner_join(person::table.on(comment::creator_id.eq(person::id)))
231 .inner_join(post::table.on(comment::post_id.eq(post::id)))
232 .inner_join(community::table.on(post::community_id.eq(community::id)))
233 .inner_join(person_alias_1::table)
234 .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id)))
236 community_person_ban::table.on(
238 .eq(community_person_ban::community_id)
239 .and(community_person_ban::person_id.eq(comment::creator_id))
241 community_person_ban::expires
243 .or(community_person_ban::expires.gt(now)),
248 community_follower::table.on(
250 .eq(community_follower::community_id)
251 .and(community_follower::person_id.eq(person_id_join)),
255 comment_saved::table.on(
257 .eq(comment_saved::comment_id)
258 .and(comment_saved::person_id.eq(person_id_join)),
262 person_block::table.on(
264 .eq(person_block::target_id)
265 .and(person_block::person_id.eq(person_id_join)),
269 comment_like::table.on(
271 .eq(comment_like::comment_id)
272 .and(comment_like::person_id.eq(person_id_join)),
276 comment_reply::all_columns,
277 comment::all_columns,
278 Person::safe_columns_tuple(),
280 Community::safe_columns_tuple(),
281 PersonAlias1::safe_columns_tuple(),
282 comment_aggregates::all_columns,
283 community_person_ban::all_columns.nullable(),
284 community_follower::all_columns.nullable(),
285 comment_saved::all_columns.nullable(),
286 person_block::all_columns.nullable(),
287 comment_like::score.nullable(),
291 if let Some(recipient_id) = self.recipient_id {
292 query = query.filter(comment_reply::recipient_id.eq(recipient_id));
295 if self.unread_only.unwrap_or(false) {
296 query = query.filter(comment_reply::read.eq(false));
299 if !self.show_bot_accounts.unwrap_or(true) {
300 query = query.filter(person::bot_account.eq(false));
303 query = match self.sort.unwrap_or(CommentSortType::Hot) {
304 CommentSortType::Hot => query
305 .then_order_by(hot_rank(comment_aggregates::score, comment_aggregates::published).desc())
306 .then_order_by(comment_aggregates::published.desc()),
307 CommentSortType::New => query.then_order_by(comment::published.desc()),
308 CommentSortType::Old => query.then_order_by(comment::published.asc()),
309 CommentSortType::Top => query.order_by(comment_aggregates::score.desc()),
312 let (limit, offset) = limit_and_offset(self.page, self.limit)?;
317 .load::<CommentReplyViewTuple>(self.conn)?;
319 Ok(CommentReplyView::from_tuple_to_vec(res))
323 impl ViewToVec for CommentReplyView {
324 type DbTuple = CommentReplyViewTuple;
325 fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
336 creator_banned_from_community: a.7.is_some(),
337 subscribed: CommunityFollower::to_subscribed_type(&a.8),
338 saved: a.9.is_some(),
339 creator_blocked: a.10.is_some(),
342 .collect::<Vec<Self>>()