From: Piotr Juszczyk <74842304+pijuszczyk@users.noreply.github.com>
Date: Tue, 8 Aug 2023 09:40:28 +0000 (+0200)
Subject: Allow filtering posts and comments by whether they were liked/disliked - fixes #3401... 
X-Git-Url: http://these/git/%22https:/nerdica.net/photo/contact/80/%7B%60%24%7BarchiveTodayUrl%7D/?a=commitdiff_plain;h=2ad3450004a32dac311922e3d70f0884a660c41b;p=lemmy.git

Allow filtering posts and comments by whether they were liked/disliked - fixes #3401 (#3523)

* Allow filtering posts and comments by whether they were liked/disliked

* Switch to 2 args - liked_only, disliked_only - taking bools

* Make liked_only and disliked_only Option<bool>

* Fix unrelated is_profile_view compilation error
---

diff --git a/crates/api_common/src/comment.rs b/crates/api_common/src/comment.rs
index 1b0df39d..ec9ca132 100644
--- a/crates/api_common/src/comment.rs
+++ b/crates/api_common/src/comment.rs
@@ -126,6 +126,8 @@ pub struct GetComments {
   pub post_id: Option<PostId>,
   pub parent_id: Option<CommentId>,
   pub saved_only: Option<bool>,
+  pub liked_only: Option<bool>,
+  pub disliked_only: Option<bool>,
   pub auth: Option<Sensitive<String>>,
 }
 
diff --git a/crates/api_common/src/post.rs b/crates/api_common/src/post.rs
index 01a7db9c..e511d279 100644
--- a/crates/api_common/src/post.rs
+++ b/crates/api_common/src/post.rs
@@ -75,6 +75,8 @@ pub struct GetPosts {
   pub community_id: Option<CommunityId>,
   pub community_name: Option<String>,
   pub saved_only: Option<bool>,
+  pub liked_only: Option<bool>,
+  pub disliked_only: Option<bool>,
   pub moderator_view: Option<bool>,
   pub auth: Option<Sensitive<String>>,
 }
