Adding GetUnreadCount to the API. Fixes #1794 (#1842)
authorDessalines <dessalines@users.noreply.github.com>
Sat, 16 Oct 2021 10:43:41 +0000 (06:43 -0400)
committerGitHub <noreply@github.com>
Sat, 16 Oct 2021 10:43:41 +0000 (10:43 +0000)
* Adding GetUnreadCount to the API. Fixes #1794

* Reordering filters to fix unread replies.

crates/api/src/lib.rs
crates/api/src/local_user.rs
crates/api_common/src/person.rs
crates/db_views/src/comment_view.rs
crates/db_views/src/private_message_view.rs
crates/db_views_actor/src/person_mention_view.rs
crates/websocket/src/lib.rs
src/api_routes.rs

index bfaceeb02ba6ac2f0450d652d67a2d771c52b07f..ccc817616e2aecf7e555f58a9dbd6abb03c09b0b 100644 (file)
@@ -72,6 +72,9 @@ pub async fn match_websocket_operation(
     UserOperation::GetReportCount => {
       do_websocket_operation::<GetReportCount>(context, id, op, data).await
     }
+    UserOperation::GetUnreadCount => {
+      do_websocket_operation::<GetUnreadCount>(context, id, op, data).await
+    }
 
     // Private Message ops
     UserOperation::MarkPrivateMessageAsRead => {
index a7d2f0c3cf8f1d86357b4d57d30e9921e970f793..d5a1533f99dd4b5b67a4e41f98c0a766875d74a2 100644 (file)
@@ -47,9 +47,10 @@ use lemmy_db_schema::{
 };
 use lemmy_db_views::{
   comment_report_view::CommentReportView,
-  comment_view::CommentQueryBuilder,
+  comment_view::{CommentQueryBuilder, CommentView},
   local_user_view::LocalUserView,
   post_report_view::PostReportView,
+  private_message_view::PrivateMessageView,
 };
 use lemmy_db_views_actor::{
   community_moderator_view::CommunityModeratorView,
@@ -831,3 +832,43 @@ impl Perform for GetReportCount {
     Ok(res)
   }
 }
+
+#[async_trait::async_trait(?Send)]
+impl Perform for GetUnreadCount {
+  type Response = GetUnreadCountResponse;
+
+  async fn perform(
+    &self,
+    context: &Data<LemmyContext>,
+    _websocket_id: Option<ConnectionId>,
+  ) -> Result<Self::Response, LemmyError> {
+    let data = self;
+    let local_user_view =
+      get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
+
+    let person_id = local_user_view.person.id;
+
+    let replies = blocking(context.pool(), move |conn| {
+      CommentView::get_unread_replies(conn, person_id)
+    })
+    .await??;
+
+    let mentions = blocking(context.pool(), move |conn| {
+      PersonMentionView::get_unread_mentions(conn, person_id)
+    })
+    .await??;
+
+    let private_messages = blocking(context.pool(), move |conn| {
+      PrivateMessageView::get_unread_messages(conn, person_id)
+    })
+    .await??;
+
+    let res = Self::Response {
+      replies,
+      mentions,
+      private_messages,
+    };
+
+    Ok(res)
+  }
+}
index 2dd9953b778b56cf0a41eeb143377646de9d7c53..af7212bac078d8c89c5088d807480a6f3fee89e3 100644 (file)
@@ -266,3 +266,15 @@ pub struct GetReportCountResponse {
   pub comment_reports: i64,
   pub post_reports: i64,
 }
+
+#[derive(Deserialize)]
+pub struct GetUnreadCount {
+  pub auth: String,
+}
+
+#[derive(Serialize, Clone)]
+pub struct GetUnreadCountResponse {
+  pub replies: i64,
+  pub mentions: i64,
+  pub private_messages: i64,
+}
index f682a232cd091ade860afe589dcf61ca2bd82706..e61752805c9cb05e643891cf817842ddca9490a7 100644 (file)
@@ -184,6 +184,46 @@ impl CommentView {
       None => self.post.creator_id,
     }
   }
+
+  /// Gets the number of unread replies
+  pub fn get_unread_replies(conn: &PgConnection, my_person_id: PersonId) -> Result<i64, Error> {
+    use diesel::dsl::*;
+
+    comment::table
+      // recipient here
+      .left_join(comment_alias_1::table.on(comment_alias_1::id.nullable().eq(comment::parent_id)))
+      .left_join(person_alias_1::table.on(person_alias_1::id.eq(comment_alias_1::creator_id)))
+      .inner_join(post::table)
+      .inner_join(community::table.on(post::community_id.eq(community::id)))
+      .left_join(
+        person_block::table.on(
+          comment::creator_id
+            .eq(person_block::target_id)
+            .and(person_block::person_id.eq(my_person_id)),
+        ),
+      )
+      .left_join(
+        community_block::table.on(
+          community::id
+            .eq(community_block::community_id)
+            .and(community_block::person_id.eq(my_person_id)),
+        ),
+      )
+      .filter(person_alias_1::id.eq(my_person_id)) // Gets the comment replies
+      .or_filter(
+        comment::parent_id
+          .is_null()
+          .and(post::creator_id.eq(my_person_id)),
+      ) // Gets the top level replies
+      .filter(comment::read.eq(false))
+      .filter(comment::deleted.eq(false))
+      .filter(comment::removed.eq(false))
+      // Don't show blocked communities or persons
+      .filter(community_block::person_id.is_null())
+      .filter(person_block::person_id.is_null())
+      .select(count(comment::id))
+      .first::<i64>(conn)
+  }
 }
 
 pub struct CommentQueryBuilder<'a> {
