emoji api packs changes in routes with docs update
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Sat, 28 Mar 2020 18:15:14 +0000 (21:15 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Thu, 30 Apr 2020 13:09:18 +0000 (16:09 +0300)
docs/API/pleroma_api.md
lib/pleroma/emoji/pack.ex
lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex
lib/pleroma/web/router.ex
test/web/pleroma_api/controllers/emoji_api_controller_test.exs

index 49b75f5f9c5f6edcce7ffb359ee17b63f056f2ba..65d22980b653094f0afd216c95850ab68f0ec9bd 100644 (file)
@@ -323,27 +323,47 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa
 * Params: None
 * Response: JSON, returns a list of Mastodon Conversation entities that were marked as read (200 - healthy, 503 unhealthy).
 
-## `GET /api/pleroma/emoji/packs`
-### Lists the custom emoji packs on the server
+## `GET /api/pleroma/emoji/packs/import`
+### Imports packs from filesystem
 * Method `GET`
-* Authentication: not required
+* Authentication: required
 * Params: None
-* Response: JSON, "ok" and 200 status and the JSON hashmap of "pack name" to "pack contents"
+* Response: JSON, returns a list of imported packs.
 
-## `GET /api/pleroma/emoji/packs/:name`
-### Get pack.json for the pack
+## `GET /api/pleroma/emoji/packs/remote`
+### Make request to another instance for packs list
 * Method `GET`
-* Authentication: not required
-* Params: None
-* Response: JSON, pack json with `files` and `pack` keys with 200 status or 404 if the pack does not exist
+* Authentication: required
+* Params:
+  * `url`: url of the instance to get packs from
+* Response: JSON with the pack list, hashmap with pack name and pack contents
 
-## `PUT /api/pleroma/emoji/packs/:name`
-### Creates an empty custom emoji pack
-* Method `PUT`
+## `POST /api/pleroma/emoji/packs/download`
+### Download pack from another instance
+* Method `POST`
+* Authentication: required
+* Params:
+  * `url`: url of the instance to download from
+  * `name`: pack to download from that instance
+* Response: JSON, "ok" with 200 status if the pack was downloaded, or 500 if there were
+  errors downloading the pack
+
+## `POST /api/pleroma/emoji/packs/:name`
+### Creates an empty pack
+* Method `POST`
 * Authentication: required
 * Params: None
 * Response: JSON, "ok" and 200 status or 409 if the pack with that name already exists
 
+## `PATCH /api/pleroma/emoji/packs/:name`
+### Updates (replaces) pack metadata
+* Method `POST`
+* Authentication: required
+* Params:
+  * `metadata`: metadata to replace the old one
+* Response: JSON, updated "metadata" section of the pack and 200 status or 400 if there was a
+  problem with the new metadata (the error is specified in the "error" part of the response JSON)
+
 ## `DELETE /api/pleroma/emoji/packs/:name`
 ### Delete a custom emoji pack
 * Method `DELETE`
@@ -351,54 +371,50 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa
 * Params: None
 * Response: JSON, "ok" and 200 status or 500 if there was an error deleting the pack
 
-## `POST /api/pleroma/emoji/packs/:name/update_file`
-### Update a file in a custom emoji pack
+## `POST /api/pleroma/emoji/packs/:name/files`
+### Add new file to the pack
 * Method `POST`
 * Authentication: required
 * Params:
-    * if the `action` is `add`, adds an emoji file to the pack `pack_name`,
-      (thus requiring it to be a multipart request) and be named `file`.
-      If `shortcode` is not specified, `shortcode` will be used from filename.
-      There can also be an optional `filename` that will be the new emoji file name
-      (if it's not there, the name will be taken from the uploaded file).
-    * 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 new_shortcode is used in another emoji 409 status will be returned. If you want to override shortcode
-      pass `force` option with `true` value.
-    * 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
-  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)
-
-## `POST /api/pleroma/emoji/packs/:name/update_metadata`
-### Updates (replaces) pack metadata
-* Method `POST`
-* Authentication: required
-* Params:
-  * `new_data`: new metadata to replace the old one
-* Response: JSON, updated "metadata" section of the pack and 200 status or 400 if there was a
-  problem with the new metadata (the error is specified in the "error" part of the response JSON)
+  * `file`: uploaded file or link to remote file.
+  * `shortcode`: (*optional*) shortcode for new emoji, must be uniq for all emoji. If not sended, shortcode will be taken from original filename.
+  * `filename`: (*optional*) new emoji file name. If not specified will be taken from original filename.
+* Response: JSON, list of files for updated pack (hasmap -> shortcode => filename) with status 200, either error status with error message.
 
-## `POST /api/pleroma/emoji/packs/download_from`
-### Requests the instance to download the pack from another instance
-* Method `POST`
+## `PATCH /api/pleroma/emoji/packs/:name/files`
+### Update emoji file from pack
+* Method `PATCH`
 * Authentication: required
 * Params:
-  * `instance_address`: the address of the instance to download from
-  * `pack_name`: the pack to download from that instance
-* Response: JSON, "ok" and 200 status if the pack was downloaded, or 500 if there were
-  errors downloading the pack
-
-## `POST /api/pleroma/emoji/packs/list_from`
-### Requests the instance to list the packs from another instance
-* Method `POST`
+  * `shortcode`: emoji file shortcode
+  * `new_shortcode`: new emoji file shortcode
+  * `new_filename`: new filename for emoji file
+  * `force`: (*optional*) with true value to overwrite existing emoji with new shortcode
+* Response: JSON, list with updated files for updated pack (hasmap -> shortcode => filename) with status 200, either error status with error message.
+
+## `DELETE /api/pleroma/emoji/packs/:name/files`
+### Delete emoji file from pack
+* Method `DELETE`
 * Authentication: required
 * Params:
-  * `instance_address`: the address of the instance to get packs from
-* Response: JSON with the pack list, same as if the request was made to that instance's
-  list endpoint directly + 200 status
+  * `shortcode`: emoji file shortcode
+* Response: JSON, list with updated files for updated pack (hasmap -> shortcode => filename) with status 200, either error status with error message.
+
+## `GET /api/pleroma/emoji/packs`
+### Lists local custom emoji packs
+* Method `GET`
+* Authentication: not required
+* Params: None
+* Response: JSON, "ok" and 200 status and the JSON hashmap of pack name to pack contents
+
+## `GET /api/pleroma/emoji/packs/:name`
+### Get pack.json for the pack
+* Method `GET`
+* Authentication: not required
+* Params: None
+* Response: JSON, pack json with `files` and `pack` keys with 200 status or 404 if the pack does not exist
 
-## `GET /api/pleroma/emoji/packs/:name/download_shared`
+## `GET /api/pleroma/emoji/packs/:name/archive`
 ### Requests a local pack from the instance
 * Method `GET`
 * Authentication: not required
index 21ed12c7882f53c0f9ec9aee3ae64619d3198429..eb50e52fab32384225e58ae13489c031218ede9e 100644 (file)
@@ -102,9 +102,9 @@ defmodule Pleroma.Emoji.Pack do
     end
   end
 
-  @spec remove_file(String.t(), String.t()) ::
+  @spec delete_file(String.t(), String.t()) ::
           {:ok, t()} | {:error, File.posix()} | {:error, :empty_values}
-  def remove_file(name, shortcode) when byte_size(name) > 0 and byte_size(shortcode) > 0 do
+  def delete_file(name, shortcode) when byte_size(name) > 0 and byte_size(shortcode) > 0 do
     with {_, %__MODULE__{} = pack} <- {:loaded, load_pack(name)},
          {_, {filename, files}} when not is_nil(filename) <-
            {:exists, Map.pop(pack.files, shortcode)},
@@ -131,7 +131,7 @@ defmodule Pleroma.Emoji.Pack do
     end
   end
 
-  def remove_file(_, _), do: {:error, :empty_values}
+  def delete_file(_, _), do: {:error, :empty_values}
 
   @spec update_file(String.t(), String.t(), String.t(), String.t(), boolean()) ::
           {:ok, t()} | {:error, File.posix()} | {:error, :empty_values}
@@ -249,8 +249,8 @@ defmodule Pleroma.Emoji.Pack do
     end
   end
 
-  @spec list_remote_packs(String.t()) :: {:ok, map()}
-  def list_remote_packs(url) do
+  @spec list_remote(String.t()) :: {:ok, map()}
+  def list_remote(url) do
     uri =
       url
       |> String.trim()
@@ -269,8 +269,8 @@ defmodule Pleroma.Emoji.Pack do
     end
   end
 
-  @spec list_local_packs() :: {:ok, map()}
-  def list_local_packs do
+  @spec list_local() :: {:ok, map()}
+  def list_local do
     emoji_path = emoji_path()
 
     # Create the directory first if it does not exist. This is probably the first request made
@@ -315,8 +315,8 @@ defmodule Pleroma.Emoji.Pack do
       end)
   end
 
