|
|
@@ -13,8 +13,14 @@ defmodule Pleroma.Emoji do |
|
|
|
This GenServer stores in an ETS table the list of the loaded emojis, and also allows to reload the list at runtime. |
|
|
|
""" |
|
|
|
use GenServer |
|
|
|
|
|
|
|
@type pattern :: Regex.t() | module() | String.t() |
|
|
|
@type patterns :: pattern | [pattern] |
|
|
|
@type group_patterns :: keyword(patterns) |
|
|
|
|
|
|
|
@ets __MODULE__.Ets |
|
|
|
@ets_options [:ordered_set, :protected, :named_table, {:read_concurrency, true}] |
|
|
|
@groups Application.get_env(:pleroma, :emoji)[:groups] |
|
|
|
|
|
|
|
@doc false |
|
|
|
def start_link do |
|
|
@@ -73,13 +79,14 @@ defmodule Pleroma.Emoji do |
|
|
|
end |
|
|
|
|
|
|
|
defp load do |
|
|
|
finmoji_enabled = Keyword.get(Application.get_env(:pleroma, :instance), :finmoji_enabled) |
|
|
|
shortcode_globs = Keyword.get(Application.get_env(:pleroma, :emoji, []), :shortcode_globs, []) |
|
|
|
|
|
|
|
emojis = |
|
|
|
(load_finmoji(Keyword.get(Application.get_env(:pleroma, :instance), :finmoji_enabled)) ++ |
|
|
|
(load_finmoji(finmoji_enabled) ++ |
|
|
|
load_from_file("config/emoji.txt") ++ |
|
|
|
load_from_file("config/custom_emoji.txt") ++ |
|
|
|
load_from_globs( |
|
|
|
Keyword.get(Application.get_env(:pleroma, :emoji, []), :shortcode_globs, []) |
|
|
|
)) |
|
|
|
load_from_globs(shortcode_globs)) |
|
|
|
|> Enum.reject(fn value -> value == nil end) |
|
|
|
|
|
|
|
true = :ets.insert(@ets, emojis) |
|
|
@@ -151,11 +158,12 @@ defmodule Pleroma.Emoji do |
|
|
|
"white_nights", |
|
|
|
"woollysocks" |
|
|
|
] |
|
|
|
defp load_finmoji(true) do |
|
|
|
tag = Application.get_env(:pleroma, :emoji)[:finmoji_tag] |
|
|
|
|
|
|
|
defp load_finmoji(true) do |
|
|
|
Enum.map(@finmoji, fn finmoji -> |
|
|
|
{finmoji, "/finmoji/128px/#{finmoji}-128.png", tag} |
|
|
|
file_name = "/finmoji/128px/#{finmoji}-128.png" |
|
|
|
group = match_extra(@groups, file_name) |
|
|
|
{finmoji, file_name, to_string(group)} |
|
|
|
end) |
|
|
|
end |
|
|
|
|
|
|
@@ -170,11 +178,6 @@ defmodule Pleroma.Emoji do |
|
|
|
end |
|
|
|
|
|
|
|
defp load_from_file_stream(stream) do |
|
|
|
default_tag = |
|
|
|
stream.path |
|
|
|
|> Path.basename(".txt") |
|
|
|
|> get_default_tag() |
|
|
|
|
|
|
|
stream |
|
|
|
|> Stream.map(&String.trim/1) |
|
|
|
|> Stream.map(fn line -> |
|
|
@@ -183,7 +186,7 @@ defmodule Pleroma.Emoji do |
|
|
|
{name, file, tags} |
|
|
|
|
|
|
|
[name, file] -> |
|
|
|
{name, file, default_tag} |
|
|
|
{name, file, to_string(match_extra(@groups, file))} |
|
|
|
|
|
|
|
_ -> |
|
|
|
nil |
|
|
@@ -192,48 +195,51 @@ defmodule Pleroma.Emoji do |
|
|
|
|> Enum.to_list() |
|
|
|
end |
|
|
|
|
|
|
|
@spec get_default_tag(String.t()) :: String.t() |
|
|
|
defp get_default_tag(file_name) when file_name in ["emoji", "custom_emoji"] do |
|
|
|
Keyword.get( |
|
|
|
Application.get_env(:pleroma, :emoji), |
|
|
|
String.to_existing_atom(file_name <> "_tag") |
|
|
|
) |
|
|
|
end |
|
|
|
|
|
|
|
defp get_default_tag(_), do: Application.get_env(:pleroma, :emoji)[:custom_tag] |
|
|
|
|
|
|
|
defp load_from_globs(globs) do |
|
|
|
static_path = Path.join(:code.priv_dir(:pleroma), "static") |
|
|
|
|
|
|
|
paths = |
|
|
|
Enum.map(globs, fn glob -> |
|
|
|
static_part = |
|
|
|
Path.dirname(glob) |
|
|
|
|> String.replace_trailing("**", "") |
|
|
|
|
|
|
|
Path.join(static_path, glob) |
|
|
|
|> Path.wildcard() |
|
|
|
|> Enum.map(fn path -> |
|
|
|
custom_folder = |
|
|
|
path |
|
|
|
|> Path.relative_to(Path.join(static_path, static_part)) |
|
|
|
|> Path.dirname() |
|
|
|
|
|
|
|
[path, custom_folder] |
|
|
|
end) |
|
|
|
end) |
|
|
|
|> Enum.concat() |
|
|
|
|
|
|
|
Enum.map(paths, fn [path, custom_folder] -> |
|
|
|
tag = |
|
|
|
case custom_folder do |
|
|
|
"." -> Keyword.get(Application.get_env(:pleroma, :emoji), :custom_tag) |
|
|
|
tag -> tag |
|
|
|
end |
|
|
|
|
|
|
|
Enum.map(paths, fn path -> |
|
|
|
tag = match_extra(@groups, Path.join("/", Path.relative_to(path, static_path))) |
|
|
|
shortcode = Path.basename(path, Path.extname(path)) |
|
|
|
external_path = Path.join("/", Path.relative_to(path, static_path)) |
|
|
|
{shortcode, external_path, tag} |
|
|
|
{shortcode, external_path, to_string(tag)} |
|
|
|
end) |
|
|
|
end |
|
|
|
|
|
|
|
@doc """ |
|
|
|
Finds a matching group for the given extra filename |
|
|
|
""" |
|
|
|
@spec match_extra(group_patterns(), String.t()) :: atom() | nil |
|
|
|
def match_extra(group_patterns, filename) do |
|
|
|
match_group_patterns(group_patterns, fn pattern -> |
|
|
|
case pattern do |
|
|
|
%Regex{} = regex -> Regex.match?(regex, filename) |
|
|
|
string when is_binary(string) -> filename == string |
|
|
|
end |
|
|
|
end) |
|
|
|
end |
|
|
|
|
|
|
|
defp match_group_patterns(group_patterns, matcher) do |
|
|
|
Enum.find_value(group_patterns, fn {group, patterns} -> |
|
|
|
patterns = |
|
|
|
patterns |
|
|
|
|> List.wrap() |
|
|
|
|> Enum.map(fn pattern -> |
|
|
|
if String.contains?(pattern, "*") do |
|
|
|
~r(#{String.replace(pattern, "*", ".*")}) |
|
|
|
else |
|
|
|
pattern |
|
|
|
end |
|
|
|
end) |
|
|
|
|
|
|
|
Enum.any?(patterns, matcher) && group |
|
|
|
end) |
|
|
|
end |
|
|
|
end |