1
0

Somewhat smarter rate limiting

This commit is contained in:
Mint
2023-04-16 17:46:36 +03:00
parent 21b1d99e69
commit da1cb1d3c4
2 changed files with 42 additions and 12 deletions
+2
View File
@@ -446,6 +446,8 @@ config :pleroma, :mrf_inline_quote, prefix: "RT"
config :pleroma, :mrf_high_roller,
user: "blockbot",
timeout: 60,
global_threshold: 5,
actor_blacklist: [],
domain_greylist: [],
domain_blacklist: [],
@@ -58,9 +58,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.HighRollerPolicy do
@impl true
def filter(message) do
with {:error, _} <- Cachex.stats(:highroller), do: Cachex.start(:highroller)
{_, n} = Cachex.fetch(:highroller, message["actor"], fn(i) -> {:commit, :os.system_time(:seconds)-1} end)
t = :os.system_time(:seconds)
with {:error, _} <- Cachex.stats(:highroller), do: Cachex.start(:highroller, [ stats: true ])
systime = :os.system_time(:seconds)
with {true, action, object} <- is_block_or_unblock(message),
%User{} = actor <- User.get_cached_by_ap_id(message["actor"]),
@@ -69,6 +68,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.HighRollerPolicy do
false <- Enum.member?(Config.get([:mrf_high_roller, :domain_blacklist]), URI.parse(message["actor"]).host),
true <- recipient.local do
{_, actiontime} = Cachex.fetch(:highroller, actor.nickname<>","<>recipient.nickname<>","<>action, fn(_i) -> {:commit, :os.system_time(:seconds)-1} end)
{_, globalcount} = Cachex.fetch(:highroller, "global:"<>actor.nickname, fn(_i) -> {:commit, 0} end)
blocker = if(Config.get([:mrf_high_roller, :tag_blocking_actor]) && !Enum.member?(Config.get([:mrf_high_roller, :domain_greylist]), URI.parse(message["actor"]).host)) do
"@" <> actor.nickname
else
@@ -90,15 +92,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.HighRollerPolicy do
end
)
if t > n do
Cachex.put(:highroller, message["actor"], t+15)
if (systime > actiontime && globalcount < Config.get([:mrf_high_roller, :global_threshold])) do
Cachex.incr(:highroller, "global:"<>actor.nickname, globalcount+1)
Cachex.put(:highroller, actor.nickname<>","<>recipient.nickname<>","<>action, systime+Config.get([:mrf_high_roller, :timeout]))
CommonAPI.post(User.get_by_nickname(Config.get([:mrf_high_roller, :user])), %{
status: msg,
visibility: Config.get([:mrf_high_roller, :block_visibility])
})
else
Logger.warn("Rate-limited incoming block notif! #{inspect(message)}")
Cachex.incr(:highroller, message["actor"], 30*(1+(n-t)))
Cachex.incr(:highroller, "global:"<>actor.nickname, globalcount+1)
Cachex.incr(:highroller, actor.nickname<>","<>recipient.nickname<>","<>action, 30*(1+(systime-actiontime)))
end
end
@@ -109,6 +113,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.HighRollerPolicy do
false <- Enum.member?(Config.get([:mrf_high_roller, :domain_blacklist]), URI.parse(message["actor"]).host),
true <- recipient.local do
{_, actiontime} = Cachex.fetch(:highroller, actor.nickname<>","<>recipient.nickname<>",report", fn(_i) -> {:commit, :os.system_time(:seconds)-1} end)
{_, globalcount} = Cachex.fetch(:highroller, "global:"<>actor.nickname, fn(_i) -> {:commit, 0} end)
reporter = if(Config.get([:mrf_high_roller, :tag_reporting_actor]) && !Enum.member?(Config.get([:mrf_high_roller, :domain_greylist]), URI.parse(message["actor"]).host)) do
"@" <> actor.nickname
else
@@ -149,15 +156,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.HighRollerPolicy do
_ -> ""
end
if t > n do
Cachex.put(:highroller, message["actor"], t+15)
if (systime > actiontime && globalcount < Config.get([:mrf_high_roller, :global_threshold])) do
Cachex.incr(:highroller, "global:"<>actor.nickname, globalcount+1)
Cachex.put(:highroller, actor.nickname<>","<>recipient.nickname<>",report", systime+Config.get([:mrf_high_roller, :timeout]))
CommonAPI.post(User.get_by_nickname(Config.get([:mrf_high_roller, :user])), %{
status: msg <> comment <> posts,
visibility: Config.get([:mrf_high_roller, :report_visibility])
})
else
Logger.warn("Rate-limited incoming report notif! #{inspect(message)}")
Cachex.incr(:highroller, message["actor"], 30*(1+(n-t)))
Cachex.incr(:highroller, "global:"<>actor.nickname, globalcount+1)
Cachex.incr(:highroller, actor.nickname<>","<>recipient.nickname<>",report", 30*(1+(systime-actiontime)))
end
end
@@ -168,6 +177,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.HighRollerPolicy do
false <- Enum.member?(Config.get([:mrf_high_roller, :domain_blacklist]), URI.parse(message["actor"]).host),
true <- recipient.local do
{_, actiontime} = Cachex.fetch(:highroller, actor.nickname<>","<>recipient.nickname<>",unfollow", fn(_i) -> {:commit, :os.system_time(:seconds)-1} end)
{_, globalcount} = Cachex.fetch(:highroller, "global:"<>actor.nickname, fn(_i) -> {:commit, 0} end)
unfollower = if(Config.get([:mrf_high_roller, :tag_unfollowing_actor]) && !Enum.member?(Config.get([:mrf_high_roller, :domain_greylist]), URI.parse(message["actor"]).host)) do
"@" <> actor.nickname
else
@@ -188,15 +200,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.HighRollerPolicy do
end
)
if t > n do
Cachex.put(:highroller, message["actor"], t+15)
if (systime > actiontime && globalcount < Config.get([:mrf_high_roller, :global_threshold])) do
Cachex.incr(:highroller, "global:"<>actor.nickname, globalcount+1)
Cachex.put(:highroller, actor.nickname<>","<>recipient.nickname<>",unfollow", systime+Config.get([:mrf_high_roller, :timeout]))
CommonAPI.post(User.get_by_nickname(Config.get([:mrf_high_roller, :user])), %{
status: msg,
visibility: Config.get([:mrf_high_roller, :unfollow_visibility])
})
else
Logger.warn("Rate-limited incoming unfollow notif! #{inspect(message)}")
Cachex.incr(:highroller, message["actor"], 30*(1+(n-t)))
Cachex.incr(:highroller, "global:"<>actor.nickname, globalcount+1)
Cachex.incr(:highroller, actor.nickname<>","<>recipient.nickname<>",unfollow", 30*(1+(systime-actiontime)))
end
end
@@ -218,6 +232,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.HighRollerPolicy do
description: "Account from which notifications would be sent",
suggestions: ["blockbot"]
},
%{
key: :timeout,
type: :integer,
label: "Timeout",
description: "Timeout (in seconds) between which no new notifications of the same type can be sent",
suggestions: [60]
},
%{
key: :global_threshold,
type: :integer,
label: "Global threshold",
description: "Global threshold of the actions for the actor",
suggestions: [5]
},
%{
key: :actor_blacklist,
type: {:list, :string},