index 8fee2fc9bb3012c9009bf919bcb9992f6754fe63..86c1b79cb197a47b52948113abf9ffeb819b4785 100644 (file)
@@ -41,6 +41,17 @@ impl PrivateMessageView {
       recipient,
     })
   }
+
+  /// Gets the number of unread messages
+  pub fn get_unread_messages(conn: &PgConnection, my_person_id: PersonId) -> Result<i64, Error> {
+    use diesel::dsl::*;
+    private_message::table
+      .filter(private_message::read.eq(false))
+      .filter(private_message::recipient_id.eq(my_person_id))
+      .filter(private_message::deleted.eq(false))
+      .select(count(private_message::id))
+      .first::<i64>(conn)
+  }
 }
 
 pub struct PrivateMessageQueryBuilder<'a> {
index 421c60a401e796ca6f527e06ecaefb4e88e826d6..0d3cfc837ac6c1dac7786beae95401dad0ee4add 100644 (file)
@@ -163,6 +163,17 @@ impl PersonMentionView {
       my_vote,
     })
   }
+
+  /// Gets the number of unread mentions
+  pub fn get_unread_mentions(conn: &PgConnection, my_person_id: PersonId) -> Result<i64, Error> {
+    use diesel::dsl::*;
+
+    person_mention::table
+      .filter(person_mention::recipient_id.eq(my_person_id))
+      .filter(person_mention::read.eq(false))
+      .select(count(person_mention::id))
+      .first::<i64>(conn)
+  }
 }
 
 pub struct PersonMentionQueryBuilder<'a> {
index 366512eb904ceff6caa5c0c36e3f932bc6079250..e9f48874124155294d759335fa3ba40ce8431f5d 100644 (file)
@@ -116,6 +116,7 @@ pub enum UserOperation {
   ResolvePostReport,
   ListPostReports,
   GetReportCount,
+  GetUnreadCount,
   FollowCommunity,
   GetReplies,
   GetPersonMentions,
index 1d76af002ae509c19c15d4ec7bf86e116412aa23..80d507ef83f4c772e80d460dbcdcab5802f5a3cd 100644 (file)
@@ -193,7 +193,8 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
             "/change_password",
             web::put().to(route_post::<ChangePassword>),
           )
-          .route("/report_count", web::get().to(route_get::<GetReportCount>)),
+          .route("/report_count", web::get().to(route_get::<GetReportCount>))
+          .route("/unread_count", web::get().to(route_get::<GetUnreadCount>)),
       )
       // Admin Actions
       .service(