# SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do require Logger @moduledoc "Detect new emoji and steal them" @behaviour Pleroma.Web.ActivityPub.MRF defp has_emojo(installed_emoji, str) do result = for emojo <- installed_emoji, elem(emojo, 0) == str, do: true length(result) == 1 end defp is_remote(host) do my_host = Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host]) my_host != host end # if whitelist is not defined, everything is "whitelisted" defp is_whitelisted(domain) do whitelist = Pleroma.Config.get([:emoji_stealer, :whitelist]) whitelist == nil || Enum.member?(whitelist, domain) end @impl true def filter(%{"object" => %{"emoji" => foreign_emoji, "actor" => actor}} = object) do host = URI.parse(actor).host if is_remote(host) && is_whitelisted(host) do num_foreign_emoji = Kernel.map_size(foreign_emoji) if num_foreign_emoji > 0 do Logger.debug("#{num_foreign_emoji} EMOJI TO PROCESS") installed_emoji = Pleroma.Emoji.get_all() new_files = for {emojo_shortcode, emojo_url} <- foreign_emoji, !has_emojo(installed_emoji, emojo_shortcode) do Logger.debug("HANDLING EMOJO") cond do String.contains?(emojo_shortcode, "/") -> Logger.error("BAD EMOJO SHORTCODE: #{emojo_shortcode}") String.starts_with?(emojo_url, "https://") -> try do remote_emojo = HTTPoison.get!(emojo_url) if remote_emojo.status_code == 200 do with {:ok, current_dir} <- File.cwd() do new_file = current_dir <> "/priv/static/emoji/stolen/" <> emojo_shortcode <> Path.extname(emojo_url) {:ok, file} = File.open(new_file, [:write]) IO.binwrite(file, remote_emojo.body) File.close(file) Logger.debug("SAVED EMOJO") new_file end end rescue e in RuntimeError -> Logger.error("FAILED TO QUERY REMOTE EMOJO #{emojo_url} #{e}") end true -> Logger.error("EMOJO COND FAIL #{emojo_shortcode} #{emojo_url}") end end Logger.debug("EMOJI FILES: #{inspect(new_files)}") if length(new_files) > 0 do Logger.debug("RELOADING EMOJI") Pleroma.Emoji.reload() else Logger.debug("NO EMOJI TO LOAD") end end end {:ok, object} end @impl true def filter(object) do {:ok, object} end @impl true def describe, do: {:ok, %{}} end