logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

hellthread_policy.ex (3780B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
  5. alias Pleroma.User
  6. require Pleroma.Constants
  7. @moduledoc "Block messages with too much mentions (configurable)"
  8. @behaviour Pleroma.Web.ActivityPub.MRF.Policy
  9. defp delist_message(message, threshold) when threshold > 0 do
  10. follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
  11. to = message["to"] || []
  12. cc = message["cc"] || []
  13. follower_collection? = Enum.member?(to ++ cc, follower_collection)
  14. message =
  15. case get_recipient_count(message) do
  16. {:public, recipients}
  17. when follower_collection? and recipients > threshold ->
  18. message
  19. |> Map.put("to", [follower_collection])
  20. |> Map.put("cc", [Pleroma.Constants.as_public()])
  21. {:public, recipients} when recipients > threshold ->
  22. message
  23. |> Map.put("to", [])
  24. |> Map.put("cc", [Pleroma.Constants.as_public()])
  25. _ ->
  26. message
  27. end
  28. {:ok, message}
  29. end
  30. defp delist_message(message, _threshold), do: {:ok, message}
  31. defp reject_message(message, threshold) when threshold > 0 do
  32. with {_, recipients} <- get_recipient_count(message) do
  33. if recipients > threshold do
  34. {:reject, "[HellthreadPolicy] #{recipients} recipients is over the limit of #{threshold}"}
  35. else
  36. {:ok, message}
  37. end
  38. end
  39. end
  40. defp reject_message(message, _threshold), do: {:ok, message}
  41. defp get_recipient_count(message) do
  42. recipients = (message["to"] || []) ++ (message["cc"] || [])
  43. follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
  44. if Enum.member?(recipients, Pleroma.Constants.as_public()) do
  45. recipients =
  46. recipients
  47. |> List.delete(Pleroma.Constants.as_public())
  48. |> List.delete(follower_collection)
  49. {:public, length(recipients)}
  50. else
  51. recipients =
  52. recipients
  53. |> List.delete(follower_collection)
  54. {:not_public, length(recipients)}
  55. end
  56. end
  57. @impl true
  58. def filter(%{"type" => "Create", "object" => %{"type" => object_type}} = message)
  59. when object_type in ~w{Note Article} do
  60. reject_threshold =
  61. Pleroma.Config.get(
  62. [:mrf_hellthread, :reject_threshold],
  63. Pleroma.Config.get([:mrf_hellthread, :threshold])
  64. )
  65. delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
  66. with {:ok, message} <- reject_message(message, reject_threshold),
  67. {:ok, message} <- delist_message(message, delist_threshold) do
  68. {:ok, message}
  69. else
  70. e -> e
  71. end
  72. end
  73. @impl true
  74. def filter(message), do: {:ok, message}
  75. @impl true
  76. def describe,
  77. do: {:ok, %{mrf_hellthread: Pleroma.Config.get(:mrf_hellthread) |> Enum.into(%{})}}
  78. @impl true
  79. def config_description do
  80. %{
  81. key: :mrf_hellthread,
  82. related_policy: "Pleroma.Web.ActivityPub.MRF.HellthreadPolicy",
  83. label: "MRF Hellthread",
  84. description: "Block messages with excessive user mentions",
  85. children: [
  86. %{
  87. key: :delist_threshold,
  88. type: :integer,
  89. description:
  90. "Number of mentioned users after which the message gets removed from timelines and" <>
  91. "disables notifications. Set to 0 to disable.",
  92. suggestions: [10]
  93. },
  94. %{
  95. key: :reject_threshold,
  96. type: :integer,
  97. description:
  98. "Number of mentioned users after which the messaged gets rejected. Set to 0 to disable.",
  99. suggestions: [20]
  100. }
  101. ]
  102. }
  103. end
  104. end