v2 Suggestions: rudimentary API response
authorAlex Gleason <alex@alexgleason.me>
Fri, 26 Nov 2021 20:33:27 +0000 (14:33 -0600)
committerAlex Gleason <alex@alexgleason.me>
Fri, 26 Nov 2021 20:34:10 +0000 (14:34 -0600)
lib/pleroma/user.ex
lib/pleroma/user/query.ex
lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex
lib/pleroma/web/mastodon_api/views/suggestion_view.ex [new file with mode: 0644]
priv/repo/migrations/20211126191138_add_suggestions.exs [new file with mode: 0644]
test/pleroma/user/query_test.exs
test/pleroma/web/mastodon_api/controllers/suggestion_controller_test.exs
test/pleroma/web/mastodon_api/views/suggestion_view_test.exs [new file with mode: 0644]

index 62506f37ad6d29ef6e10ffb86cdb14651f9e8667..6d62e9b4346daf6b441520eb1b03fbf688ca317d 100644 (file)
@@ -149,6 +149,7 @@ defmodule Pleroma.User do
     field(:last_active_at, :naive_datetime)
     field(:disclose_client, :boolean, default: true)
     field(:pinned_objects, :map, default: %{})
+    field(:is_suggested, :boolean, default: false)
 
     embeds_one(
       :notification_settings,
index ac807fc7927f5340cf37c9fbc83329b222e987c7..334e395fb10e3623f18a94f390a7174ea0a25d56 100644 (file)
@@ -167,6 +167,10 @@ defmodule Pleroma.User.Query do
     where(query, [u], u.is_confirmed == false)
   end
 
+  defp compose_query({:is_suggested, bool}, query) do
+    where(query, [u], u.is_suggested == ^bool)
+  end
+
   defp compose_query({:followers, %User{id: id}}, query) do
     query
     |> where([u], u.id != ^id)
index b941849f55a07f29d7258696a2b3499b4a2a559f..a34da98df183c0bbbda0be18a4258f1e84d62563 100644 (file)
@@ -4,6 +4,7 @@
 
 defmodule Pleroma.Web.MastodonAPI.SuggestionController do
   use Pleroma.Web, :controller
+  alias Pleroma.User
 
   require Logger
 
@@ -29,7 +30,7 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do
   def index2_operation do
     %OpenApiSpex.Operation{
       tags: ["Suggestions"],
-      summary: "Follow suggestions (Not implemented)",
+      summary: "Follow suggestions",
       operationId: "SuggestionController.index2",
       responses: %{
         200 => Pleroma.Web.ApiSpec.Helpers.empty_array_response()
@@ -42,6 +43,14 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do
     do: Pleroma.Web.MastodonAPI.MastodonAPIController.empty_array(conn, params)
 
   @doc "GET /api/v2/suggestions"
-  def index2(conn, params),
-    do: Pleroma.Web.MastodonAPI.MastodonAPIController.empty_array(conn, params)
+  def index2(conn, params) do
+    limit = Map.get(params, :limit, 40) |> min(80)
+
+    users =
+      %{is_suggested: true, limit: limit}
+      |> User.Query.build()
+      |> Pleroma.Repo.all()
+
+    render(conn, "index.json", %{users: users, source: :staff, skip_visibility_check: true})
+  end
 end
diff --git a/lib/pleroma/web/mastodon_api/views/suggestion_view.ex b/lib/pleroma/web/mastodon_api/views/suggestion_view.ex
new file mode 100644 (file)
index 0000000..865229a
--- /dev/null
@@ -0,0 +1,28 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.SuggestionView do
+  use Pleroma.Web, :view
+  alias Pleroma.Web.MastodonAPI.AccountView
+
+  @source_types [:staff, :global, :past_interactions]
+
+  def render("index.json", %{users: users} = opts) do
+    Enum.map(users, fn user ->
+      opts =
+        opts
+        |> Map.put(:user, user)
+        |> Map.delete(:users)
+
+      render("show.json", opts)
+    end)
+  end
+
+  def render("show.json", %{source: source, user: _user} = opts) when source in @source_types do
+    %{
+      source: source,
+      account: AccountView.render("show.json", opts)
+    }
+  end
+end
diff --git a/priv/repo/migrations/20211126191138_add_suggestions.exs b/priv/repo/migrations/20211126191138_add_suggestions.exs
new file mode 100644 (file)
index 0000000..5ad604e
--- /dev/null
@@ -0,0 +1,9 @@
+defmodule Pleroma.Repo.Migrations.AddSuggestions do
+  use Ecto.Migration
+
+  def change do
+    alter table(:users) do
+      add(:is_suggested, :boolean, default: false, null: false)
+    end
+  end
+end
index 357016e3e2ce9874876c3a792ce076f00fdf9c64..363da7665967546d97489a42b8a3109f1d3281fd 100644 (file)
@@ -34,4 +34,14 @@ defmodule Pleroma.User.QueryTest do
       assert %{internal: true} |> Query.build() |> Repo.aggregate(:count) == 2
     end
   end
+
+  test "is_suggested param" do
+    _user1 = insert(:user, is_suggested: false)
+    user2 = insert(:user, is_suggested: true)
+
+    assert [^user2] =
+             %{is_suggested: true}
+             |> User.Query.build()
+             |> Repo.all()
+  end
 end
index 5a9aea68094d6dad29b02d9f14c9d5cec28228f8..407063fa15fec068a62d10eb9eda3227a627aaec 100644 (file)
@@ -4,6 +4,7 @@
 
 defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
   use Pleroma.Web.ConnCase, async: true
+  import Pleroma.Factory
 
   setup do: oauth_access(["read"])
 
@@ -16,12 +17,14 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
     assert res == []
   end
 
-  test "returns empty result (v2)", %{conn: conn} do
+  test "returns v2 suggestions", %{conn: conn} do
+    %{id: user_id} = insert(:user, is_suggested: true)
+
     res =
       conn
       |> get("/api/v2/suggestions")
       |> json_response_and_validate_schema(200)
 
-    assert res == []
+    assert [%{"source" => "staff", "account" => %{"id" => ^user_id}}] = res
   end
 end
diff --git a/test/pleroma/web/mastodon_api/views/suggestion_view_test.exs b/test/pleroma/web/mastodon_api/views/suggestion_view_test.exs
new file mode 100644 (file)
index 0000000..5aae36c
--- /dev/null
@@ -0,0 +1,34 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.SuggestionViewTest do
+  use Pleroma.DataCase, async: true
+  import Pleroma.Factory
+  alias Pleroma.Web.MastodonAPI.SuggestionView, as: View
+
+  test "show.json" do
+    user = insert(:user, is_suggested: true)
+    json = View.render("show.json", %{user: user, source: :staff, skip_visibility_check: true})
+
+    assert json.source == :staff
+    assert json.account.id == user.id
+  end
+
+  test "index.json" do
+    user1 = insert(:user, is_suggested: true)
+    user2 = insert(:user, is_suggested: true)
+    user3 = insert(:user, is_suggested: true)
+
+    [suggestion1, suggestion2, suggestion3] =
+      View.render("index.json", %{
+        users: [user1, user2, user3],
+        source: :staff,
+        skip_visibility_check: true
+      })
+
+    assert suggestion1.source == :staff
+    assert suggestion2.account.id == user2.id
+    assert suggestion3.account.url == user3.ap_id
+  end
+end