commit: 321bd75dca71e395544c05de3583261a2793c7af
parent 7042495d7c683026dfb4711a54db92ed869b24ad
Author: Ekaterina Vaartis <vaartis@kotobank.ch>
Date: Tue, 14 Jan 2025 02:02:46 +0300
Add a way to upload emoji pack from zip/url easily
Essentially the same as the mix task
Diffstat:
5 files changed, 127 insertions(+), 0 deletions(-)
diff --git a/changelog.d/emoji-pack-upload-zip.add b/changelog.d/emoji-pack-upload-zip.add
@@ -0,0 +1 @@
+Added a way to upload new packs from a URL or ZIP file via Admin API
+\ No newline at end of file
diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex
@@ -225,6 +225,67 @@ defmodule Pleroma.Emoji.Pack do
end
end
+ def download_zip(name, opts \\ %{}) do
+ pack_path =
+ Path.join([
+ Pleroma.Config.get!([:instance, :static_dir]),
+ "emoji",
+ name
+ ])
+
+ with {_, false} <-
+ {"Pack already exists, refusing to import #{name}", File.exists?(pack_path)},
+ {_, :ok} <- {"Could not create the pack directory", File.mkdir_p(pack_path)},
+ {_, {:ok, %{body: binary_archive}}} <-
+ (case opts do
+ %{url: url} ->
+ {"Could not download pack", Pleroma.HTTP.get(url)}
+
+ %{file: file} ->
+ case File.read(file.path) do
+ {:ok, data} -> {nil, {:ok, %{body: data}}}
+ {:error, _e} -> {"Could not read the uploaded pack file", :error}
+ end
+
+ _ ->
+ {"Neither file nor URL was present in the request", :error}
+ end),
+ {_, {:ok, _}} <-
+ {"Could not unzip pack",
+ :zip.unzip(binary_archive, cwd: String.to_charlist(pack_path))} do
+ # Get the pack SHA
+ archive_sha = :crypto.hash(:sha256, binary_archive) |> Base.encode16()
+
+ pack_json_path = Path.join([pack_path, "pack.json"])
+ # Make a json if it does not exist
+ if not File.exists?(pack_json_path) do
+ # Make a list of the emojis
+ emoji_map =
+ Pleroma.Emoji.Loader.make_shortcode_to_file_map(
+ pack_path,
+ Map.get(opts, :exts, [".png", ".gif", ".jpg"])
+ )
+
+ pack_json = %{
+ pack: %{
+ license: Map.get(opts, :license, ""),
+ homepage: Map.get(opts, :homepage, ""),
+ description: Map.get(opts, :description, ""),
+ src: Map.get(opts, :url),
+ src_sha256: archive_sha
+ },
+ files: emoji_map
+ }
+
+ File.write!(pack_json_path, Jason.encode!(pack_json, pretty: true))
+ end
+
+ :ok
+ else
+ {err, _} -> {:error, err}
+ end
+ end
+
@spec download(String.t(), String.t(), String.t()) :: {:ok, t()} | {:error, atom()}
def download(name, url, as) do
uri = url |> String.trim() |> URI.parse()
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex
@@ -127,6 +127,20 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
}
end
+ def download_zip_operation do
+ %Operation{
+ tags: ["Emoji pack administration"],
+ summary: "Download a pack from a URL or an uploaded file",
+ operationId: "PleromaAPI.EmojiPackController.download_zip",
+ security: [%{"oAuth" => ["admin:write"]}],
+ requestBody: request_body("Parameters", download_zip_request(), required: true),
+ responses: %{
+ 200 => ok_response(),
+ 400 => Operation.response("Bad Request", "application/json", ApiError)
+ }
+ }
+ end
+
defp download_request do
%Schema{
type: :object,
@@ -143,6 +157,25 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
}
end
+ defp download_zip_request do
+ %Schema{
+ type: :object,
+ required: [:name],
+ properties: %{
+ url: %Schema{
+ type: :string,
+ format: :uri,
+ description: "URL of the file"
+ },
+ file: %Schema{
+ description: "The uploaded ZIP file",
+ type: :object
+ },
+ name: %Schema{type: :string, format: :uri, description: "Pack Name"}
+ }
+ }
+ end
+
def create_operation do
%Operation{
tags: ["Emoji pack administration"],
diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex
@@ -16,6 +16,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
:import_from_filesystem,
:remote,
:download,
+ :download_zip,
:create,
:update,
:delete
@@ -113,6 +114,35 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end
end
+ def download_zip(
+ %{private: %{open_api_spex: %{body_params: %{url: url, name: name}}}} = conn,
+ _
+ ) do
+ with :ok <- Pack.download_zip(name, %{url: url}) do
+ json(conn, "ok")
+ else
+ {:error, error} ->
+ conn
+ |> put_status(:bad_request)
+ |> json(%{error: error})
+ end
+ end
+
+ def download_zip(
+ %{private: %{open_api_spex: %{body_params: %{file: %Plug.Upload{} = file, name: name}}}} =
+ conn,
+ _
+ ) do
+ with :ok <- Pack.download_zip(name, %{file: file}) do
+ json(conn, "ok")
+ else
+ {:error, error} ->
+ conn
+ |> put_status(:bad_request)
+ |> json(%{error: error})
+ end
+ end
+
def download(
%{private: %{open_api_spex: %{body_params: %{url: url, name: name} = params}}} = conn,
_
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
@@ -466,6 +466,7 @@ defmodule Pleroma.Web.Router do
get("/import", EmojiPackController, :import_from_filesystem)
get("/remote", EmojiPackController, :remote)
post("/download", EmojiPackController, :download)
+ post("/download_zip", EmojiPackController, :download_zip)
post("/files", EmojiFileController, :create)
patch("/files", EmojiFileController, :update)