Allow importing old (emoji.txt / plain) packs from the filesystem
authorEkaterina Vaartis <vaartis@cock.li>
Tue, 10 Sep 2019 18:16:30 +0000 (21:16 +0300)
committerEkaterina Vaartis <vaartis@cock.li>
Wed, 18 Sep 2019 21:16:33 +0000 (00:16 +0300)
lib/pleroma/web/emoji_api/emoji_api_controller.ex
lib/pleroma/web/router.ex
test/instance_static/emoji/test_pack_for_import/blank.png [new file with mode: 0644]
test/web/emoji_api_controller_test.exs

index f34a4e08cab291b6e1a61a1ee7fe14c215c6da92..dffb91b0f9a9faf042b800b56b7a8a4acde5fa61 100644 (file)
@@ -446,4 +446,70 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
         e
     end
   end
+
+  def import_from_fs(conn, _params) do
+    case File.ls(@emoji_dir_path) do
+      {:error, _} ->
+        conn
+        |> put_status(:internal_server_error)
+        |> text("Error accessing emoji pack directory")
+
+      {:ok, results} ->
+        imported_pack_names =
+          results
+          |> Enum.filter(fn file ->
+            dir_path = Path.join(@emoji_dir_path, file)
+            # Find the directories that do NOT have pack.json
+            File.dir?(dir_path) and not File.exists?(Path.join(dir_path, "pack.json"))
+          end)
+          |> Enum.map(fn dir ->
+            dir_path = Path.join(@emoji_dir_path, dir)
+            emoji_txt_path = Path.join(dir_path, "emoji.txt")
+
+            files_for_pack =
+              if File.exists?(emoji_txt_path) do
+                # There's an emoji.txt file, it's likely from a pack installed by the pack manager.
+                # Make a pack.json file from the contents of that emoji.txt fileh
+
+                # FIXME: Copy-pasted from Pleroma.Emoji/load_from_file_stream/2
+
+                # Create a map of shortcodes to filenames from emoji.txt
+
+                File.read!(emoji_txt_path)
+                |> String.split("\n")
+                |> Enum.map(&String.trim/1)
+                |> Enum.map(fn line ->
+                  case String.split(line, ~r/,\s*/) do
+                    # This matches both strings with and without tags and we don't care about tags here
+                    [name, file | _] ->
+                      {name, file}
+
+                    _ ->
+                      nil
+                  end
+                end)
+                |> Enum.filter(fn x -> not is_nil(x) end)
+                |> Enum.into(%{})
+              else
+                # If there's no emoji.txt, assume all files that are of certain extensions from the config
+                # are emojis and import them all
+                Pleroma.Emoji.make_shortcode_to_file_map(
+                  dir_path,
+                  Pleroma.Config.get!([:emoji, :pack_extensions])
+                )
+              end
+
+            pack_json_contents = Jason.encode!(%{pack: %{}, files: files_for_pack})
+
+            File.write!(
+              Path.join(dir_path, "pack.json"),
+              pack_json_contents
+            )
+
+            dir
+          end)
+
+        conn |> json(imported_pack_names)
+    end
+  end
 end
index a21fefc70f45af73bbb494c75af736382d34b887..1252048f0f2398bef847c01e6e0e765d8f199cd8 100644 (file)
@@ -218,6 +218,8 @@ defmodule Pleroma.Web.Router do
       # Modifying packs
       pipe_through([:admin_api, :oauth_write])
 
+      post("/import_from_fs", EmojiAPIController, :import_from_fs)
+
       post("/update_file/:pack_name", EmojiAPIController, :update_file)
       post("/update_metadata/:pack_name", EmojiAPIController, :update_metadata)
       post("/create/:name", EmojiAPIController, :create)
diff --git a/test/instance_static/emoji/test_pack_for_import/blank.png b/test/instance_static/emoji/test_pack_for_import/blank.png
new file mode 100644 (file)
index 0000000..8f50fa0
Binary files /dev/null and b/test/instance_static/emoji/test_pack_for_import/blank.png differ
index fa194a26c3c9d258b89f09dd746480a412bdf37b..8b2a942ceaa2d4359210fbc476c572ac65e9c9eb 100644 (file)
@@ -365,4 +365,45 @@ defmodule Pleroma.Web.EmojiAPI.EmojiAPIControllerTest do
 
     refute File.exists?("#{@emoji_dir_path}/test_created/pack.json")
   end
+
+  test "filesystem import" do
+    on_exit(fn ->
+      File.rm!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt")
+      File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
+    end)
+
+    conn = build_conn()
+    resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+
+    refute Map.has_key?(resp, "test_pack_for_import")
+
+    admin = insert(:user, info: %{is_admin: true})
+
+    assert conn
+           |> assign(:user, admin)
+           |> post(emoji_api_path(conn, :import_from_fs))
+           |> json_response(200) == ["test_pack_for_import"]
+
+    resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+    assert resp["test_pack_for_import"]["files"] == %{"blank" => "blank.png"}
+
+    File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
+    refute File.exists?("#{@emoji_dir_path}/test_pack_for_import/pack.json")
+
+    emoji_txt_content = "blank, blank.png, Fun\n\nblank2, blank.png"
+
+    File.write!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
+
+    assert conn
+           |> assign(:user, admin)
+           |> post(emoji_api_path(conn, :import_from_fs))
+           |> json_response(200) == ["test_pack_for_import"]
+
+    resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+
+    assert resp["test_pack_for_import"]["files"] == %{
+             "blank" => "blank.png",
+             "blank2" => "blank.png"
+           }
+  end
 end