-  @spec download(String.t()) :: {:ok, binary()}
-  def download(name) do
+  @spec get_archive(String.t()) :: {:ok, binary()}
+  def get_archive(name) do
     with {_, %__MODULE__{} = pack} <- {:exists?, load_pack(name)},
          {_, true} <- {:can_download?, downloadable?(pack)} do
       {:ok, fetch_archive(pack)}
@@ -356,15 +356,14 @@ defmodule Pleroma.Emoji.Pack do
     result
   end
 
-  @spec download_from_source(String.t(), String.t(), String.t()) :: :ok
-  def download_from_source(name, url, as) do
+  @spec download(String.t(), String.t(), String.t()) :: :ok
+  def download(name, url, as) do
     uri =
       url
       |> String.trim()
       |> URI.parse()
 
     with {_, true} <- {:shareable, shareable_packs_available?(uri)} do
-      # TODO: why do we load all packs, if we know the name of pack we need
       remote_pack =
         uri
         |> URI.merge("/api/pleroma/emoji/packs/#{name}")
@@ -379,8 +378,7 @@ defmodule Pleroma.Emoji.Pack do
             {:ok,
              %{
                sha: sha,
-               url:
-                 URI.merge(uri, "/api/pleroma/emoji/packs/#{name}/download_shared") |> to_string()
+               url: URI.merge(uri, "/api/pleroma/emoji/packs/#{name}/archive") |> to_string()
              }}
 
           %{"fallback-src" => src, "fallback-src-sha256" => sha} when is_binary(src) ->
