From be5e2c4dbba63831ea6a0617556e686969b5080f Mon Sep 17 00:00:00 2001
From: Ivan Tashkinov <ivantashkinov@gmail.com>
Date: Wed, 25 Mar 2020 17:01:45 +0300
Subject: [PATCH] Applied relationships preloading to GET
 /api/v1/accounts/relationships. Refactoring (User.binary_id/1).

---
 lib/pleroma/conversation/participation.ex         | 11 ++++-------
 lib/pleroma/following_relationship.ex             |  8 ++------
 lib/pleroma/thread_mute.ex                        |  4 ++--
 lib/pleroma/user.ex                               | 15 +++++++++++++++
 lib/pleroma/user_relationship.ex                  |  9 ++-------
 .../web/mastodon_api/views/account_view.ex        |  6 +++++-
 6 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/lib/pleroma/conversation/participation.ex b/lib/pleroma/conversation/participation.ex
index 693825cf5..215265fc9 100644
--- a/lib/pleroma/conversation/participation.ex
+++ b/lib/pleroma/conversation/participation.ex
@@ -129,21 +129,18 @@ defmodule Pleroma.Conversation.Participation do
   end
 
   def restrict_recipients(query, user, %{"recipients" => user_ids}) do
-    user_ids =
+    user_binary_ids =
       [user.id | user_ids]
       |> Enum.uniq()
-      |> Enum.reduce([], fn user_id, acc ->
-        {:ok, user_id} = FlakeId.Ecto.CompatType.dump(user_id)
-        [user_id | acc]
-      end)
+      |> User.binary_id()
 
     conversation_subquery =
       __MODULE__
       |> group_by([p], p.conversation_id)
       |> having(
         [p],
-        count(p.user_id) == ^length(user_ids) and
-          fragment("array_agg(?) @> ?", p.user_id, ^user_ids)
+        count(p.user_id) == ^length(user_binary_ids) and
+          fragment("array_agg(?) @> ?", p.user_id, ^user_binary_ids)
       )
       |> select([p], %{id: p.conversation_id})
 
diff --git a/lib/pleroma/following_relationship.ex b/lib/pleroma/following_relationship.ex
index dd1696136..624bddfe4 100644
--- a/lib/pleroma/following_relationship.ex
+++ b/lib/pleroma/following_relationship.ex
@@ -135,12 +135,8 @@ defmodule Pleroma.FollowingRelationship do
         target_users
       )
       when is_list(source_users) and is_list(target_users) do
-    get_bin_ids = fn user ->
-      with {:ok, bin_id} <- CompatType.dump(user.id), do: bin_id
-    end
-
-    source_user_ids = Enum.map(source_users, &get_bin_ids.(&1))
-    target_user_ids = Enum.map(target_users, &get_bin_ids.(&1))
+    source_user_ids = User.binary_id(source_users)
+    target_user_ids = User.binary_id(target_users)
 
     __MODULE__
     |> where(
diff --git a/lib/pleroma/thread_mute.ex b/lib/pleroma/thread_mute.ex
index cc815430a..f657758aa 100644
--- a/lib/pleroma/thread_mute.ex
+++ b/lib/pleroma/thread_mute.ex
@@ -24,10 +24,10 @@ defmodule Pleroma.ThreadMute do
   end
 
   def query(user_id, context) do
-    {:ok, user_id} = FlakeId.Ecto.CompatType.dump(user_id)
+    user_binary_id = User.binary_id(user_id)
 
     ThreadMute
-    |> Ecto.Query.where(user_id: ^user_id)
+    |> Ecto.Query.where(user_id: ^user_binary_id)
     |> Ecto.Query.where(context: ^context)
   end
 
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index f74e43cce..699256a3b 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -218,6 +218,21 @@ defmodule Pleroma.User do
     end
   end
 
+  @doc "Dumps id to SQL-compatible format"
+  def binary_id(source_id) when is_binary(source_id) do
+    with {:ok, dumped_id} <- FlakeId.Ecto.CompatType.dump(source_id) do
+      dumped_id
+    else
+      _ -> source_id
+    end
+  end
+
+  def binary_id(source_ids) when is_list(source_ids) do
+    Enum.map(source_ids, &binary_id/1)
+  end
+
+  def binary_id(%User{} = user), do: binary_id(user.id)
+
   @doc "Returns status account"
   @spec account_status(User.t()) :: account_status()
   def account_status(%User{deactivated: true}), do: :deactivated
diff --git a/lib/pleroma/user_relationship.ex b/lib/pleroma/user_relationship.ex
index 9423e3a42..519d2998d 100644
--- a/lib/pleroma/user_relationship.ex
+++ b/lib/pleroma/user_relationship.ex
@@ -8,7 +8,6 @@ defmodule Pleroma.UserRelationship do
   import Ecto.Changeset
   import Ecto.Query
 
-  alias FlakeId.Ecto.CompatType
   alias Pleroma.Repo
   alias Pleroma.User
   alias Pleroma.UserRelationship
@@ -84,12 +83,8 @@ defmodule Pleroma.UserRelationship do
         target_to_source_rel_types \\ nil
       )
       when is_list(source_users) and is_list(target_users) do
-    get_bin_ids = fn user ->
-      with {:ok, bin_id} <- CompatType.dump(user.id), do: bin_id
-    end
-
-    source_user_ids = Enum.map(source_users, &get_bin_ids.(&1))
-    target_user_ids = Enum.map(target_users, &get_bin_ids.(&1))
+    source_user_ids = User.binary_id(source_users)
+    target_user_ids = User.binary_id(target_users)
 
     get_rel_type_codes = fn rel_type -> user_relationship_mappings()[rel_type] end
 
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index 702d9e658..6b2eca1f3 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
   alias Pleroma.UserRelationship
   alias Pleroma.Web.CommonAPI.Utils
   alias Pleroma.Web.MastodonAPI.AccountView
+  alias Pleroma.Web.MastodonAPI.StatusView
   alias Pleroma.Web.MediaProxy
 
   defp find_following_rel(following_relationships, follower, following) do
@@ -129,7 +130,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
   end
 
   def render("relationships.json", %{user: user, targets: targets}) do
-    render_many(targets, AccountView, "relationship.json", user: user, as: :target)
+    relationships_opts = StatusView.relationships_opts(user, targets)
+    opts = %{as: :target, user: user, relationships: relationships_opts}
+
+    render_many(targets, AccountView, "relationship.json", opts)
   end
 
   defp do_render("show.json", %{user: user} = opts) do