diff --git a/crates/apub/src/api/list_comments.rs b/crates/apub/src/api/list_comments.rs
index f07ce3da..3954df58 100644
--- a/crates/apub/src/api/list_comments.rs
+++ b/crates/apub/src/api/list_comments.rs
@@ -35,6 +35,13 @@ pub async fn list_comments(
   let sort = data.sort;
   let max_depth = data.max_depth;
   let saved_only = data.saved_only;
+
+  let liked_only = data.liked_only;
+  let disliked_only = data.disliked_only;
+  if liked_only.unwrap_or_default() && disliked_only.unwrap_or_default() {
+    return Err(LemmyError::from(LemmyErrorType::ContradictingFilters));
+  }
+
   let page = data.page;
   let limit = data.limit;
   let parent_id = data.parent_id;
@@ -59,6 +66,8 @@ pub async fn list_comments(
     sort,
     max_depth,
     saved_only,
+    liked_only,
+    disliked_only,
     community_id,
     parent_path: parent_path_cloned,
     post_id,
diff --git a/crates/apub/src/api/list_posts.rs b/crates/apub/src/api/list_posts.rs
index 2635e149..d7138df3 100644
--- a/crates/apub/src/api/list_posts.rs
+++ b/crates/apub/src/api/list_posts.rs
@@ -36,6 +36,12 @@ pub async fn list_posts(
   };
   let saved_only = data.saved_only;
 
+  let liked_only = data.liked_only;
+  let disliked_only = data.disliked_only;
+  if liked_only.unwrap_or_default() && disliked_only.unwrap_or_default() {
+    return Err(LemmyError::from(LemmyErrorType::ContradictingFilters));
+  }
+
   let moderator_view = data.moderator_view;
 
   let listing_type = Some(listing_type_with_default(
@@ -50,6 +56,8 @@ pub async fn list_posts(
     sort,
     community_id,
     saved_only,
+    liked_only,
+    disliked_only,
     moderator_view,
     page,
     limit,
diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs
index 45ab82bd..506efb32 100644
--- a/crates/db_views/src/comment_view.rs
+++ b/crates/db_views/src/comment_view.rs
@@ -195,6 +195,12 @@ fn queries<'a>() -> Queries<
       query = query.filter(comment_saved::comment_id.is_not_null());
     }
 
+    if options.liked_only.unwrap_or_default() {
+      query = query.filter(comment_like::score.eq(1));
+    } else if options.disliked_only.unwrap_or_default() {
+      query = query.filter(comment_like::score.eq(-1));
+    }
+
     let is_creator = options.creator_id == options.local_user.map(|l| l.person.id);
     // only show deleted comments to creator
     if !is_creator {
@@ -309,6 +315,8 @@ pub struct CommentQuery<'a> {
   pub local_user: Option<&'a LocalUserView>,
   pub search_term: Option<String>,
   pub saved_only: Option<bool>,
+  pub liked_only: Option<bool>,
+  pub disliked_only: Option<bool>,
   pub is_profile_view: bool,
   pub page: Option<i64>,
   pub limit: Option<i64>,
@@ -608,6 +616,33 @@ mod tests {
     // Make sure block set the creator blocked
     assert!(read_comment_from_blocked_person.creator_blocked);
 
+    let read_liked_comment_views = CommentQuery {
+      local_user: (Some(&data.local_user_view)),
+      liked_only: (Some(true)),
+      ..Default::default()
+    }
+    .list(pool)
+    .await
+    .unwrap();
+
+    assert_eq!(
+      expected_comment_view_with_person,
+      read_liked_comment_views[0]
+    );
+
+    assert_eq!(1, read_liked_comment_views.len());
+
+    let read_disliked_comment_views: Vec<CommentView> = CommentQuery {
+      local_user: (Some(&data.local_user_view)),
+      disliked_only: (Some(true)),
+      ..Default::default()
+    }
+    .list(pool)
+    .await
+    .unwrap();
+
+    assert!(read_disliked_comment_views.is_empty());
+
     cleanup(data, pool).await;
   }
 
diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs
index 0f844a49..a832e111 100644
--- a/crates/db_views/src/post_view.rs
+++ b/crates/db_views/src/post_view.rs
@@ -313,6 +313,12 @@ fn queries<'a>() -> Queries<
       }
     }
 
+    if options.liked_only.unwrap_or_default() {
+      query = query.filter(post_like::score.eq(1));
+    } else if options.disliked_only.unwrap_or_default() {
+      query = query.filter(post_like::score.eq(-1));
+    }
+
     if options.local_user.is_some() {
       // Filter out the rows with missing languages
       query = query.filter(local_user_language::language_id.is_not_null());
@@ -426,6 +432,8 @@ pub struct PostQuery<'a> {
   pub search_term: Option<String>,
   pub url_search: Option<String>,
   pub saved_only: Option<bool>,
+  pub liked_only: Option<bool>,
+  pub disliked_only: Option<bool>,
   pub moderator_view: Option<bool>,
   pub is_profile_view: bool,
   pub page: Option<i64>,
@@ -796,6 +804,28 @@ mod tests {
 
     assert_eq!(expected_post_with_upvote, read_post_listing[0]);
 
+    let read_liked_post_listing = PostQuery {
+      community_id: (Some(data.inserted_community.id)),
+      local_user: (Some(&data.local_user_view)),
+      liked_only: (Some(true)),
+      ..Default::default()
+    }
+    .list(pool)
+    .await
+    .unwrap();
+    assert_eq!(read_post_listing, read_liked_post_listing);
+
+    let read_disliked_post_listing = PostQuery {
+      community_id: (Some(data.inserted_community.id)),
+      local_user: (Some(&data.local_user_view)),
+      disliked_only: (Some(true)),
+      ..Default::default()
+    }
+    .list(pool)
+    .await
+    .unwrap();
+    assert!(read_disliked_post_listing.is_empty());
+
     let like_removed =
       PostLike::remove(pool, data.local_user_view.person.id, data.inserted_post.id)
         .await
diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs
index c6e6ad01..9ddd3b29 100644
--- a/crates/utils/src/error.rs
+++ b/crates/utils/src/error.rs
@@ -207,6 +207,7 @@ pub enum LemmyErrorType {
   CouldntCreateAudioCaptcha,
   InvalidUrlScheme,
   CouldntSendWebmention,
+  ContradictingFilters,
   Unknown(String),
 }