index 9fa8574749a12383c9be91a729508a3c83098c96..83a7f03e8b0a382493d2eae290e674523bc0417c 100644 (file)
@@ -7,12 +7,15 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     Pleroma.Plugs.OAuthScopesPlug,
     %{scopes: ["write"], admin: true}
     when action in [
+           :import,
+           :remote,
+           :download,
            :create,
+           :update,
            :delete,
-           :download_from,
-           :import_from_fs,
+           :add_file,
            :update_file,
-           :update_metadata
+           :delete_file
          ]
   )
 
@@ -22,14 +25,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     when action in [:download_shared, :list_packs, :list_from]
   )
 
-  @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
-    with {:ok, packs} <- Pack.list_remote_packs(address) do
+  def remote(conn, %{"url" => url}) do
+    with {:ok, packs} <- Pack.list_remote(url) do
       json(conn, packs)
     else
       {:shareable, _} ->
@@ -39,20 +36,14 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     end
   end
 
-  @doc """
-  Lists the packs available on the instance as JSON.
-
-  The information is public and does not require authentication. The format is
-  a map of "pack directory name" to pack.json contents.
-  """
-  def list_packs(conn, _params) do
+  def list(conn, _params) do
     emoji_path =
       Path.join(
         Pleroma.Config.get!([:instance, :static_dir]),
         "emoji"
       )
 
-    with {:ok, packs} <- Pack.list_local_packs() do
+    with {:ok, packs} <- Pack.list_local() do
       json(conn, packs)
     else
       {:create_dir, {:error, e}} ->
@@ -87,12 +78,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     end
   end
 
-  @doc """
-  An endpoint for other instances (via admin UI) or users (via browser)
-  to download packs that the instance shares.
-  """
-  def download_shared(conn, %{"name" => name}) do
-    with {:ok, archive} <- Pack.download(name) do
+  def archive(conn, %{"name" => name}) do
+    with {:ok, archive} <- Pack.get_archive(name) do
       send_download(conn, {:binary, archive}, filename: "#{name}.zip")
     else
       {:can_download?, _} ->
@@ -110,15 +97,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     end
   end
 
