Add emoji_url to notifications to allow rendering
[akkoma] / lib / pleroma / emoji.ex
index bafad2ae9fa915a947ed24fae8cf2f8c57e6e3a2..f4043ac80b9d317ab6c39369b5d7cc69cd74ecdf 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Emoji do
@@ -50,12 +50,24 @@ defmodule Pleroma.Emoji do
   @doc "Returns the path of the emoji `name`."
   @spec get(String.t()) :: String.t() | nil
   def get(name) do
+    name =
+      if String.starts_with?(name, ":") do
+        name
+        |> String.replace_leading(":", "")
+        |> String.replace_trailing(":", "")
+      else
+        name
+      end
+
     case :ets.lookup(@ets, name) do
       [{_, path}] -> path
       _ -> nil
     end
   end
 
+  @spec exist?(String.t()) :: boolean()
+  def exist?(name), do: not is_nil(get(name))
+
   @doc "Returns all the emojos!!"
   @spec get_all() :: list({String.t(), String.t(), String.t()})
   def get_all do
@@ -98,4 +110,76 @@ defmodule Pleroma.Emoji do
   defp update_emojis(emojis) do
     :ets.insert(@ets, emojis)
   end
+
+  @external_resource "lib/pleroma/emoji-test.txt"
+
+  regional_indicators =
+    Enum.map(127_462..127_487, fn codepoint ->
+      <<codepoint::utf8>>
+    end)
+
+  emojis =
+    @external_resource
+    |> File.read!()
+    |> String.split("\n")
+    |> Enum.filter(fn line ->
+      line != "" and not String.starts_with?(line, "#") and
+        String.contains?(line, "qualified")
+    end)
+    |> Enum.map(fn line ->
+      line
+      |> String.split(";", parts: 2)
+      |> hd()
+      |> String.trim()
+      |> String.split()
+      |> Enum.map(fn codepoint ->
+        <<String.to_integer(codepoint, 16)::utf8>>
+      end)
+      |> Enum.join()
+    end)
+    |> Enum.uniq()
+
+  emojis = emojis ++ regional_indicators
+
+  for emoji <- emojis do
+    def is_unicode_emoji?(unquote(emoji)), do: true
+  end
+
+  def is_unicode_emoji?(_), do: false
+
+  def stripped_name(name) when is_binary(name) do
+    name
+    |> String.replace_leading(":", "")
+    |> String.replace_trailing(":", "")
+  end
+
+  def stripped_name(name), do: name
+
+  def maybe_quote(name) when is_binary(name) do
+    if is_unicode_emoji?(name) do
+      name
+    else
+      ":#{name}:"
+    end
+  end
+
+  def maybe_quote(name), do: name
+
+  def emoji_url(%{"type" => "EmojiReact", "content" => emoji, "tag" => []}), do: nil
+
+  def emoji_url(%{"type" => "EmojiReact", "content" => emoji, "tag" => tags}) do
+    tag =
+      tags
+      |> Enum.find(fn tag -> tag["type"] == "Emoji" && tag["name"] == stripped_name(emoji) end)
+
+    if is_nil(tag) do
+      nil
+    else
+      tag
+      |> Map.get("icon")
+      |> Map.get("url")
+    end
+  end
+
+  def emoji_url(_), do: nil
 end