diff options
| author | Sergey Suprunenko <suprunenko.s@gmail.com> | 2019-11-22 19:52:50 +0100 | 
|---|---|---|
| committer | Alexander Strizhakov <alex.strizhakov@gmail.com> | 2020-07-06 09:28:22 +0300 | 
| commit | 5af1bf443dfd21a6b0be9efc1f55a73e590f6ba3 (patch) | |
| tree | d7e5766a8adda68a088854cd796b0d6045075d33 | |
| parent | 4a8c26654eb7ca7ce049dd4c485c16672b5837a6 (diff) | |
| download | pleroma-5af1bf443dfd21a6b0be9efc1f55a73e590f6ba3.tar.gz pleroma-5af1bf443dfd21a6b0be9efc1f55a73e590f6ba3.zip | |
Skip notifications for statuses that contain an irreversible filtered word
| -rw-r--r-- | lib/pleroma/notification.ex | 36 | ||||
| -rw-r--r-- | test/notification_test.exs | 101 | 
2 files changed, 119 insertions, 18 deletions
| diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 2ef1a80c5..3f749cace 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -130,6 +130,7 @@ defmodule Pleroma.Notification do      |> preload([n, a, o], activity: {a, object: o})      |> exclude_notification_muted(user, exclude_notification_muted_opts)      |> exclude_blocked(user, exclude_blocked_opts) +    |> exclude_filtered(user)      |> exclude_visibility(opts)    end @@ -158,6 +159,20 @@ defmodule Pleroma.Notification do      |> where([n, a, o, tm], is_nil(tm.user_id))    end +  defp exclude_filtered(query, user) do +    case Pleroma.Filter.compose_regex(user) do +      nil -> +        query + +      regex -> +        from([_n, a, o] in query, +          where: +            fragment("not(?->>'content' ~* ?)", o.data, ^regex) or +              fragment("?->>'actor' = ?", o.data, ^user.ap_id) +        ) +    end +  end +    @valid_visibilities ~w[direct unlisted public private]    defp exclude_visibility(query, %{exclude_visibilities: visibility}) @@ -555,7 +570,8 @@ defmodule Pleroma.Notification do        :follows,        :non_followers,        :non_follows, -      :recently_followed +      :recently_followed, +      :filtered      ]      |> Enum.find(&skip?(&1, activity, user))    end @@ -624,6 +640,24 @@ defmodule Pleroma.Notification do      end)    end +  def skip?(:filtered, activity, user) do +    object = Object.normalize(activity) + +    cond do +      is_nil(object) -> +        false + +      object.data["actor"] == user.ap_id -> +        false + +      not is_nil(regex = Pleroma.Filter.compose_regex(user, :re)) -> +        Regex.match?(regex, object.data["content"]) + +      true -> +        false +    end +  end +    def skip?(_, _, _), do: false    def for_user_and_activity(user, activity) do diff --git a/test/notification_test.exs b/test/notification_test.exs index 6add3f7eb..9ac6925c3 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -324,6 +324,44 @@ defmodule Pleroma.NotificationTest do        {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})        refute Notification.create_notification(status, user)      end + +    test "it doesn't create notifications if content matches with an irreversible filter" do +      user = insert(:user) +      subscriber = insert(:user) + +      User.subscribe(subscriber, user) +      insert(:filter, user: subscriber, phrase: "cofe", hide: true) + +      {:ok, status} = CommonAPI.post(user, %{"status" => "got cofe?"}) + +      assert {:ok, [nil]} == Notification.create_notifications(status) +    end + +    test "it creates notifications if content matches with a not irreversible filter" do +      user = insert(:user) +      subscriber = insert(:user) + +      User.subscribe(subscriber, user) +      insert(:filter, user: subscriber, phrase: "cofe", hide: false) + +      {:ok, status} = CommonAPI.post(user, %{"status" => "got cofe?"}) +      {:ok, [notification]} = Notification.create_notifications(status) + +      assert notification +    end + +    test "it creates notifications when someone likes user's status with a filtered word" do +      user = insert(:user) +      other_user = insert(:user) +      insert(:filter, user: user, phrase: "tesla", hide: true) + +      {:ok, activity_one} = CommonAPI.post(user, %{"status" => "wow tesla"}) +      {:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, other_user) + +      {:ok, [notification]} = Notification.create_notifications(activity_two) + +      assert notification +    end    end    describe "follow / follow_request notifications" do @@ -990,8 +1028,13 @@ defmodule Pleroma.NotificationTest do    end    describe "for_user" do -    test "it returns notifications for muted user without notifications" do +    setup do        user = insert(:user) + +      {:ok, %{user: user}} +    end + +    test "it returns notifications for muted user without notifications", %{user: user} do        muted = insert(:user)        {:ok, _user_relationships} = User.mute(user, muted, false) @@ -1002,8 +1045,7 @@ defmodule Pleroma.NotificationTest do        assert notification.activity.object      end -    test "it doesn't return notifications for muted user with notifications" do -      user = insert(:user) +    test "it doesn't return notifications for muted user with notifications", %{user: user} do        muted = insert(:user)        {:ok, _user_relationships} = User.mute(user, muted) @@ -1012,8 +1054,7 @@ defmodule Pleroma.NotificationTest do        assert Notification.for_user(user) == []      end -    test "it doesn't return notifications for blocked user" do -      user = insert(:user) +    test "it doesn't return notifications for blocked user", %{user: user} do        blocked = insert(:user)        {:ok, _user_relationship} = User.block(user, blocked) @@ -1022,8 +1063,7 @@ defmodule Pleroma.NotificationTest do        assert Notification.for_user(user) == []      end -    test "it doesn't return notifications for domain-blocked non-followed user" do -      user = insert(:user) +    test "it doesn't return notifications for domain-blocked non-followed user", %{user: user} do        blocked = insert(:user, ap_id: "http://some-domain.com")        {:ok, user} = User.block_domain(user, "some-domain.com") @@ -1044,8 +1084,7 @@ defmodule Pleroma.NotificationTest do        assert length(Notification.for_user(user)) == 1      end -    test "it doesn't return notifications for muted thread" do -      user = insert(:user) +    test "it doesn't return notifications for muted thread", %{user: user} do        another_user = insert(:user)        {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"}) @@ -1054,8 +1093,7 @@ defmodule Pleroma.NotificationTest do        assert Notification.for_user(user) == []      end -    test "it returns notifications from a muted user when with_muted is set" do -      user = insert(:user) +    test "it returns notifications from a muted user when with_muted is set", %{user: user} do        muted = insert(:user)        {:ok, _user_relationships} = User.mute(user, muted) @@ -1064,8 +1102,9 @@ defmodule Pleroma.NotificationTest do        assert length(Notification.for_user(user, %{with_muted: true})) == 1      end -    test "it doesn't return notifications from a blocked user when with_muted is set" do -      user = insert(:user) +    test "it doesn't return notifications from a blocked user when with_muted is set", %{ +      user: user +    } do        blocked = insert(:user)        {:ok, _user_relationship} = User.block(user, blocked) @@ -1075,8 +1114,8 @@ defmodule Pleroma.NotificationTest do      end      test "when with_muted is set, " <> -           "it doesn't return notifications from a domain-blocked non-followed user" do -      user = insert(:user) +           "it doesn't return notifications from a domain-blocked non-followed user", +         %{user: user} do        blocked = insert(:user, ap_id: "http://some-domain.com")        {:ok, user} = User.block_domain(user, "some-domain.com") @@ -1085,8 +1124,7 @@ defmodule Pleroma.NotificationTest do        assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))      end -    test "it returns notifications from muted threads when with_muted is set" do -      user = insert(:user) +    test "it returns notifications from muted threads when with_muted is set", %{user: user} do        another_user = insert(:user)        {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"}) @@ -1094,5 +1132,34 @@ defmodule Pleroma.NotificationTest do        {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])        assert length(Notification.for_user(user, %{with_muted: true})) == 1      end + +    test "it doesn't return notifications about mentiones with filtered word", %{user: user} do +      insert(:filter, user: user, phrase: "cofe", hide: true) +      another_user = insert(:user) + +      {:ok, _activity} = +        CommonAPI.post(another_user, %{"status" => "@#{user.nickname} got cofe?"}) + +      assert Enum.empty?(Notification.for_user(user)) +    end + +    test "it returns notifications about mentiones with not hidden filtered word", %{user: user} do +      insert(:filter, user: user, phrase: "test", hide: false) +      another_user = insert(:user) + +      {:ok, _activity} = CommonAPI.post(another_user, %{"status" => "@#{user.nickname} test"}) + +      assert length(Notification.for_user(user)) == 1 +    end + +    test "it returns notifications about favorites with filtered word", %{user: user} do +      insert(:filter, user: user, phrase: "cofe", hide: true) +      another_user = insert(:user) + +      {:ok, activity} = CommonAPI.post(user, %{"status" => "Give me my cofe!"}) +      {:ok, _, _} = CommonAPI.favorite(activity.id, another_user) + +      assert length(Notification.for_user(user)) == 1 +    end    end  end | 
