diff --git a/files/classes/user.py b/files/classes/user.py index a84cdb8ef..b26a9cd86 100644 --- a/files/classes/user.py +++ b/files/classes/user.py @@ -553,10 +553,27 @@ class User(Base): @lazy def normal_notifications_count(self): return self.notifications_count \ + - self.message_notifications_count \ - self.post_notifications_count \ - self.modaction_notifications_count \ - self.reddit_notifications_count + @property + @lazy + def message_notifications_count(self): + notifs = g.db.query(Notification).join(Comment).filter( + Notification.user_id == self.id, + Notification.read == False, + Comment.sentto != None, + or_(Comment.author_id==self.id, Comment.sentto==self.id), + Comment.parent_submission == None, + ) + + if not self.shadowbanned and self.admin_level < 3: + notifs = notifs.join(Comment.author).filter(User.shadowbanned == None) + + return notifs.count() + @property @lazy def post_notifications_count(self): @@ -599,6 +616,8 @@ class User(Base): # only meaningful when notifications_count > 0; otherwise falsely '' ~ normal if self.normal_notifications_count > 0: return '' + elif self.message_notifications_count > 0: + return 'messages' elif self.post_notifications_count > 0: return 'posts' elif self.modaction_notifications_count > 0: @@ -612,6 +631,7 @@ class User(Base): def notifications_color(self): colors = { '': '#dc3545', + 'messages': '#dc3545', 'posts': '#0000ff', 'modactions': '#e5990d', 'reddit': '#805ad5', diff --git a/files/routes/notifications.py b/files/routes/notifications.py index 50ef9e409..47865eb3b 100644 --- a/files/routes/notifications.py +++ b/files/routes/notifications.py @@ -66,16 +66,51 @@ def notifications_messages(v): try: page = max(int(request.values.get("page", 1)), 1) except: page = 1 - if v and (v.shadowbanned or v.admin_level > 2): - comments = g.db.query(Comment).filter(Comment.sentto != None, or_(Comment.author_id==v.id, Comment.sentto==v.id), Comment.parent_submission == None, Comment.level == 1).order_by(Comment.id.desc()).offset(25*(page-1)).limit(26).all() - else: - comments = g.db.query(Comment).join(Comment.author).filter(User.shadowbanned == None, Comment.sentto != None, or_(Comment.author_id==v.id, Comment.sentto==v.id), Comment.parent_submission == None, Comment.level == 1).order_by(Comment.id.desc()).offset(25*(page-1)).limit(26).all() + # All of these queries are horrible. For whomever comes here after me, + # PLEASE just turn DMs into their own table and get them out of + # Notifications & Comments. It's worth it. Save yourself. + message_threads = g.db.query(Comment).filter( + Comment.sentto != None, + or_(Comment.author_id == v.id, Comment.sentto == v.id), + Comment.parent_submission == None, + Comment.level == 1, + ) + if not v.shadowbanned and v.admin_level < 3: + message_threads = message_threads.join(Comment.author) \ + .filter(User.shadowbanned == None) - next_exists = (len(comments) > 25) - listing = comments[:25] + thread_order = g.db.query(Comment.top_comment_id, Comment.created_utc) \ + .distinct(Comment.top_comment_id) \ + .filter( + Comment.sentto != None, + or_(Comment.author_id == v.id, Comment.sentto == v.id), + ).order_by( + Comment.top_comment_id.desc(), + Comment.created_utc.desc() + ).subquery() + message_threads = message_threads.join(thread_order, + thread_order.c.top_comment_id == Comment.top_comment_id) + message_threads = message_threads.order_by(thread_order.c.created_utc.desc()) \ + .offset(25*(page-1)).limit(26).all() + + # Clear notifications (used for unread indicator only) for all user messages. + notifs_unread_row = g.db.query(Notification.comment_id).join(Comment).filter( + Notification.user_id == v.id, + Notification.read == False, + or_(Comment.author_id == v.id, Comment.sentto == v.id), + ).all() + + notifs_unread = [n.comment_id for n in notifs_unread_row] + g.db.query(Notification).filter( + Notification.user_id == v.id, + Notification.comment_id.in_(notifs_unread), + ).update({Notification.read: True}) g.db.commit() + next_exists = (len(message_threads) > 25) + listing = message_threads[:25] + if request.headers.get("Authorization"): return {"data":[x.json for x in listing]} return render_template("notifications.html", @@ -213,6 +248,7 @@ def notifications(v): Comment.is_banned == False, Comment.deleted_utc == 0, Comment.body_html.notlike('%

New site mention% - Messages + Messages {% if v.message_notifications_count %}({{v.message_notifications_count}}){% endif %} {% if v.admin_level >= NOTIF_MODACTION_JL_MIN %}