-  @doc """
-  An admin endpoint to request downloading and storing a pack named `pack_name` from the instance
-  `instance_address`.
-
-  If the requested instance's admin chose to share the pack, it will be downloaded
-  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} = params) do
-    with :ok <- Pack.download_from_source(name, address, params["as"]) do
+  def download(conn, %{"url" => url, "name" => name} = params) do
+    with :ok <- Pack.download(name, url, params["as"]) do
       json(conn, "ok")
     else
       {:shareable, _} ->
@@ -138,9 +118,6 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     end
   end
 
-  @doc """
-  Creates an empty pack named `name` which then can be updated via the admin UI.
-  """
   def create(conn, %{"name" => name}) do
     name = String.trim(name)
 
@@ -166,9 +143,6 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     end
   end
 
-  @doc """
-  Deletes the pack `name` and all it's files.
-  """
   def delete(conn, %{"name" => name}) do
     name = String.trim(name)
 
@@ -192,13 +166,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     end
   end
 
-  @doc """
-  An endpoint to update `pack_names`'s metadata.
-
-  `new_data` is the new metadata for the pack, that will replace the old metadata.
-  """
-  def update_metadata(conn, %{"pack_name" => name, "new_data" => new_data}) do
-    with {:ok, pack} <- Pack.update_metadata(name, new_data) do
+  def update(conn, %{"name" => name, "metadata" => metadata}) do
+    with {:ok, pack} <- Pack.update_metadata(name, metadata) do
       json(conn, pack.pack)
     else
       {:has_all_files?, _} ->
@@ -215,30 +184,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     end
   end
 
-  @doc """
-  Updates a file in a pack.
-
-  Updating can mean three things:
-
-  - `add` adds an emoji named `shortcode` to the pack `pack_name`,
-    that means that the emoji file needs to be uploaded with the request
-    (thus requiring it to be a multipart request) and be named `file`.
-    There can also be an optional `filename` that will be the new emoji file name
-    (if it's not there, the name will be taken from the uploaded file).
-  - `update` changes emoji shortcode (from `shortcode` to `new_shortcode` or moves the file
-    (from the current filename to `new_filename`)
-  - `remove` removes the emoji named `shortcode` and it's associated file
-  """
-
-  # Add
-  def update_file(
-        conn,
-        %{"pack_name" => pack_name, "action" => "add"} = params
-      ) do
+  def add_file(conn, %{"name" => name} = params) do
     filename = params["filename"] || get_filename(params["file"])
     shortcode = params["shortcode"] || Path.basename(filename, Path.extname(filename))
 
-    with {:ok, pack} <- Pack.add_file(pack_name, shortcode, filename, params["file"]) do
+    with {:ok, pack} <- Pack.add_file(name, shortcode, filename, params["file"]) do
       json(conn, pack.files)
     else
       {:exists, _} ->
@@ -249,7 +199,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
       {:loaded, _} ->
         conn
         |> put_status(:bad_request)
-        |> json(%{error: "pack \"#{pack_name}\" is not found"})
+        |> json(%{error: "pack \"#{name}\" is not found"})
 
       {:error, :empty_values} ->
         conn
@@ -265,13 +215,12 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
     end
   end
 
-  # Remove
-  def update_file(conn, %{
-        "pack_name" => pack_name,
-        "action" => "remove",
-        "shortcode" => shortcode
-      }) do
-    with {:ok, pack} <- Pack.remove_file(pack_name, shortcode) do
+  def update_file(conn, %{"name" => name, "shortcode" => shortcode} = params) do
+    new_shortcode = params["new_shortcode"]
+    new_filename = params["new_filename"]
+    force = params["force"] == true
+
+    with {:ok, pack} <- Pack.update_file(name, shortcode, new_shortcode, new_filename, force) do
       json(conn, pack.files)
     else
       {:exists, _} ->
@@ -279,35 +228,35 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
         |> put_status(:bad_request)
         |> json(%{error: "Emoji \"#{shortcode}\" does not exist"})
 
+      {:not_used, _} ->
+        conn
+        |> put_status(:conflict)
+        |> json(%{
+          error:
+            "New shortcode \"#{new_shortcode}\" is already used. If you want to override emoji use 'force' option"
+        })
+
       {:loaded, _} ->
         conn
         |> put_status(:bad_request)
-        |> json(%{error: "pack \"#{pack_name}\" is not found"})
+        |> json(%{error: "pack \"#{name}\" is not found"})
 
       {:error, :empty_values} ->
         conn
         |> put_status(:bad_request)
-        |> json(%{error: "pack name or shortcode cannot be empty"})
+        |> json(%{error: "new_shortcode or new_filename cannot be empty"})
 
       {:error, _} ->
         render_error(
           conn,
           :internal_server_error,
-          "Unexpected error occurred while removing file from pack."
+          "Unexpected error occurred while updating file in pack."
         )
     end
   end
 
-  # Update
-  def update_file(
-        conn,
-        %{"pack_name" => name, "action" => "update", "shortcode" => shortcode} = params
-      ) do
-    new_shortcode = params["new_shortcode"]
-    new_filename = params["new_filename"]
-    force = params["force"] == true
-
-    with {:ok, pack} <- Pack.update_file(name, shortcode, new_shortcode, new_filename, force) do
+  def delete_file(conn, %{"name" => name, "shortcode" => shortcode}) do
+    with {:ok, pack} <- Pack.delete_file(name, shortcode) do
       json(conn, pack.files)
     else
       {:exists, _} ->
@@ -315,14 +264,6 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
         |> put_status(:bad_request)
         |> json(%{error: "Emoji \"#{shortcode}\" does not exist"})
 
-      {:not_used, _} ->
-        conn
-        |> put_status(:conflict)
-        |> json(%{
-          error:
-            "New shortcode \"#{new_shortcode}\" is already used. If you want to override emoji use 'force' option"
-        })
-
       {:loaded, _} ->
         conn
         |> put_status(:bad_request)
@@ -331,35 +272,18 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do
       {:error, :empty_values} ->
         conn
         |> put_status(:bad_request)
-        |> json(%{error: "new_shortcode or new_filename cannot be empty"})
+        |> json(%{error: "pack name or shortcode cannot be empty"})
 
       {:error, _} ->
         render_error(
           conn,
           :internal_server_error,
-          "Unexpected error occurred while updating file in pack."
+          "Unexpected error occurred while removing file from pack."
         )
     end
   end
 
-  def update_file(conn, %{"action" => action}) do
-    conn
-    |> put_status(:bad_request)
-    |> json(%{error: "Unknown action: #{action}"})
-  end
-
-  @doc """
-  Imports emoji from the filesystem.
-
-  Importing means checking all the directories in the
-  `$instance_static/emoji/` for directories which do not have
-  `pack.json`. If one has an emoji.txt file, that file will be used
-  to create a `pack.json` file with it's contents. If the directory has
-  neither, all the files with specific configured extenstions will be
-  assumed to be emojis and stored in the new `pack.json` file.
-  """
-
-  def import_from_fs(conn, _params) do
+  def import_from_filesystem(conn, _params) do
     with {:ok, names} <- Pack.import_from_filesystem() do
       json(conn, names)
     else
index 0fcb517cfaaf3ef907bc7e0735a2483e4ab1f6bc..a7e1f2f57a43032c589b88a6adaf8b9b99cb414a 100644 (file)
@@ -214,25 +214,24 @@ defmodule Pleroma.Web.Router do
     scope "/packs" do
       pipe_through(:admin_api)
 
-      post("/import_from_fs", EmojiAPIController, :import_from_fs)
-      post("/:pack_name/update_file", EmojiAPIController, :update_file)
-      post("/:pack_name/update_metadata", EmojiAPIController, :update_metadata)
-      put("/:name", EmojiAPIController, :create)
+      get("/import", EmojiAPIController, :import_from_filesystem)
+      get("/remote", EmojiAPIController, :remote)
+      post("/download", EmojiAPIController, :download)
+
+      post("/:name", EmojiAPIController, :create)
+      patch("/:name", EmojiAPIController, :update)
       delete("/:name", EmojiAPIController, :delete)
 
-      # Note: /download_from downloads and saves to instance, not to requester
-      post("/download_from", EmojiAPIController, :download_from)
+      post("/:name/files", EmojiAPIController, :add_file)
+      patch("/:name/files", EmojiAPIController, :update_file)
+      delete("/:name/files", EmojiAPIController, :delete_file)
     end
 
     # Pack info / downloading
     scope "/packs" do
-      get("/", EmojiAPIController, :list_packs)
+      get("/", EmojiAPIController, :list)
       get("/:name", EmojiAPIController, :show)
-      get("/:name/download_shared/", EmojiAPIController, :download_shared)
-      get("/list_from", EmojiAPIController, :list_from)
-
-      # Deprecated: POST /api/pleroma/emoji/packs/list_from (use GET instead)
-      post("/list_from", EmojiAPIController, :list_from)
+      get("/:name/archive", EmojiAPIController, :archive)
     end
   end
 
index 6a0d7dd11f93a2ce89a1587eba6824dd5d85f8f3..d343256fe2652473e5e4dd8f9d9668808460b806 100644 (file)
@@ -41,7 +41,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
     assert non_shared["pack"]["can-download"] == false
   end
 
-  describe "POST /api/pleroma/emoji/packs/list_from" do
+  describe "GET /api/pleroma/emoji/packs/remote" do
     test "shareable instance", %{admin_conn: admin_conn, conn: conn} do
       resp =
         conn
@@ -60,8 +60,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       end)
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/list_from", %{
-               instance_address: "https://example.com"
+             |> get("/api/pleroma/emoji/packs/remote", %{
+               url: "https://example.com"
              })
              |> json_response(200) == resp
     end
@@ -76,20 +76,18 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       end)
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/list_from", %{
-               instance_address: "https://example.com"
-             })
+             |> get("/api/pleroma/emoji/packs/remote", %{url: "https://example.com"})
              |> json_response(500) == %{
                "error" => "The requested instance does not support sharing emoji packs"
              }
     end
   end
 
-  describe "GET /api/pleroma/emoji/packs/:name/download_shared" do
+  describe "GET /api/pleroma/emoji/packs/:name/archive" do
     test "download shared pack", %{conn: conn} do
       resp =
         conn
-        |> get("/api/pleroma/emoji/packs/test_pack/download_shared")
+        |> get("/api/pleroma/emoji/packs/test_pack/archive")
         |> response(200)
 
       {:ok, arch} = :zip.unzip(resp, [:memory])
@@ -100,7 +98,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "non existing pack", %{conn: conn} do
       assert conn
-             |> get("/api/pleroma/emoji/packs/test_pack_for_import/download_shared")
+             |> get("/api/pleroma/emoji/packs/test_pack_for_import/archive")
              |> json_response(:not_found) == %{
                "error" => "Pack test_pack_for_import does not exist"
              }
@@ -108,7 +106,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "non downloadable pack", %{conn: conn} do
       assert conn
-             |> get("/api/pleroma/emoji/packs/test_pack_nonshared/download_shared")
+             |> get("/api/pleroma/emoji/packs/test_pack_nonshared/archive")
              |> json_response(:forbidden) == %{
                "error" =>
                  "Pack test_pack_nonshared cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing"
@@ -116,7 +114,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
     end
   end
 
-  describe "POST /api/pleroma/emoji/packs/download_from" do
+  describe "POST /api/pleroma/emoji/packs/download" do
     test "shared pack from remote and non shared from fallback-src", %{
       admin_conn: admin_conn,
       conn: conn
@@ -139,10 +137,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
         %{
           method: :get,
-          url: "https://example.com/api/pleroma/emoji/packs/test_pack/download_shared"
+          url: "https://example.com/api/pleroma/emoji/packs/test_pack/archive"
         } ->
           conn
-          |> get("/api/pleroma/emoji/packs/test_pack/download_shared")
+          |> get("/api/pleroma/emoji/packs/test_pack/archive")
           |> response(200)
           |> text()
 
@@ -163,9 +161,9 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       end)
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/download_from", %{
-               instance_address: "https://example.com",
-               pack_name: "test_pack",
+             |> post("/api/pleroma/emoji/packs/download", %{
+               url: "https://example.com",
+               name: "test_pack",
                as: "test_pack2"
              })
              |> json_response(200) == "ok"
@@ -181,10 +179,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
       assert admin_conn
              |> post(
-               "/api/pleroma/emoji/packs/download_from",
+               "/api/pleroma/emoji/packs/download",
                %{
-                 instance_address: "https://example.com",
-                 pack_name: "test_pack_nonshared",
+                 url: "https://example.com",
+                 name: "test_pack_nonshared",
                  as: "test_pack_nonshared2"
                }
              )
@@ -211,10 +209,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
       assert admin_conn
              |> post(
-               "/api/pleroma/emoji/packs/download_from",
+               "/api/pleroma/emoji/packs/download",
                %{
-                 instance_address: "https://old-instance",
-                 pack_name: "test_pack",
+                 url: "https://old-instance",
+                 name: "test_pack",
                  as: "test_pack2"
                }
              )
@@ -242,7 +240,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
         %{
           method: :get,
-          url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha/download_shared"
+          url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha/archive"
         } ->
           %Tesla.Env{
             status: 200,
@@ -251,9 +249,9 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       end)
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/download_from", %{
-               instance_address: "https://example.com",
-               pack_name: "pack_bad_sha",
+             |> post("/api/pleroma/emoji/packs/download", %{
+               url: "https://example.com",
+               name: "pack_bad_sha",
                as: "pack_bad_sha2"
              })
              |> json_response(:internal_server_error) == %{
@@ -275,23 +273,14 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
         } ->
           %Tesla.Env{
             status: 200,
-            body: %{"test_pack" => Pleroma.Emoji.Pack.load_pack("test_pack")} |> Jason.encode!()
-          }
-
-        %{
-          method: :get,
-          url: "https://example.com/api/pleroma/emoji/packs/test_pack/download_shared"
-        } ->
-          %Tesla.Env{
-            status: 200,
-            body: File.read!("test/instance_static/emoji/test_pack/pack.json")
+            body: Pleroma.Emoji.Pack.load_pack("test_pack") |> Jason.encode!()
           }
       end)
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/download_from", %{
-               instance_address: "https://example.com",
-               pack_name: "test_pack",
+             |> post("/api/pleroma/emoji/packs/download", %{
+               url: "https://example.com",
+               name: "test_pack",
                as: "test_pack2"
              })
              |> json_response(:internal_server_error) == %{
@@ -301,7 +290,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
     end
   end
 
-  describe "updating pack metadata" do
+  describe "PATCH /api/pleroma/emoji/packs/:name" do
     setup do
       pack_file = "#{@emoji_path}/test_pack/pack.json"
       original_content = File.read!(pack_file)
@@ -322,12 +311,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "for a pack without a fallback source", ctx do
       assert ctx[:admin_conn]
-             |> post(
-               "/api/pleroma/emoji/packs/test_pack/update_metadata",
-               %{
-                 "new_data" => ctx[:new_data]
-               }
-             )
+             |> patch("/api/pleroma/emoji/packs/test_pack", %{"metadata" => ctx[:new_data]})
              |> json_response(200) == ctx[:new_data]
 
       assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data]
@@ -352,12 +336,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
         )
 
       assert ctx[:admin_conn]
-             |> post(
-               "/api/pleroma/emoji/packs/test_pack/update_metadata",
-               %{
-                 "new_data" => new_data
-               }
-             )
+             |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data})
              |> json_response(200) == new_data_with_sha
 
       assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha
@@ -376,19 +355,14 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
 
       assert ctx[:admin_conn]
-             |> post(
-               "/api/pleroma/emoji/packs/test_pack/update_metadata",
-               %{
-                 "new_data" => new_data
-               }
-             )
+             |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data})
              |> json_response(:bad_request) == %{
                "error" => "The fallback archive does not have all files specified in pack.json"
              }
     end
   end
 
-  describe "POST /api/pleroma/emoji/packs/:pack_name/update_file" do
+  describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/:name/files" do
     setup do
       pack_file = "#{@emoji_path}/test_pack/pack.json"
       original_content = File.read!(pack_file)
@@ -402,11 +376,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "create shortcode exists", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "add",
-               "shortcode" => "blank",
-               "filename" => "dir/blank.png",
-               "file" => %Plug.Upload{
+             |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank",
+               filename: "dir/blank.png",
+               file: %Plug.Upload{
                  filename: "blank.png",
                  path: "#{@emoji_path}/test_pack/blank.png"
                }
@@ -420,11 +393,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir/") end)
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "add",
-               "shortcode" => "blank2",
-               "filename" => "dir/blank.png",
-               "file" => %Plug.Upload{
+             |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank2",
+               filename: "dir/blank.png",
+               file: %Plug.Upload{
                  filename: "blank.png",
                  path: "#{@emoji_path}/test_pack/blank.png"
                }
@@ -434,11 +406,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "update",
-               "shortcode" => "blank",
-               "new_shortcode" => "blank2",
-               "new_filename" => "dir_2/blank_3.png"
+             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank",
+               new_shortcode: "blank2",
+               new_filename: "dir_2/blank_3.png"
              })
              |> json_response(:conflict) == %{
                "error" =>
@@ -450,11 +421,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir_2/") end)
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "add",
-               "shortcode" => "blank2",
-               "filename" => "dir/blank.png",
-               "file" => %Plug.Upload{
+             |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank2",
+               filename: "dir/blank.png",
+               file: %Plug.Upload{
                  filename: "blank.png",
                  path: "#{@emoji_path}/test_pack/blank.png"
                }
@@ -464,12 +434,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "update",
-               "shortcode" => "blank2",
-               "new_shortcode" => "blank3",
-               "new_filename" => "dir_2/blank_3.png",
-               "force" => true
+             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank2",
+               new_shortcode: "blank3",
+               new_filename: "dir_2/blank_3.png",
+               force: true
              })
              |> json_response(200) == %{
                "blank" => "blank.png",
@@ -481,11 +450,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "with empty filename", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "add",
-               "shortcode" => "blank2",
-               "filename" => "",
-               "file" => %Plug.Upload{
+             |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank2",
+               filename: "",
+               file: %Plug.Upload{
                  filename: "blank.png",
                  path: "#{@emoji_path}/test_pack/blank.png"
                }
@@ -497,11 +465,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "add file with not loaded pack", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/not_loaded/update_file", %{
-               "action" => "add",
-               "shortcode" => "blank2",
-               "filename" => "dir/blank.png",
-               "file" => %Plug.Upload{
+             |> post("/api/pleroma/emoji/packs/not_loaded/files", %{
+               shortcode: "blank2",
+               filename: "dir/blank.png",
+               file: %Plug.Upload{
                  filename: "blank.png",
                  path: "#{@emoji_path}/test_pack/blank.png"
                }
@@ -513,19 +480,13 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "remove file with not loaded pack", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/not_loaded/update_file", %{
-               "action" => "remove",
-               "shortcode" => "blank3"
-             })
+             |> delete("/api/pleroma/emoji/packs/not_loaded/files", %{shortcode: "blank3"})
              |> json_response(:bad_request) == %{"error" => "pack \"not_loaded\" is not found"}
     end
 
     test "remove file with empty shortcode", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/not_loaded/update_file", %{
-               "action" => "remove",
-               "shortcode" => ""
-             })
+             |> delete("/api/pleroma/emoji/packs/not_loaded/files", %{shortcode: ""})
              |> json_response(:bad_request) == %{
                "error" => "pack name or shortcode cannot be empty"
              }
@@ -533,22 +494,20 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "update file with not loaded pack", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/not_loaded/update_file", %{
-               "action" => "update",
-               "shortcode" => "blank4",
-               "new_shortcode" => "blank3",
-               "new_filename" => "dir_2/blank_3.png"
+             |> patch("/api/pleroma/emoji/packs/not_loaded/files", %{
+               shortcode: "blank4",
+               new_shortcode: "blank3",
+               new_filename: "dir_2/blank_3.png"
              })
              |> json_response(:bad_request) == %{"error" => "pack \"not_loaded\" is not found"}
     end
 
     test "new with shortcode as file with update", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "add",
-               "shortcode" => "blank4",
-               "filename" => "dir/blank.png",
-               "file" => %Plug.Upload{
+             |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank4",
+               filename: "dir/blank.png",
+               file: %Plug.Upload{
                  filename: "blank.png",
                  path: "#{@emoji_path}/test_pack/blank.png"
                }
@@ -558,11 +517,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "update",
-               "shortcode" => "blank4",
-               "new_shortcode" => "blank3",
-               "new_filename" => "dir_2/blank_3.png"
+             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank4",
+               new_shortcode: "blank3",
+               new_filename: "dir_2/blank_3.png"
              })
              |> json_response(200) == %{"blank3" => "dir_2/blank_3.png", "blank" => "blank.png"}
 
@@ -570,10 +528,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "remove",
-               "shortcode" => "blank3"
-             })
+             |> delete("/api/pleroma/emoji/packs/test_pack/files", %{shortcode: "blank3"})
              |> json_response(200) == %{"blank" => "blank.png"}
 
       refute File.exists?("#{@emoji_path}/test_pack/dir_2/")
@@ -591,10 +546,9 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       end)
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "add",
-               "shortcode" => "blank_url",
-               "file" => "https://test-blank/blank_url.png"
+             |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank_url",
+               file: "https://test-blank/blank_url.png"
              })
              |> json_response(200) == %{
                "blank_url" => "blank_url.png",
@@ -610,9 +564,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/shortcode.png") end)
 
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "add",
-               "file" => %Plug.Upload{
+             |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+               file: %Plug.Upload{
                  filename: "shortcode.png",
                  path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png"
                }
@@ -622,51 +575,36 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "remove",
-               "shortcode" => "blank2"
-             })
+             |> delete("/api/pleroma/emoji/packs/test_pack/files", %{shortcode: "blank2"})
              |> json_response(:bad_request) == %{"error" => "Emoji \"blank2\" does not exist"}
     end
 
     test "update non existing emoji", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "update",
-               "shortcode" => "blank2",
-               "new_shortcode" => "blank3",
-               "new_filename" => "dir_2/blank_3.png"
+             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank2",
+               new_shortcode: "blank3",
+               new_filename: "dir_2/blank_3.png"
              })
              |> json_response(:bad_request) == %{"error" => "Emoji \"blank2\" does not exist"}
     end
 
     test "update with empty shortcode", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "update",
-               "shortcode" => "blank",
-               "new_filename" => "dir_2/blank_3.png"
+             |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+               shortcode: "blank",
+               new_filename: "dir_2/blank_3.png"
              })
              |> json_response(:bad_request) == %{
                "error" => "new_shortcode or new_filename cannot be empty"
              }
     end
-
-    test "undefined action", %{admin_conn: admin_conn} do
-      assert admin_conn
-             |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
-               "action" => "undefined"
-             })
-             |> json_response(:bad_request) == %{
-               "error" => "Unknown action: undefined"
-             }
-    end
   end
 
-  describe "PUT /api/pleroma/emoji/packs/:name" do
+  describe "POST/DELETE /api/pleroma/emoji/packs/:name" do
     test "creating and deleting a pack", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> put("/api/pleroma/emoji/packs/test_created")
+             |> post("/api/pleroma/emoji/packs/test_created")
              |> json_response(200) == "ok"
 
       assert File.exists?("#{@emoji_path}/test_created/pack.json")
@@ -690,7 +628,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
       File.write!(Path.join(path, "pack.json"), pack_file)
 
       assert admin_conn
-             |> put("/api/pleroma/emoji/packs/test_created")
+             |> post("/api/pleroma/emoji/packs/test_created")
              |> json_response(:conflict) == %{
                "error" => "A pack named \"test_created\" already exists"
              }
@@ -700,7 +638,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
 
     test "with empty name", %{admin_conn: admin_conn} do
       assert admin_conn
-             |> put("/api/pleroma/emoji/packs/ ")
+             |> post("/api/pleroma/emoji/packs/ ")
              |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"}
     end
   end
@@ -728,7 +666,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
     refute Map.has_key?(resp, "test_pack_for_import")
 
     assert admin_conn
-           |> post("/api/pleroma/emoji/packs/import_from_fs")
+           |> get("/api/pleroma/emoji/packs/import")
            |> json_response(200) == ["test_pack_for_import"]
 
     resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)
@@ -747,7 +685,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
     File.write!("#{@emoji_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
 
     assert admin_conn
-           |> post("/api/pleroma/emoji/packs/import_from_fs")
+           |> get("/api/pleroma/emoji/packs/import")
            |> json_response(200) == ["test_pack_for_import"]
 
     resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)