Ensure we only apply NSFW Simple policy on parsable objects
[akkoma] / lib / pleroma / emoji / pack.ex
index 5660c4c9d8e39a20a910d7765afd62ad7cca8f28..d076ae3125c5318815dba7d59042862c9f1399e8 100644 (file)
@@ -1,6 +1,7 @@
 defmodule Pleroma.Emoji.Pack do
-  @derive {Jason.Encoder, only: [:files, :pack]}
+  @derive {Jason.Encoder, only: [:files, :pack, :files_count]}
   defstruct files: %{},
+            files_count: 0,
             pack_file: nil,
             path: nil,
             pack: %{},
@@ -8,6 +9,7 @@ defmodule Pleroma.Emoji.Pack do
 
   @type t() :: %__MODULE__{
           files: %{String.t() => Path.t()},
+          files_count: non_neg_integer(),
           pack_file: Path.t(),
           path: Path.t(),
           pack: map(),
@@ -26,10 +28,28 @@ defmodule Pleroma.Emoji.Pack do
     end
   end
 
-  @spec show(String.t()) :: {:ok, t()} | {:error, atom()}
-  def show(name) do
+  defp paginate(entities, 1, page_size), do: Enum.take(entities, page_size)
+
+  defp paginate(entities, page, page_size) do
+    entities
+    |> Enum.chunk_every(page_size)
+    |> Enum.at(page - 1)
+  end
+
+  @spec show(keyword()) :: {:ok, t()} | {:error, atom()}
+  def show(opts) do
+    name = opts[:name]
+
     with :ok <- validate_not_empty([name]),
          {:ok, pack} <- load_pack(name) do
+      shortcodes =
+        pack.files
+        |> Map.keys()
+        |> Enum.sort()
+        |> paginate(opts[:page], opts[:page_size])
+
+      pack = Map.put(pack, :files, Map.take(pack.files, shortcodes))
+
       {:ok, validate_pack(pack)}
     end
   end
@@ -120,10 +140,10 @@ defmodule Pleroma.Emoji.Pack do
     end
   end
 
-  @spec list_local(keyword()) :: {:ok, map()}
+  @spec list_local(keyword()) :: {:ok, map(), non_neg_integer()}
   def list_local(opts) do
     with {:ok, results} <- list_packs_dir() do
-      packs =
+      all_packs =
         results
         |> Enum.map(fn name ->
           case load_pack(name) do
@@ -134,18 +154,11 @@ defmodule Pleroma.Emoji.Pack do
         |> Enum.reject(&is_nil/1)
 
       packs =
-        case opts[:page] do
-          1 ->
-            Enum.take(packs, opts[:page_size])
-
-          _ ->
-            packs
-            |> Enum.take(opts[:page] * opts[:page_size])
-            |> Enum.take(-opts[:page_size])
-        end
+        all_packs
+        |> paginate(opts[:page], opts[:page_size])
         |> Map.new(fn pack -> {pack.name, validate_pack(pack)} end)
 
-      {:ok, packs}
+      {:ok, packs, length(all_packs)}
     end
   end
 
@@ -208,7 +221,12 @@ defmodule Pleroma.Emoji.Pack do
         |> Map.put(:path, Path.dirname(pack_file))
         |> Map.put(:name, name)
 
-      {:ok, pack}
+      files_count =
+        pack.files
+        |> Map.keys()
+        |> length()
+
+      {:ok, Map.put(pack, :files_count, files_count)}
     else
       {:error, :not_found}
     end
@@ -307,7 +325,9 @@ defmodule Pleroma.Emoji.Pack do
     # Otherwise, they'd have to download it from external-src
     pack.pack["share-files"] &&
       Enum.all?(pack.files, fn {_, file} ->
-        File.exists?(Path.join(pack.path, file))
+        pack.path
+        |> Path.join(file)
+        |> File.exists?()
       end)
   end
 
@@ -451,7 +471,7 @@ defmodule Pleroma.Emoji.Pack do
     # with the API so it should be sufficient
     with {:create_dir, :ok} <- {:create_dir, File.mkdir_p(emoji_path)},
          {:ls, {:ok, results}} <- {:ls, File.ls(emoji_path)} do
-      {:ok, results}
+      {:ok, Enum.sort(results)}
     else
       {:create_dir, {:error, e}} -> {:error, :create_dir, e}
       {:ls, {:error, e}} -> {:error, :ls, e}