Add an API endpoint for listing remote packs
authorEkaterina Vaartis <vaartis@cock.li>
Tue, 24 Sep 2019 16:18:07 +0000 (19:18 +0300)
committerEkaterina Vaartis <vaartis@cock.li>
Wed, 25 Sep 2019 10:32:19 +0000 (12:32 +0200)
lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex
lib/pleroma/web/router.ex
test/web/pleroma_api/emoji_api_controller_test.exs

index b7eede6c9e729f5b6b1b912093843b414a9015bf..cf5a086feece30072b962ab2b1a58ca6e679a060 100644 (file)
@@ -10,6 +10,27 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     )
   end
 
+  @doc """
+  Lists packs from the remote instance.
+
+  Since JS cannot ask remote instances for their packs due to CPS, it has to
+  be done by the server
+  """
+  def list_from(conn, %{"instance_address" => address}) do
+    address = String.trim(address)
+
+    if shareable_packs_available(address) do
+      list_resp =
+        "#{address}/api/pleroma/emoji/packs" |> Tesla.get!() |> Map.get(:body) |> Jason.decode!()
+
+      json(conn, list_resp)
+    else
+      conn
+      |> put_status(:internal_server_error)
+      |> json(%{error: "The requested instance does not support sharing emoji packs"})
+    end
+  end
+
   @doc """
   Lists the packs available on the instance as JSON.
 
@@ -156,6 +177,21 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
     end
   end
 
+  defp shareable_packs_available(address) do
+    "#{address}/.well-known/nodeinfo"
+    |> Tesla.get!()
+    |> Map.get(:body)
+    |> Jason.decode!()
+    |> List.last()
+    |> Map.get("href")
+    # Get the actual nodeinfo address and fetch it
+    |> Tesla.get!()
+    |> Map.get(:body)
+    |> Jason.decode!()
+    |> get_in(["metadata", "features"])
+    |> Enum.member?("shareable_emoji_packs")
+  end
+
   @doc """
   An admin endpoint to request downloading a pack named `pack_name` from the instance
   `instance_address`.
@@ -164,21 +200,9 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
   from that instance, otherwise it will be downloaded from the fallback source, if there is one.
   """
   def download_from(conn, %{"instance_address" => address, "pack_name" => name} = data) do
-    shareable_packs_available =
-      "#{address}/.well-known/nodeinfo"
-      |> Tesla.get!()
-      |> Map.get(:body)
-      |> Jason.decode!()
-      |> List.last()
-      |> Map.get("href")
-      # Get the actual nodeinfo address and fetch it
-      |> Tesla.get!()
-      |> Map.get(:body)
-      |> Jason.decode!()
-      |> get_in(["metadata", "features"])
-      |> Enum.member?("shareable_emoji_packs")
-
-    if shareable_packs_available do
+    address = String.trim(address)
+
+    if shareable_packs_available(address) do
       full_pack =
         "#{address}/api/pleroma/emoji/packs/list"
         |> Tesla.get!()
index e583093d20fe1fb11ef6d059962dc35f86d12eae..8bc051936c182a41d219a0f0e63593aa788fc1b8 100644 (file)
@@ -222,6 +222,7 @@ defmodule Pleroma.Web.Router do
       put("/:name", EmojiAPIController, :create)
       delete("/:name", EmojiAPIController, :delete)
       post("/download_from", EmojiAPIController, :download_from)
+      post("/list_from", EmojiAPIController, :list_from)
     end
 
     scope "/packs" do
index c5a5536924412e07c34a1cc883eb89bbb70813a1..166a0201dc844d4d86cf76b4910d0a94fc0b031b 100644 (file)
@@ -33,6 +33,28 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
     refute pack["pack"]["can-download"]
   end
 
+  test "listing remote packs" do
+    admin = insert(:user, info: %{is_admin: true})
+    conn = build_conn() |> assign(:user, admin)
+
+    resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+
+    mock(fn
+      %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+        json([%{href: "https://example.com/nodeinfo/2.1.json"}])
+
+      %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+        json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+      %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} ->
+        json(resp)
+    end)
+
+    assert conn
+           |> post(emoji_api_path(conn, :list_from), %{instance_address: "https://example.com"})
+           |> json_response(200) == resp
+  end
+
   test "downloading a shared pack from download_shared" do
     conn = build_conn()