forked from AkkomaGang/akkoma
Also use actor_type to determine if an account is a bot in antiFollowbotPolicy
This commit is contained in:
parent
3fd87b6a75
commit
661d0ba481
4 changed files with 66 additions and 15 deletions
|
@ -117,6 +117,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Improved Twittercard and OpenGraph meta tag generation including thumbnails and image dimension metadata when available.
|
- Improved Twittercard and OpenGraph meta tag generation including thumbnails and image dimension metadata when available.
|
||||||
- AdminAPI: sort users so the newest are at the top.
|
- AdminAPI: sort users so the newest are at the top.
|
||||||
- ActivityPub Client-to-Server(C2S): Limitation on the type of Activity/Object are lifted as they are now passed through ObjectValidators
|
- ActivityPub Client-to-Server(C2S): Limitation on the type of Activity/Object are lifted as they are now passed through ObjectValidators
|
||||||
|
- MRF (`AntiFollowbotPolicy`): Bot accounts are now also considered followbots. Users can still allow bots to follow them by first following the bot.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,8 @@ To add configuration to your config file, you can copy it from the base config.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.Workers.PurgeExpiredActivity` to be enabled for processing the scheduled delections.
|
* `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.Workers.PurgeExpiredActivity` to be enabled for processing the scheduled delections.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy`: Makes all bot posts to disappear from public timelines.
|
* `Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy`: Makes all bot posts to disappear from public timelines.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.FollowBotPolicy`: Automatically follows newly discovered users from the specified bot account. Local accounts, locked accounts, and users with "#nobot" in their bio are respected and excluded from being followed.
|
* `Pleroma.Web.ActivityPub.MRF.FollowBotPolicy`: Automatically follows newly discovered users from the specified bot account. Local accounts, locked accounts, and users with "#nobot" in their bio are respected and excluded from being followed.
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy`: Drops follow requests from followbots. Users can still allow bots to follow them by first following the bot.
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.KeywordPolicy`: Rejects or removes from the federated timeline or replaces keywords. (See [`:mrf_keyword`](#mrf_keyword)).
|
||||||
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
|
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
|
||||||
* `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
|
* `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ defp score_displayname("federationbot"), do: 1.0
|
||||||
defp score_displayname("fedibot"), do: 1.0
|
defp score_displayname("fedibot"), do: 1.0
|
||||||
defp score_displayname(_), do: 0.0
|
defp score_displayname(_), do: 0.0
|
||||||
|
|
||||||
defp determine_if_followbot(%User{nickname: nickname, name: displayname}) do
|
defp determine_if_followbot(%User{nickname: nickname, name: displayname, actor_type: actor_type}) do
|
||||||
# nickname will be a binary string except when following a relay
|
# nickname will be a binary string except when following a relay
|
||||||
nick_score =
|
nick_score =
|
||||||
if is_binary(nickname) do
|
if is_binary(nickname) do
|
||||||
|
@ -45,19 +45,32 @@ defp determine_if_followbot(%User{nickname: nickname, name: displayname}) do
|
||||||
0.0
|
0.0
|
||||||
end
|
end
|
||||||
|
|
||||||
nick_score + name_score
|
# actor_type "Service" is a Bot account
|
||||||
|
actor_type_score =
|
||||||
|
if actor_type == "Service" do
|
||||||
|
1.0
|
||||||
|
else
|
||||||
|
0.0
|
||||||
|
end
|
||||||
|
|
||||||
|
nick_score + name_score + actor_type_score
|
||||||
end
|
end
|
||||||
|
|
||||||
defp determine_if_followbot(_), do: 0.0
|
defp determine_if_followbot(_), do: 0.0
|
||||||
|
|
||||||
|
defp bot_allowed?(%{"object" => target}, bot_actor) do
|
||||||
|
%User{} = user = normalize_by_ap_id(target)
|
||||||
|
|
||||||
|
User.following?(user, bot_actor)
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def filter(%{"type" => "Follow", "actor" => actor_id} = message) do
|
def filter(%{"type" => "Follow", "actor" => actor_id} = message) do
|
||||||
%User{} = actor = normalize_by_ap_id(actor_id)
|
%User{} = actor = normalize_by_ap_id(actor_id)
|
||||||
|
|
||||||
score = determine_if_followbot(actor)
|
score = determine_if_followbot(actor)
|
||||||
|
|
||||||
# TODO: scan biography data for keywords and score it somehow.
|
if score < 0.8 || bot_allowed?(message, actor) do
|
||||||
if score < 0.8 do
|
|
||||||
{:ok, message}
|
{:ok, message}
|
||||||
else
|
else
|
||||||
{:reject, "[AntiFollowbotPolicy] Scored #{actor_id} as #{score}"}
|
{:reject, "[AntiFollowbotPolicy] Scored #{actor_id} as #{score}"}
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
|
||||||
use Pleroma.DataCase, async: true
|
use Pleroma.DataCase, async: true
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy
|
alias Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy
|
||||||
|
|
||||||
describe "blocking based on attributes" do
|
describe "blocking based on attributes" do
|
||||||
|
@ -38,21 +39,55 @@ test "matches followbots by display name" do
|
||||||
|
|
||||||
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
|
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "matches followbots by actor_type" do
|
||||||
|
actor = insert(:user, %{actor_type: "Service"})
|
||||||
|
target = insert(:user)
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
|
"type" => "Follow",
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"object" => target.ap_id,
|
||||||
|
"id" => "https://example.com/activities/1234"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it allows non-followbots" do
|
describe "it allows" do
|
||||||
actor = insert(:user)
|
test "non-followbots" do
|
||||||
target = insert(:user)
|
actor = insert(:user)
|
||||||
|
target = insert(:user)
|
||||||
|
|
||||||
message = %{
|
message = %{
|
||||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
"type" => "Follow",
|
"type" => "Follow",
|
||||||
"actor" => actor.ap_id,
|
"actor" => actor.ap_id,
|
||||||
"object" => target.ap_id,
|
"object" => target.ap_id,
|
||||||
"id" => "https://example.com/activities/1234"
|
"id" => "https://example.com/activities/1234"
|
||||||
}
|
}
|
||||||
|
|
||||||
{:ok, _} = AntiFollowbotPolicy.filter(message)
|
{:ok, _} = AntiFollowbotPolicy.filter(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "bots if the target follows the bots" do
|
||||||
|
actor = insert(:user, %{actor_type: "Service"})
|
||||||
|
target = insert(:user)
|
||||||
|
|
||||||
|
User.follow(target, actor)
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
|
"type" => "Follow",
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"object" => target.ap_id,
|
||||||
|
"id" => "https://example.com/activities/1234"
|
||||||
|
}
|
||||||
|
|
||||||
|
{:ok, _} = AntiFollowbotPolicy.filter(message)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it gracefully handles nil display names" do
|
test "it gracefully handles nil display names" do
|
||||||
|
|
Loading…
Reference in a new issue