forked from AkkomaGang/akkoma
A feature for shareable emoji packs, use it in download_from & tests
This commit is contained in:
parent
74fb6d8647
commit
36f2275dc9
3 changed files with 88 additions and 50 deletions
|
@ -153,64 +153,79 @@ def download_shared(conn, %{"name" => name}) do
|
||||||
from that instance, otherwise it will be downloaded from the fallback source, if there is one.
|
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
|
def download_from(conn, %{"instance_address" => address, "pack_name" => name} = data) do
|
||||||
full_pack =
|
shareable_packs_available =
|
||||||
"#{address}/api/pleroma/emoji/packs/list"
|
"#{address}/nodeinfo/2.1.json"
|
||||||
|> Tesla.get!()
|
|> Tesla.get!()
|
||||||
|> Map.get(:body)
|
|> Map.get(:body)
|
||||||
|> Jason.decode!()
|
|> Jason.decode!()
|
||||||
|> Map.get(name)
|
|> Map.get("features")
|
||||||
|
|> Enum.member?("shareable_emoji_packs")
|
||||||
|
|
||||||
pack_info_res =
|
if shareable_packs_available do
|
||||||
case full_pack["pack"] do
|
full_pack =
|
||||||
%{"share-files" => true, "can-download" => true, "download-sha256" => sha} ->
|
"#{address}/api/pleroma/emoji/packs/list"
|
||||||
{:ok,
|
|> Tesla.get!()
|
||||||
%{
|
|> Map.get(:body)
|
||||||
sha: sha,
|
|> Jason.decode!()
|
||||||
uri: "#{address}/api/pleroma/emoji/packs/download_shared/#{name}"
|
|> Map.get(name)
|
||||||
}}
|
|
||||||
|
|
||||||
%{"fallback-src" => src, "fallback-src-sha256" => sha} when is_binary(src) ->
|
pack_info_res =
|
||||||
{:ok,
|
case full_pack["pack"] do
|
||||||
%{
|
%{"share-files" => true, "can-download" => true, "download-sha256" => sha} ->
|
||||||
sha: sha,
|
{:ok,
|
||||||
uri: src,
|
%{
|
||||||
fallback: true
|
sha: sha,
|
||||||
}}
|
uri: "#{address}/api/pleroma/emoji/packs/download_shared/#{name}"
|
||||||
|
}}
|
||||||
|
|
||||||
_ ->
|
%{"fallback-src" => src, "fallback-src-sha256" => sha} when is_binary(src) ->
|
||||||
{:error, "The pack was not set as shared and there is no fallback src to download from"}
|
{:ok,
|
||||||
|
%{
|
||||||
|
sha: sha,
|
||||||
|
uri: src,
|
||||||
|
fallback: true
|
||||||
|
}}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:error,
|
||||||
|
"The pack was not set as shared and there is no fallback src to download from"}
|
||||||
|
end
|
||||||
|
|
||||||
|
with {:ok, %{sha: sha, uri: uri} = pinfo} <- pack_info_res,
|
||||||
|
%{body: emoji_archive} <- Tesla.get!(uri),
|
||||||
|
{_, true} <- {:checksum, Base.decode16!(sha) == :crypto.hash(:sha256, emoji_archive)} do
|
||||||
|
local_name = data["as"] || name
|
||||||
|
pack_dir = Path.join(@emoji_dir_path, local_name)
|
||||||
|
File.mkdir_p!(pack_dir)
|
||||||
|
|
||||||
|
files = Enum.map(full_pack["files"], fn {_, path} -> to_charlist(path) end)
|
||||||
|
# Fallback cannot contain a pack.json file
|
||||||
|
files = if pinfo[:fallback], do: files, else: ['pack.json'] ++ files
|
||||||
|
|
||||||
|
{:ok, _} = :zip.unzip(emoji_archive, cwd: to_charlist(pack_dir), file_list: files)
|
||||||
|
|
||||||
|
# Fallback can't contain a pack.json file, since that would cause the fallback-src-sha256
|
||||||
|
# in it to depend on itself
|
||||||
|
if pinfo[:fallback] do
|
||||||
|
pack_file_path = Path.join(pack_dir, "pack.json")
|
||||||
|
|
||||||
|
File.write!(pack_file_path, Jason.encode!(full_pack, pretty: true))
|
||||||
|
end
|
||||||
|
|
||||||
|
json(conn, "ok")
|
||||||
|
else
|
||||||
|
{:error, e} ->
|
||||||
|
conn |> put_status(:internal_server_error) |> json(%{error: e})
|
||||||
|
|
||||||
|
{:checksum, _} ->
|
||||||
|
conn
|
||||||
|
|> put_status(:internal_server_error)
|
||||||
|
|> json(%{error: "SHA256 for the pack doesn't match the one sent by the server"})
|
||||||
end
|
end
|
||||||
|
|
||||||
with {:ok, %{sha: sha, uri: uri} = pinfo} <- pack_info_res,
|
|
||||||
%{body: emoji_archive} <- Tesla.get!(uri),
|
|
||||||
{_, true} <- {:checksum, Base.decode16!(sha) == :crypto.hash(:sha256, emoji_archive)} do
|
|
||||||
local_name = data["as"] || name
|
|
||||||
pack_dir = Path.join(@emoji_dir_path, local_name)
|
|
||||||
File.mkdir_p!(pack_dir)
|
|
||||||
|
|
||||||
files = Enum.map(full_pack["files"], fn {_, path} -> to_charlist(path) end)
|
|
||||||
# Fallback cannot contain a pack.json file
|
|
||||||
files = if pinfo[:fallback], do: files, else: ['pack.json'] ++ files
|
|
||||||
|
|
||||||
{:ok, _} = :zip.unzip(emoji_archive, cwd: to_charlist(pack_dir), file_list: files)
|
|
||||||
|
|
||||||
# Fallback can't contain a pack.json file, since that would cause the fallback-src-sha256
|
|
||||||
# in it to depend on itself
|
|
||||||
if pinfo[:fallback] do
|
|
||||||
pack_file_path = Path.join(pack_dir, "pack.json")
|
|
||||||
|
|
||||||
File.write!(pack_file_path, Jason.encode!(full_pack, pretty: true))
|
|
||||||
end
|
|
||||||
|
|
||||||
json(conn, "ok")
|
|
||||||
else
|
else
|
||||||
{:error, e} ->
|
conn
|
||||||
conn |> put_status(:internal_server_error) |> json(%{error: e})
|
|> put_status(:internal_server_error)
|
||||||
|
|> json(%{error: "The requested instance does not support sharing emoji packs"})
|
||||||
{:checksum, _} ->
|
|
||||||
conn
|
|
||||||
|> put_status(:internal_server_error)
|
|
||||||
|> json(%{error: "SHA256 for the pack doesn't match the one sent by the server"})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ def raw_nodeinfo do
|
||||||
"mastodon_api_streaming",
|
"mastodon_api_streaming",
|
||||||
"polls",
|
"polls",
|
||||||
"pleroma_explicit_addressing",
|
"pleroma_explicit_addressing",
|
||||||
|
"shareable_emoji_packs",
|
||||||
if Config.get([:media_proxy, :enabled]) do
|
if Config.get([:media_proxy, :enabled]) do
|
||||||
"media_proxy"
|
"media_proxy"
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -54,6 +54,12 @@ test "downloading shared & unshared packs from another instance via download_fro
|
||||||
end)
|
end)
|
||||||
|
|
||||||
mock(fn
|
mock(fn
|
||||||
|
%{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
|
||||||
|
json(%{features: []})
|
||||||
|
|
||||||
|
%{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
|
||||||
|
json(%{features: ["shareable_emoji_packs"]})
|
||||||
|
|
||||||
%{
|
%{
|
||||||
method: :get,
|
method: :get,
|
||||||
url: "https://example.com/api/pleroma/emoji/packs/list"
|
url: "https://example.com/api/pleroma/emoji/packs/list"
|
||||||
|
@ -87,6 +93,22 @@ test "downloading shared & unshared packs from another instance via download_fro
|
||||||
|
|
||||||
conn = build_conn() |> assign(:user, admin)
|
conn = build_conn() |> assign(:user, admin)
|
||||||
|
|
||||||
|
assert (conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post(
|
||||||
|
emoji_api_path(
|
||||||
|
conn,
|
||||||
|
:download_from
|
||||||
|
),
|
||||||
|
%{
|
||||||
|
instance_address: "https://old-instance",
|
||||||
|
pack_name: "test_pack",
|
||||||
|
as: "test_pack2"
|
||||||
|
}
|
||||||
|
|> Jason.encode!()
|
||||||
|
)
|
||||||
|
|> json_response(500))["error"] =~ "does not support"
|
||||||
|
|
||||||
assert conn
|
assert conn
|
||||||
|> put_req_header("content-type", "application/json")
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post(
|
|> post(
|
||||||
|
|
Loading…
Reference in a new issue