Skip notifications for statuses that contain an irreversible filtered word

This commit is contained in:
Sergey Suprunenko 2019-11-22 19:52:50 +01:00
parent 73b284ae62
commit 54fa6ab8f6
No known key found for this signature in database
GPG Key ID: 5DCA7D1BE3914F9C
2 changed files with 124 additions and 19 deletions

View File

@ -6,6 +6,7 @@ defmodule Pleroma.Notification do
use Ecto.Schema
alias Pleroma.Activity
alias Pleroma.Filter
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Pagination
@ -68,14 +69,16 @@ defmodule Pleroma.Notification do
|> join(:left, [n, a], object in Object,
on:
fragment(
"(?->>'id') = COALESCE((? -> 'object'::text) ->> 'id'::text)",
"(?->>'id') = COALESCE(?->'object'->>'id', ?->>'object')",
object.data,
a.data,
a.data
)
)
|> 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
@ -106,6 +109,20 @@ defmodule Pleroma.Notification do
|> where([n, a, o, tm], is_nil(tm.user_id))
end
defp exclude_filtered(query, user) do
case 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})
@ -325,7 +342,8 @@ defmodule Pleroma.Notification do
:follows,
:non_followers,
:non_follows,
:recently_followed
:recently_followed,
:filtered
]
|> Enum.any?(&skip?(&1, activity, user))
end
@ -381,5 +399,23 @@ 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 = Filter.compose_regex(user, :re)) ->
Regex.match?(regex, object.data["content"])
true ->
false
end
end
def skip?(_, _, _), do: false
end

View File

@ -202,6 +202,44 @@ defmodule Pleroma.NotificationTest do
assert {:ok, []} == Notification.create_notifications(status)
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 "get notification" do
@ -662,8 +700,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)
@ -672,8 +715,7 @@ defmodule Pleroma.NotificationTest do
assert length(Notification.for_user(user)) == 1
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)
@ -682,8 +724,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)
@ -692,8 +733,7 @@ defmodule Pleroma.NotificationTest do
assert Notification.for_user(user) == []
end
test "it doesn't return notificatitons for blocked domain" do
user = insert(:user)
test "it doesn't return notificatitons for blocked domain", %{user: user} do
blocked = insert(:user, ap_id: "http://some-domain.com")
{:ok, user} = User.block_domain(user, "some-domain.com")
@ -702,8 +742,7 @@ defmodule Pleroma.NotificationTest do
assert Notification.for_user(user) == []
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}"})
@ -712,8 +751,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)
@ -722,8 +760,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)
@ -732,8 +771,9 @@ defmodule Pleroma.NotificationTest do
assert length(Notification.for_user(user, %{with_muted: true})) == 0
end
test "it doesn't return notifications from a domain-blocked user when with_muted is set" do
user = insert(:user)
test "it doesn't return notifications from a domain-blocked user when with_muted is set", %{
user: user
} do
blocked = insert(:user, ap_id: "http://some-domain.com")
{:ok, user} = User.block_domain(user, "some-domain.com")
@ -742,8 +782,7 @@ defmodule Pleroma.NotificationTest do
assert length(Notification.for_user(user, %{with_muted: true})) == 0
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}"})
@ -751,5 +790,35 @@ 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