v2 Suggestions: also filter out users you follow
authorAlex Gleason <alex@alexgleason.me>
Sat, 27 Nov 2021 03:42:28 +0000 (21:42 -0600)
committerAlex Gleason <alex@alexgleason.me>
Sat, 27 Nov 2021 03:46:08 +0000 (21:46 -0600)
lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex
test/pleroma/web/mastodon_api/controllers/suggestion_controller_test.exs

index 3c5a07b7d4ce8e04c78145d5d8a354b5661c6b7e..e913fcf4bbb5c66f8e850ca81fb832e57e3f9bd6 100644 (file)
@@ -5,6 +5,7 @@
 defmodule Pleroma.Web.MastodonAPI.SuggestionController do
   use Pleroma.Web, :controller
   import Ecto.Query
+  alias Pleroma.FollowingRelationship
   alias Pleroma.User
   alias Pleroma.UserRelationship
 
@@ -66,20 +67,15 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do
     do: Pleroma.Web.MastodonAPI.MastodonAPIController.empty_array(conn, params)
 
   @doc "GET /api/v2/suggestions"
-  def index2(%{assigns: %{user: %{id: user_id} = user}} = conn, params) do
+  def index2(%{assigns: %{user: user}} = conn, params) do
     limit = Map.get(params, :limit, 40) |> min(80)
 
     users =
       %{is_suggested: true, invisible: false, limit: limit}
       |> User.Query.build()
-      |> where([u], u.id != ^user_id)
-      |> join(:left, [u], r in UserRelationship,
-        as: :relationships,
-        on:
-          r.target_id == u.id and r.source_id == ^user_id and
-            r.relationship_type in [:block, :mute, :suggestion_dismiss]
-      )
-      |> where([relationships: r], is_nil(r.target_id))
+      |> exclude_user(user)
+      |> exclude_relationships(user, [:block, :mute, :suggestion_dismiss])
+      |> exclude_following(user)
       |> Pleroma.Repo.all()
 
     render(conn, "index.json", %{
@@ -90,6 +86,30 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do
     })
   end
 
+  defp exclude_user(query, %User{id: user_id}) do
+    where(query, [u], u.id != ^user_id)
+  end
+
+  defp exclude_relationships(query, %User{id: user_id}, relationship_types) do
+    query
+    |> join(:left, [u], r in UserRelationship,
+      as: :user_relationships,
+      on:
+        r.target_id == u.id and r.source_id == ^user_id and
+          r.relationship_type in ^relationship_types
+    )
+    |> where([user_relationships: r], is_nil(r.target_id))
+  end
+
+  defp exclude_following(query, %User{id: user_id}) do
+    query
+    |> join(:left, [u], r in FollowingRelationship,
+      as: :following_relationships,
+      on: r.following_id == u.id and r.follower_id == ^user_id and r.state == :follow_accept
+    )
+    |> where([following_relationships: r], is_nil(r.following_id))
+  end
+
   @doc "DELETE /api/v1/suggestions/:account_id"
   def dismiss(%{assigns: %{user: source}} = conn, %{account_id: user_id}) do
     with %User{} = target <- User.get_cached_by_id(user_id),
index 8948a52de149c60d1ecb10ed5eb2c9133911ff55..89273e67bd3251204ec0c8ee7af2067ec34064ea 100644 (file)
@@ -5,6 +5,7 @@
 defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
   use Pleroma.Web.ConnCase, async: true
   alias Pleroma.UserRelationship
+  alias Pleroma.Web.CommonAPI
   import Pleroma.Factory
 
   setup do: oauth_access(["read", "write"])
@@ -46,7 +47,19 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
 
   test "returns v2 suggestions excluding blocked accounts", %{conn: conn, user: blocker} do
     blocked = insert(:user, is_suggested: true)
-    {:ok, _} = Pleroma.Web.CommonAPI.block(blocker, blocked)
+    {:ok, _} = CommonAPI.block(blocker, blocked)
+
+    res =
+      conn
+      |> get("/api/v2/suggestions")
+      |> json_response_and_validate_schema(200)
+
+    assert [] = res
+  end
+
+  test "returns v2 suggestions excluding followed accounts", %{conn: conn, user: follower} do
+    followed = insert(:user, is_suggested: true)
+    {:ok, _, _, _} = CommonAPI.follow(follower, followed)
 
     res =
       conn