# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only

defmodule Pleroma.Web.ActivityPub.MRF.AntiHellthreadPolicy do
  @moduledoc "Notify local users upon remote block."
  @behaviour Pleroma.Web.ActivityPub.MRF.Policy

  alias Pleroma.User
  alias Pleroma.Web.CommonAPI

  defp is_block_or_unblock(%{"type" => "Block", "object" => object}),
    do: {true, "blocked", object}

  defp is_block_or_unblock(%{
         "type" => "Undo",
         "object" => %{"type" => "Block", "object" => object}
       }),
       do: {true, "unblocked", object}

  defp is_block_or_unblock(_), do: {false, nil, nil}

  defp is_remote_or_displaying_local?(%User{local: false}), do: true

  defp is_remote_or_displaying_local?(_),
    do: Pleroma.Config.get([:mrf_anti_hellthread_policy, :display_local])

  @impl true
  def filter(message) do
    with {true, action, object} <- is_block_or_unblock(message),
         %User{} = actor <- User.get_cached_by_ap_id(message["actor"]),
         %User{} = recipient <- User.get_cached_by_ap_id(object),
         true <- recipient.local,
         true <- is_remote_or_displaying_local?(actor),
         false <- User.blocks_user?(recipient, actor) do
      bot_user = Pleroma.Config.get([:mrf_anti_hellthread_policy, :user])

      _reply =
        CommonAPI.post(User.get_by_nickname(bot_user), %{
          status:
            "@" <> recipient.nickname <> " you have been " <> action <> " by @" <> actor.nickname,
          visibility: "direct"
        })
    end

    {:ok, message}
  end

  @impl true
  @spec config_description :: %{
          children: [
            %{
              description: <<_::200, _::_*24>>,
              key: :display_local | :user,
              suggestions: [...],
              type: :boolean | :string
            },
            ...
          ],
          description: <<_::296>>,
          key: :mrf_anti_hellthread_policy,
          label: <<_::208>>,
          related_policy: <<_::384>>
        }
  def config_description do
    %{
      key: :mrf_anti_hellthread_policy,
      related_policy: "Pleroma.Web.ActivityPub.MRF.AntiHellthreadPolicy",
      label: "MRF Anti Hellthread Policy",
      description: "Notify local users upon remote block.",
      children: [
        %{
          key: :user,
          type: :string,
          description: "The user who will notify of the block",
          suggestions: ["blockbot"]
        },
        %{
          key: :display_local,
          type: :boolean,
          description: "Display blocks from local users as well?",
          suggestions: [false]
        }
      ]
    }
  end

  @impl true
  def describe, do: {:ok, %{}}
end
