1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
8 require Pleroma.Constants
10 @moduledoc "Block messages with too much mentions (configurable)"
12 @behaviour Pleroma.Web.ActivityPub.MRF.Policy
14 defp delist_message(message, threshold) when threshold > 0 do
15 follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
16 to = message["to"] || []
17 cc = message["cc"] || []
19 follower_collection? = Enum.member?(to ++ cc, follower_collection)
22 case get_recipient_count(message) do
24 when follower_collection? and recipients > threshold ->
26 |> Map.put("to", [follower_collection])
27 |> Map.put("cc", [Pleroma.Constants.as_public()])
29 {:public, recipients} when recipients > threshold ->
32 |> Map.put("cc", [Pleroma.Constants.as_public()])
41 defp delist_message(message, _threshold), do: {:ok, message}
43 defp reject_message(message, threshold) when threshold > 0 do
44 with {_, recipients} <- get_recipient_count(message) do
45 if recipients > threshold do
46 {:reject, "[HellthreadPolicy] #{recipients} recipients is over the limit of #{threshold}"}
53 defp reject_message(message, _threshold), do: {:ok, message}
55 defp get_recipient_count(message) do
56 recipients = (message["to"] || []) ++ (message["cc"] || [])
57 follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
59 if Enum.member?(recipients, Pleroma.Constants.as_public()) do
62 |> List.delete(Pleroma.Constants.as_public())
63 |> List.delete(follower_collection)
65 {:public, length(recipients)}
69 |> List.delete(follower_collection)
71 {:not_public, length(recipients)}
76 def filter(%{"type" => "Create", "object" => %{"type" => object_type}} = message)
77 when object_type in ~w{Note Article} do
80 [:mrf_hellthread, :reject_threshold],
81 Pleroma.Config.get([:mrf_hellthread, :threshold])
84 delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
86 with {:ok, message} <- reject_message(message, reject_threshold),
87 {:ok, message} <- delist_message(message, delist_threshold) do
95 def filter(message), do: {:ok, message}
99 do: {:ok, %{mrf_hellthread: Pleroma.Config.get(:mrf_hellthread) |> Enum.into(%{})}}
102 def config_description do
104 key: :mrf_hellthread,
105 related_policy: "Pleroma.Web.ActivityPub.MRF.HellthreadPolicy",
106 label: "MRF Hellthread",
107 description: "Block messages with excessive user mentions",
110 key: :delist_threshold,
113 "Number of mentioned users after which the message gets removed from timelines and" <>
114 "disables notifications. Set to 0 to disable.",
118 key: :reject_threshold,
121 "Number of mentioned users after which the messaged gets rejected. Set to 0 to disable.",