From 03f38ac4ebd97e792b0ff2a6ac804adefed85a41 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 24 Feb 2021 11:59:11 -0600 Subject: Prefer FollowBot naming convention vs Followbot --- .../web/activity_pub/mrf/follow_bot_policy.ex | 59 ++++++++++ .../web/activity_pub/mrf/followbot_policy.ex | 59 ---------- .../activity_pub/mrf/follow_bot_policy_test.exs | 126 +++++++++++++++++++++ .../activity_pub/mrf/follow_bot_policy_test.exs~ | 126 +++++++++++++++++++++ .../web/activity_pub/mrf/followbot_policy_test.exs | 126 --------------------- 5 files changed, 311 insertions(+), 185 deletions(-) create mode 100644 lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex delete mode 100644 lib/pleroma/web/activity_pub/mrf/followbot_policy.ex create mode 100644 test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs create mode 100644 test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs~ delete mode 100644 test/pleroma/web/activity_pub/mrf/followbot_policy_test.exs diff --git a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex new file mode 100644 index 000000000..7307c9c14 --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex @@ -0,0 +1,59 @@ +defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do + @behaviour Pleroma.Web.ActivityPub.MRF + alias Pleroma.Config + alias Pleroma.User + alias Pleroma.Web.CommonAPI + + require Logger + + @impl true + def filter(message) do + with follower_nickname <- Config.get([:mrf_follow_bot, :follower_nickname]), + %User{actor_type: "Service"} = follower <- + User.get_cached_by_nickname(follower_nickname), + %{"type" => "Create", "object" => %{"type" => "Note"}} <- message do + try_follow(follower, message) + else + nil -> + Logger.warn( + "#{__MODULE__} skipped because of missing `:mrf_follow_bot, :follower_nickname` configuration, the :follower_nickname + account does not exist, or the account is not correctly configured as a bot." + ) + + {:ok, message} + + _ -> + {:ok, message} + end + end + + defp try_follow(follower, message) do + to = Map.get(message, "to", []) + cc = Map.get(message, "cc", []) + actor = [message["actor"]] + + Enum.concat([to, cc, actor]) + |> List.flatten() + |> Enum.uniq() + |> User.get_all_by_ap_id() + |> Enum.each(fn user -> + with false <- user.local, + false <- User.following?(follower, user), + false <- User.locked?(user), + false <- (user.bio || "") |> String.downcase() |> String.contains?("nobot") do + Logger.debug( + "#{__MODULE__}: Follow request from #{follower.nickname} to #{user.nickname}" + ) + + CommonAPI.follow(follower, user) + end + end) + + {:ok, message} + end + + @impl true + def describe do + {:ok, %{}} + end +end diff --git a/lib/pleroma/web/activity_pub/mrf/followbot_policy.ex b/lib/pleroma/web/activity_pub/mrf/followbot_policy.ex deleted file mode 100644 index ca99e429c..000000000 --- a/lib/pleroma/web/activity_pub/mrf/followbot_policy.ex +++ /dev/null @@ -1,59 +0,0 @@ -defmodule Pleroma.Web.ActivityPub.MRF.FollowbotPolicy do - @behaviour Pleroma.Web.ActivityPub.MRF - alias Pleroma.Config - alias Pleroma.User - alias Pleroma.Web.CommonAPI - - require Logger - - @impl true - def filter(message) do - with follower_nickname <- Config.get([:mrf_follow_bot, :follower_nickname]), - %User{actor_type: "Service"} = follower <- - User.get_cached_by_nickname(follower_nickname), - %{"type" => "Create", "object" => %{"type" => "Note"}} <- message do - try_follow(follower, message) - else - nil -> - Logger.warn( - "#{__MODULE__} skipped because of missing `:mrf_follow_bot, :follower_nickname` configuration, the :follower_nickname - account does not exist, or the account is not correctly configured as a bot." - ) - - {:ok, message} - - _ -> - {:ok, message} - end - end - - defp try_follow(follower, message) do - to = Map.get(message, "to", []) - cc = Map.get(message, "cc", []) - actor = [message["actor"]] - - Enum.concat([to, cc, actor]) - |> List.flatten() - |> Enum.uniq() - |> User.get_all_by_ap_id() - |> Enum.each(fn user -> - with false <- user.local, - false <- User.following?(follower, user), - false <- User.locked?(user), - false <- (user.bio || "") |> String.downcase() |> String.contains?("nobot") do - Logger.debug( - "#{__MODULE__}: Follow request from #{follower.nickname} to #{user.nickname}" - ) - - CommonAPI.follow(follower, user) - end - end) - - {:ok, message} - end - - @impl true - def describe do - {:ok, %{}} - end -end diff --git a/test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs b/test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs new file mode 100644 index 000000000..3f63f11ef --- /dev/null +++ b/test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs @@ -0,0 +1,126 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicyTest do + use Pleroma.DataCase, async: true + + alias Pleroma.User + alias Pleroma.Web.ActivityPub.MRF.FollowBotPolicy + + import Pleroma.Factory + + describe "FollowBotPolicy" do + test "follows remote users" do + bot = insert(:user, actor_type: "Service") + remote_user = insert(:user, local: false) + clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => [remote_user.follower_address], + "cc" => ["https://www.w3.org/ns/activitystreams#Public"], + "type" => "Create", + "object" => %{ + "content" => "Test post", + "type" => "Note", + "attributedTo" => remote_user.ap_id, + "inReplyTo" => nil + }, + "actor" => remote_user.ap_id + } + + refute User.following?(bot, remote_user) + + assert User.get_follow_requests(remote_user) |> length == 0 + + FollowbotPolicy.filter(message) + + assert User.get_follow_requests(remote_user) |> length == 1 + end + + test "does not follow users with #nobot in bio" do + bot = insert(:user, actor_type: "Service") + remote_user = insert(:user, %{local: false, bio: "go away bots! #nobot"}) + clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => [remote_user.follower_address], + "cc" => ["https://www.w3.org/ns/activitystreams#Public"], + "type" => "Create", + "object" => %{ + "content" => "I don't like follow bots", + "type" => "Note", + "attributedTo" => remote_user.ap_id, + "inReplyTo" => nil + }, + "actor" => remote_user.ap_id + } + + refute User.following?(bot, remote_user) + + assert User.get_follow_requests(remote_user) |> length == 0 + + FollowbotPolicy.filter(message) + + assert User.get_follow_requests(remote_user) |> length == 0 + end + + test "does not follow local users" do + bot = insert(:user, actor_type: "Service") + local_user = insert(:user, local: true) + clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => [local_user.follower_address], + "cc" => ["https://www.w3.org/ns/activitystreams#Public"], + "type" => "Create", + "object" => %{ + "content" => "Hi I'm a local user", + "type" => "Note", + "attributedTo" => local_user.ap_id, + "inReplyTo" => nil + }, + "actor" => local_user.ap_id + } + + refute User.following?(bot, local_user) + + assert User.get_follow_requests(local_user) |> length == 0 + + FollowbotPolicy.filter(message) + + assert User.get_follow_requests(local_user) |> length == 0 + end + + test "does not follow users requiring follower approval" do + bot = insert(:user, actor_type: "Service") + remote_user = insert(:user, %{local: false, is_locked: true}) + clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => [remote_user.follower_address], + "cc" => ["https://www.w3.org/ns/activitystreams#Public"], + "type" => "Create", + "object" => %{ + "content" => "I don't like randos following me", + "type" => "Note", + "attributedTo" => remote_user.ap_id, + "inReplyTo" => nil + }, + "actor" => remote_user.ap_id + } + + refute User.following?(bot, remote_user) + + assert User.get_follow_requests(remote_user) |> length == 0 + + FollowbotPolicy.filter(message) + + assert User.get_follow_requests(remote_user) |> length == 0 + end + end +end diff --git a/test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs~ b/test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs~ new file mode 100644 index 000000000..4c39e04e8 --- /dev/null +++ b/test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs~ @@ -0,0 +1,126 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.FollowbotPolicyTest do + use Pleroma.DataCase, async: true + + alias Pleroma.User + alias Pleroma.Web.ActivityPub.MRF.FollowbotPolicy + + import Pleroma.Factory + + describe "FollowBotPolicy" do + test "follows remote users" do + bot = insert(:user, actor_type: "Service") + remote_user = insert(:user, local: false) + clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => [remote_user.follower_address], + "cc" => ["https://www.w3.org/ns/activitystreams#Public"], + "type" => "Create", + "object" => %{ + "content" => "Test post", + "type" => "Note", + "attributedTo" => remote_user.ap_id, + "inReplyTo" => nil + }, + "actor" => remote_user.ap_id + } + + refute User.following?(bot, remote_user) + + assert User.get_follow_requests(remote_user) |> length == 0 + + FollowbotPolicy.filter(message) + + assert User.get_follow_requests(remote_user) |> length == 1 + end + + test "does not follow users with #nobot in bio" do + bot = insert(:user, actor_type: "Service") + remote_user = insert(:user, %{local: false, bio: "go away bots! #nobot"}) + clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => [remote_user.follower_address], + "cc" => ["https://www.w3.org/ns/activitystreams#Public"], + "type" => "Create", + "object" => %{ + "content" => "I don't like follow bots", + "type" => "Note", + "attributedTo" => remote_user.ap_id, + "inReplyTo" => nil + }, + "actor" => remote_user.ap_id + } + + refute User.following?(bot, remote_user) + + assert User.get_follow_requests(remote_user) |> length == 0 + + FollowbotPolicy.filter(message) + + assert User.get_follow_requests(remote_user) |> length == 0 + end + + test "does not follow local users" do + bot = insert(:user, actor_type: "Service") + local_user = insert(:user, local: true) + clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => [local_user.follower_address], + "cc" => ["https://www.w3.org/ns/activitystreams#Public"], + "type" => "Create", + "object" => %{ + "content" => "Hi I'm a local user", + "type" => "Note", + "attributedTo" => local_user.ap_id, + "inReplyTo" => nil + }, + "actor" => local_user.ap_id + } + + refute User.following?(bot, local_user) + + assert User.get_follow_requests(local_user) |> length == 0 + + FollowbotPolicy.filter(message) + + assert User.get_follow_requests(local_user) |> length == 0 + end + + test "does not follow users requiring follower approval" do + bot = insert(:user, actor_type: "Service") + remote_user = insert(:user, %{local: false, is_locked: true}) + clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => [remote_user.follower_address], + "cc" => ["https://www.w3.org/ns/activitystreams#Public"], + "type" => "Create", + "object" => %{ + "content" => "I don't like randos following me", + "type" => "Note", + "attributedTo" => remote_user.ap_id, + "inReplyTo" => nil + }, + "actor" => remote_user.ap_id + } + + refute User.following?(bot, remote_user) + + assert User.get_follow_requests(remote_user) |> length == 0 + + FollowbotPolicy.filter(message) + + assert User.get_follow_requests(remote_user) |> length == 0 + end + end +end diff --git a/test/pleroma/web/activity_pub/mrf/followbot_policy_test.exs b/test/pleroma/web/activity_pub/mrf/followbot_policy_test.exs deleted file mode 100644 index 4c39e04e8..000000000 --- a/test/pleroma/web/activity_pub/mrf/followbot_policy_test.exs +++ /dev/null @@ -1,126 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.ActivityPub.MRF.FollowbotPolicyTest do - use Pleroma.DataCase, async: true - - alias Pleroma.User - alias Pleroma.Web.ActivityPub.MRF.FollowbotPolicy - - import Pleroma.Factory - - describe "FollowBotPolicy" do - test "follows remote users" do - bot = insert(:user, actor_type: "Service") - remote_user = insert(:user, local: false) - clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) - - message = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => [remote_user.follower_address], - "cc" => ["https://www.w3.org/ns/activitystreams#Public"], - "type" => "Create", - "object" => %{ - "content" => "Test post", - "type" => "Note", - "attributedTo" => remote_user.ap_id, - "inReplyTo" => nil - }, - "actor" => remote_user.ap_id - } - - refute User.following?(bot, remote_user) - - assert User.get_follow_requests(remote_user) |> length == 0 - - FollowbotPolicy.filter(message) - - assert User.get_follow_requests(remote_user) |> length == 1 - end - - test "does not follow users with #nobot in bio" do - bot = insert(:user, actor_type: "Service") - remote_user = insert(:user, %{local: false, bio: "go away bots! #nobot"}) - clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) - - message = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => [remote_user.follower_address], - "cc" => ["https://www.w3.org/ns/activitystreams#Public"], - "type" => "Create", - "object" => %{ - "content" => "I don't like follow bots", - "type" => "Note", - "attributedTo" => remote_user.ap_id, - "inReplyTo" => nil - }, - "actor" => remote_user.ap_id - } - - refute User.following?(bot, remote_user) - - assert User.get_follow_requests(remote_user) |> length == 0 - - FollowbotPolicy.filter(message) - - assert User.get_follow_requests(remote_user) |> length == 0 - end - - test "does not follow local users" do - bot = insert(:user, actor_type: "Service") - local_user = insert(:user, local: true) - clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) - - message = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => [local_user.follower_address], - "cc" => ["https://www.w3.org/ns/activitystreams#Public"], - "type" => "Create", - "object" => %{ - "content" => "Hi I'm a local user", - "type" => "Note", - "attributedTo" => local_user.ap_id, - "inReplyTo" => nil - }, - "actor" => local_user.ap_id - } - - refute User.following?(bot, local_user) - - assert User.get_follow_requests(local_user) |> length == 0 - - FollowbotPolicy.filter(message) - - assert User.get_follow_requests(local_user) |> length == 0 - end - - test "does not follow users requiring follower approval" do - bot = insert(:user, actor_type: "Service") - remote_user = insert(:user, %{local: false, is_locked: true}) - clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname) - - message = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => [remote_user.follower_address], - "cc" => ["https://www.w3.org/ns/activitystreams#Public"], - "type" => "Create", - "object" => %{ - "content" => "I don't like randos following me", - "type" => "Note", - "attributedTo" => remote_user.ap_id, - "inReplyTo" => nil - }, - "actor" => remote_user.ap_id - } - - refute User.following?(bot, remote_user) - - assert User.get_follow_requests(remote_user) |> length == 0 - - FollowbotPolicy.filter(message) - - assert User.get_follow_requests(remote_user) |> length == 0 - end - end -end -- cgit v1.2.3