return data only for updated emoji
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Thu, 6 Feb 2020 15:01:12 +0000 (18:01 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Thu, 30 Apr 2020 12:24:02 +0000 (15:24 +0300)
CHANGELOG.md
docs/API/pleroma_api.md
lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex
test/instance_static/add/shortcode.png [new file with mode: 0644]
test/web/pleroma_api/controllers/emoji_api_controller_test.exs

index c0f1bcf5708352c24e3662b6a0939a89d1d2efea..a220c14f634ffe06c563158103306799cde08d55 100644 (file)
@@ -125,13 +125,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 <details>
   <summary>API Changes</summary>
 
-- **Breaking** EmojiReactions: Change endpoints and responses to align with Mastodon
-- **Breaking** Admin API: `PATCH /api/pleroma/admin/users/:nickname/force_password_reset` is now `PATCH /api/pleroma/admin/users/force_password_reset` (accepts `nicknames` array in the request body)
+- **Breaking:** EmojiReactions: Change endpoints and responses to align with Mastodon
+- **Breaking:** Admin API: `PATCH /api/pleroma/admin/users/:nickname/force_password_reset` is now `PATCH /api/pleroma/admin/users/force_password_reset` (accepts `nicknames` array in the request body)
 - **Breaking:** Admin API: Return link alongside with token on password reset
 - **Breaking:** Admin API: `PUT /api/pleroma/admin/reports/:id` is now `PATCH /api/pleroma/admin/reports`, see admin_api.md for details
 - **Breaking:** `/api/pleroma/admin/users/invite_token` now uses `POST`, changed accepted params and returns full invite in json instead of only token string.
-- **Breaking** replying to reports is now "report notes", enpoint changed from `POST /api/pleroma/admin/reports/:id/respond` to `POST /api/pleroma/admin/reports/:id/notes`
+- **Breaking:** replying to reports is now "report notes", endpoint changed from `POST /api/pleroma/admin/reports/:id/respond` to `POST /api/pleroma/admin/reports/:id/notes`
 - Mastodon API: stopped sanitizing display names, field names and subject fields since they are supposed to be treated as plaintext
+- **Breaking:** Pleroma API: `/api/pleroma/emoji/packs/:name/update_file` endpoint returns only updated emoji data.
 - Admin API: Return `total` when querying for reports
 - Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`)
 - Admin API: Return link alongside with token on password reset
index 90c43c356be09d2706ca00377535846feffcb5a6..a7c7731ce9a439f972dde4c9c406c5942edd83bf 100644 (file)
@@ -357,7 +357,7 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa
     * if the `action` is `update`, changes emoji shortcode
       (from `shortcode` to `new_shortcode` or moves the file (from the current filename to `new_filename`)
     * if the `action` is `remove`, removes the emoji named `shortcode` and it's associated file
-* Response: JSON, updated "files" section of the pack and 200 status, 409 if the trying to use a shortcode
+* Response: JSON, emoji shortcode with filename which was added/updated/deleted and 200 status, 409 if the trying to use a shortcode
   that is already taken, 400 if there was an error with the shortcode, filename or file (additional info
   in the "error" part of the response JSON)
 
index e01825b48b28b9374f8d949c749a5f7bb3621b57..981bac4fa901a7b257ba136f975b73461ee17eca 100644 (file)
@@ -385,23 +385,35 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
     json(conn, new_data)
   end
 
-  defp get_filename(%{"filename" => filename}), do: filename
+  defp get_filename(%Plug.Upload{filename: filename}), do: filename
+  defp get_filename(url) when is_binary(url), do: Path.basename(url)
 
-  defp get_filename(%{"file" => file}) do
-    case file do
-      %Plug.Upload{filename: filename} -> filename
-      url when is_binary(url) -> Path.basename(url)
+  defp empty?(str), do: String.trim(str) == ""
+
+  defp update_pack_file(updated_full_pack, pack_file_p) do
+    content = Jason.encode!(updated_full_pack, pretty: true)
+
+    File.write!(pack_file_p, content)
+  end
+
+  defp create_subdirs(file_path) do
+    if String.contains?(file_path, "/") do
+      file_path
+      |> Path.dirname()
+      |> File.mkdir_p!()
     end
   end
 
-  defp empty?(str), do: String.trim(str) == ""
+  defp pack_info(pack_name) do
+    dir = Path.join(emoji_dir_path(), pack_name)
+    json_path = Path.join(dir, "pack.json")
 
-  defp update_file_and_send(conn, updated_full_pack, pack_file_p) do
-    # Write the emoji pack file
-    File.write!(pack_file_p, Jason.encode!(updated_full_pack, pretty: true))
+    json =
+      json_path
+      |> File.read!()
+      |> Jason.decode!()
 
-    # Return the modified file list
-    json(conn, updated_full_pack["files"])
+    {dir, json_path, json}
   end
 
   @doc """
@@ -422,23 +434,25 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
   # Add
   def update_file(
         conn,
-        %{"pack_name" => pack_name, "action" => "add", "shortcode" => shortcode} = params
+        %{"pack_name" => pack_name, "action" => "add"} = params
       ) do
-    pack_dir = Path.join(emoji_dir_path(), pack_name)
-    pack_file_p = Path.join(pack_dir, "pack.json")
+    shortcode =
+      if params["shortcode"] do
+        params["shortcode"]
+      else
+        filename = get_filename(params["file"])
+        Path.basename(filename, Path.extname(filename))
+      end
 
-    full_pack = Jason.decode!(File.read!(pack_file_p))
+    {pack_dir, pack_file_p, full_pack} = pack_info(pack_name)
 
     with {_, false} <- {:has_shortcode, Map.has_key?(full_pack["files"], shortcode)},
-         filename <- get_filename(params),
+         filename <- params["filename"] || get_filename(params["file"]),
          false <- empty?(shortcode),
-         false <- empty?(filename) do
-      file_path = Path.join(pack_dir, filename)
-
+         false <- empty?(filename),
+         file_path <- Path.join(pack_dir, filename) do
       # If the name contains directories, create them
-      if String.contains?(file_path, "/") do
-        File.mkdir_p!(Path.dirname(file_path))
-      end
+      create_subdirs(file_path)
 
       case params["file"] do
         %Plug.Upload{path: upload_path} ->
@@ -451,8 +465,11 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
           File.write!(file_path, file_contents)
       end
 
-      updated_full_pack = put_in(full_pack, ["files", shortcode], filename)
-      update_file_and_send(conn, updated_full_pack, pack_file_p)
+      full_pack
+      |> put_in(["files", shortcode], filename)
+      |> update_pack_file(pack_file_p)
+
+      json(conn, %{shortcode => filename})
     else
       {:has_shortcode, _} ->
         conn
@@ -472,10 +489,7 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
         "action" => "remove",
         "shortcode" => shortcode
       }) do
-    pack_dir = Path.join(emoji_dir_path(), pack_name)
-    pack_file_p = Path.join(pack_dir, "pack.json")
-
-    full_pack = Jason.decode!(File.read!(pack_file_p))
+    {pack_dir, pack_file_p, full_pack} = pack_info(pack_name)
 
     if Map.has_key?(full_pack["files"], shortcode) do
       {emoji_file_path, updated_full_pack} = pop_in(full_pack, ["files", shortcode])
@@ -494,7 +508,8 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
         end
       end
 
-      update_file_and_send(conn, updated_full_pack, pack_file_p)
+      update_pack_file(updated_full_pack, pack_file_p)
+      json(conn, %{shortcode => full_pack["files"][shortcode]})
     else
       conn
       |> put_status(:bad_request)
@@ -507,10 +522,7 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
         conn,
         %{"pack_name" => pack_name, "action" => "update", "shortcode" => shortcode} = params
       ) do
-    pack_dir = Path.join(emoji_dir_path(), pack_name)
-    pack_file_p = Path.join(pack_dir, "pack.json")
-
-    full_pack = Jason.decode!(File.read!(pack_file_p))
+    {pack_dir, pack_file_p, full_pack} = pack_info(pack_name)
 
     with {_, true} <- {:has_shortcode, Map.has_key?(full_pack["files"], shortcode)},
          %{"new_shortcode" => new_shortcode, "new_filename" => new_filename} <- params,
@@ -522,9 +534,7 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
       new_emoji_file_path = Path.join(pack_dir, new_filename)
 
       # If the name contains directories, create them
-      if String.contains?(new_emoji_file_path, "/") do
-        File.mkdir_p!(Path.dirname(new_emoji_file_path))
-      end
+      create_subdirs(new_emoji_file_path)
 
       # Move/Rename the old filename to a new filename
       # These are probably on the same filesystem, so just rename should work
@@ -540,8 +550,11 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
       end
 
       # Then, put in the new shortcode with the new path
-      updated_full_pack = put_in(updated_full_pack, ["files", new_shortcode], new_filename)
-      update_file_and_send(conn, updated_full_pack, pack_file_p)
+      updated_full_pack
+      |> put_in(["files", new_shortcode], new_filename)
+      |> update_pack_file(pack_file_p)
+
+      json(conn, %{new_shortcode => new_filename})
     else
       {:has_shortcode, _} ->
         conn
diff --git a/test/instance_static/add/shortcode.png b/test/instance_static/add/shortcode.png
new file mode 100644 (file)
index 0000000..8f50fa0
Binary files /dev/null and b/test/instance_static/add/shortcode.png differ
index 4246eb400046422efb4c5c5ec6466711519cdfbc..6844601d71bca2e81fb410030d1feb56a7ea503c 100644 (file)
@@ -295,96 +295,116 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
     end
   end
 
-  test "updating pack files" do
-    pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
-    original_content = File.read!(pack_file)
+  describe "update_file/2" do
+    setup do
+      pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
+      original_content = File.read!(pack_file)
 
-    on_exit(fn ->
-      File.write!(pack_file, original_content)
+      on_exit(fn ->
+        File.write!(pack_file, original_content)
+      end)
 
-      File.rm_rf!("#{@emoji_dir_path}/test_pack/blank_url.png")
-      File.rm_rf!("#{@emoji_dir_path}/test_pack/dir")
-      File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2")
-    end)
+      admin = insert(:user, is_admin: true)
+      %{conn: conn} = oauth_access(["admin:write"], user: admin)
+      {:ok, conn: conn}
+    end
 
-    admin = insert(:user, is_admin: true)
-    %{conn: conn} = oauth_access(["admin:write"], user: admin)
+    test "update file without shortcode", %{conn: conn} do
+      on_exit(fn -> File.rm_rf!("#{@emoji_dir_path}/test_pack/shortcode.png") end)
+
+      assert conn
+             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
+               "action" => "add",
+               "file" => %Plug.Upload{
+                 filename: "shortcode.png",
+                 path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png"
+               }
+             })
+             |> json_response(200) == %{"shortcode" => "shortcode.png"}
+    end
+
+    test "updating pack files", %{conn: conn} do
+      on_exit(fn ->
+        File.rm_rf!("#{@emoji_dir_path}/test_pack/blank_url.png")
+        File.rm_rf!("#{@emoji_dir_path}/test_pack/dir")
+        File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2")
+      end)
 
-    same_name = %{
-      "action" => "add",
-      "shortcode" => "blank",
-      "filename" => "dir/blank.png",
-      "file" => %Plug.Upload{
-        filename: "blank.png",
-        path: "#{@emoji_dir_path}/test_pack/blank.png"
+      same_name = %{
+        "action" => "add",
+        "shortcode" => "blank",
+        "filename" => "dir/blank.png",
+        "file" => %Plug.Upload{
+          filename: "blank.png",
+          path: "#{@emoji_dir_path}/test_pack/blank.png"
+        }
       }
-    }
 
-    different_name = %{same_name | "shortcode" => "blank_2"}
+      different_name = %{same_name | "shortcode" => "blank_2"}
 
-    assert (conn
-            |> post(emoji_api_path(conn, :update_file, "test_pack"), same_name)
-            |> json_response(:conflict))["error"] =~ "already exists"
+      assert (conn
+              |> post(emoji_api_path(conn, :update_file, "test_pack"), same_name)
+              |> json_response(:conflict))["error"] =~ "already exists"
 
-    assert conn
-           |> post(emoji_api_path(conn, :update_file, "test_pack"), different_name)
-           |> json_response(200) == %{"blank" => "blank.png", "blank_2" => "dir/blank.png"}
+      assert conn
+             |> post(emoji_api_path(conn, :update_file, "test_pack"), different_name)
+             |> json_response(200) == %{"blank_2" => "dir/blank.png"}
 
-    assert File.exists?("#{@emoji_dir_path}/test_pack/dir/blank.png")
+      assert File.exists?("#{@emoji_dir_path}/test_pack/dir/blank.png")
 
-    assert conn
-           |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
-             "action" => "update",
-             "shortcode" => "blank_2",
-             "new_shortcode" => "blank_3",
-             "new_filename" => "dir_2/blank_3.png"
-           })
-           |> json_response(200) == %{"blank" => "blank.png", "blank_3" => "dir_2/blank_3.png"}
+      assert conn
+             |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
+               "action" => "update",
+               "shortcode" => "blank_2",
+               "new_shortcode" => "blank_3",
+               "new_filename" => "dir_2/blank_3.png"
+             })
+             |> json_response(200) == %{"blank_3" => "dir_2/blank_3.png"}
 
-    refute File.exists?("#{@emoji_dir_path}/test_pack/dir/")
-    assert File.exists?("#{@emoji_dir_path}/test_pack/dir_2/blank_3.png")
+      refute File.exists?("#{@emoji_dir_path}/test_pack/dir/")
+      assert File.exists?("#{@emoji_dir_path}/test_pack/dir_2/blank_3.png")
 
-    assert conn
-           |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
-             "action" => "remove",
-             "shortcode" => "blank_3"
-           })
-           |> json_response(200) == %{"blank" => "blank.png"}
+      assert conn
+             |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
+               "action" => "remove",
+               "shortcode" => "blank_3"
+             })
+             |> json_response(200) == %{"blank_3" => "dir_2/blank_3.png"}
 
-    refute File.exists?("#{@emoji_dir_path}/test_pack/dir_2/")
+      refute File.exists?("#{@emoji_dir_path}/test_pack/dir_2/")
 
-    mock(fn
-      %{
-        method: :get,
-        url: "https://test-blank/blank_url.png"
-      } ->
-        text(File.read!("#{@emoji_dir_path}/test_pack/blank.png"))
-    end)
+      mock(fn
+        %{
+          method: :get,
+          url: "https://test-blank/blank_url.png"
+        } ->
+          text(File.read!("#{@emoji_dir_path}/test_pack/blank.png"))
+      end)
 
-    # The name should be inferred from the URL ending
-    from_url = %{
-      "action" => "add",
-      "shortcode" => "blank_url",
-      "file" => "https://test-blank/blank_url.png"
-    }
+      # The name should be inferred from the URL ending
+      from_url = %{
+        "action" => "add",
+        "shortcode" => "blank_url",
+        "file" => "https://test-blank/blank_url.png"
+      }
 
-    assert conn
-           |> post(emoji_api_path(conn, :update_file, "test_pack"), from_url)
-           |> json_response(200) == %{
-             "blank" => "blank.png",
-             "blank_url" => "blank_url.png"
-           }
+      assert conn
+             |> post(emoji_api_path(conn, :update_file, "test_pack"), from_url)
+             |> json_response(200) == %{
+               "blank_url" => "blank_url.png"
+             }
 
-    assert File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
+      assert File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
 
-    assert conn
-           |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
-             "action" => "remove",
-             "shortcode" => "blank_url"
-           })
-           |> json_response(200) == %{"blank" => "blank.png"}
+      assert conn
+             |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
+               "action" => "remove",
+               "shortcode" => "blank_url"
+             })
+             |> json_response(200) == %{"blank_url" => "blank_url.png"}
 
-    refute File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
+      refute File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
+    end
   end
 
   test "creating and deleting a pack" do