forked from AkkomaGang/akkoma
Skip notifications for statuses that contain an irreversible filtered word
This commit is contained in:
parent
4a8c26654e
commit
5af1bf443d
2 changed files with 119 additions and 18 deletions
|
@ -130,6 +130,7 @@ def for_user_query(user, opts \\ %{}) do
|
||||||
|> preload([n, a, o], activity: {a, object: o})
|
|> preload([n, a, o], activity: {a, object: o})
|
||||||
|> exclude_notification_muted(user, exclude_notification_muted_opts)
|
|> exclude_notification_muted(user, exclude_notification_muted_opts)
|
||||||
|> exclude_blocked(user, exclude_blocked_opts)
|
|> exclude_blocked(user, exclude_blocked_opts)
|
||||||
|
|> exclude_filtered(user)
|
||||||
|> exclude_visibility(opts)
|
|> exclude_visibility(opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -158,6 +159,20 @@ defp exclude_notification_muted(query, user, opts) do
|
||||||
|> where([n, a, o, tm], is_nil(tm.user_id))
|
|> where([n, a, o, tm], is_nil(tm.user_id))
|
||||||
end
|
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]
|
@valid_visibilities ~w[direct unlisted public private]
|
||||||
|
|
||||||
defp exclude_visibility(query, %{exclude_visibilities: visibility})
|
defp exclude_visibility(query, %{exclude_visibilities: visibility})
|
||||||
|
@ -555,7 +570,8 @@ def skip?(%Activity{} = activity, %User{} = user) do
|
||||||
:follows,
|
:follows,
|
||||||
:non_followers,
|
:non_followers,
|
||||||
:non_follows,
|
:non_follows,
|
||||||
:recently_followed
|
:recently_followed,
|
||||||
|
:filtered
|
||||||
]
|
]
|
||||||
|> Enum.find(&skip?(&1, activity, user))
|
|> Enum.find(&skip?(&1, activity, user))
|
||||||
end
|
end
|
||||||
|
@ -624,6 +640,24 @@ def skip?(:recently_followed, %Activity{data: %{"type" => "Follow"}} = activity,
|
||||||
end)
|
end)
|
||||||
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 skip?(_, _, _), do: false
|
||||||
|
|
||||||
def for_user_and_activity(user, activity) do
|
def for_user_and_activity(user, activity) do
|
||||||
|
|
|
@ -324,6 +324,44 @@ test "it disables notifications from people who are invisible" do
|
||||||
{:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})
|
{:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})
|
||||||
refute Notification.create_notification(status, user)
|
refute Notification.create_notification(status, user)
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
describe "follow / follow_request notifications" do
|
describe "follow / follow_request notifications" do
|
||||||
|
@ -990,8 +1028,13 @@ test "move activity generates a notification" do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "for_user" do
|
describe "for_user" do
|
||||||
test "it returns notifications for muted user without notifications" do
|
setup do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, %{user: user}}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it returns notifications for muted user without notifications", %{user: user} do
|
||||||
muted = insert(:user)
|
muted = insert(:user)
|
||||||
{:ok, _user_relationships} = User.mute(user, muted, false)
|
{:ok, _user_relationships} = User.mute(user, muted, false)
|
||||||
|
|
||||||
|
@ -1002,8 +1045,7 @@ test "it returns notifications for muted user without notifications" do
|
||||||
assert notification.activity.object
|
assert notification.activity.object
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it doesn't return notifications for muted user with notifications" do
|
test "it doesn't return notifications for muted user with notifications", %{user: user} do
|
||||||
user = insert(:user)
|
|
||||||
muted = insert(:user)
|
muted = insert(:user)
|
||||||
{:ok, _user_relationships} = User.mute(user, muted)
|
{:ok, _user_relationships} = User.mute(user, muted)
|
||||||
|
|
||||||
|
@ -1012,8 +1054,7 @@ test "it doesn't return notifications for muted user with notifications" do
|
||||||
assert Notification.for_user(user) == []
|
assert Notification.for_user(user) == []
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it doesn't return notifications for blocked user" do
|
test "it doesn't return notifications for blocked user", %{user: user} do
|
||||||
user = insert(:user)
|
|
||||||
blocked = insert(:user)
|
blocked = insert(:user)
|
||||||
{:ok, _user_relationship} = User.block(user, blocked)
|
{:ok, _user_relationship} = User.block(user, blocked)
|
||||||
|
|
||||||
|
@ -1022,8 +1063,7 @@ test "it doesn't return notifications for blocked user" do
|
||||||
assert Notification.for_user(user) == []
|
assert Notification.for_user(user) == []
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it doesn't return notifications for domain-blocked non-followed user" do
|
test "it doesn't return notifications for domain-blocked non-followed user", %{user: user} do
|
||||||
user = insert(:user)
|
|
||||||
blocked = insert(:user, ap_id: "http://some-domain.com")
|
blocked = insert(:user, ap_id: "http://some-domain.com")
|
||||||
{:ok, user} = User.block_domain(user, "some-domain.com")
|
{:ok, user} = User.block_domain(user, "some-domain.com")
|
||||||
|
|
||||||
|
@ -1044,8 +1084,7 @@ test "it returns notifications for domain-blocked but followed user" do
|
||||||
assert length(Notification.for_user(user)) == 1
|
assert length(Notification.for_user(user)) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it doesn't return notifications for muted thread" do
|
test "it doesn't return notifications for muted thread", %{user: user} do
|
||||||
user = insert(:user)
|
|
||||||
another_user = insert(:user)
|
another_user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
|
{:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
|
||||||
|
@ -1054,8 +1093,7 @@ test "it doesn't return notifications for muted thread" do
|
||||||
assert Notification.for_user(user) == []
|
assert Notification.for_user(user) == []
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns notifications from a muted user when with_muted is set" do
|
test "it returns notifications from a muted user when with_muted is set", %{user: user} do
|
||||||
user = insert(:user)
|
|
||||||
muted = insert(:user)
|
muted = insert(:user)
|
||||||
{:ok, _user_relationships} = User.mute(user, muted)
|
{:ok, _user_relationships} = User.mute(user, muted)
|
||||||
|
|
||||||
|
@ -1064,8 +1102,9 @@ test "it returns notifications from a muted user when with_muted is set" do
|
||||||
assert length(Notification.for_user(user, %{with_muted: true})) == 1
|
assert length(Notification.for_user(user, %{with_muted: true})) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it doesn't return notifications from a blocked user when with_muted is set" do
|
test "it doesn't return notifications from a blocked user when with_muted is set", %{
|
||||||
user = insert(:user)
|
user: user
|
||||||
|
} do
|
||||||
blocked = insert(:user)
|
blocked = insert(:user)
|
||||||
{:ok, _user_relationship} = User.block(user, blocked)
|
{:ok, _user_relationship} = User.block(user, blocked)
|
||||||
|
|
||||||
|
@ -1075,8 +1114,8 @@ test "it doesn't return notifications from a blocked user when with_muted is set
|
||||||
end
|
end
|
||||||
|
|
||||||
test "when with_muted is set, " <>
|
test "when with_muted is set, " <>
|
||||||
"it doesn't return notifications from a domain-blocked non-followed user" do
|
"it doesn't return notifications from a domain-blocked non-followed user",
|
||||||
user = insert(:user)
|
%{user: user} do
|
||||||
blocked = insert(:user, ap_id: "http://some-domain.com")
|
blocked = insert(:user, ap_id: "http://some-domain.com")
|
||||||
{:ok, user} = User.block_domain(user, "some-domain.com")
|
{:ok, user} = User.block_domain(user, "some-domain.com")
|
||||||
|
|
||||||
|
@ -1085,8 +1124,7 @@ test "when with_muted is set, " <>
|
||||||
assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
|
assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns notifications from muted threads when with_muted is set" do
|
test "it returns notifications from muted threads when with_muted is set", %{user: user} do
|
||||||
user = insert(:user)
|
|
||||||
another_user = insert(:user)
|
another_user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
|
{:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
|
||||||
|
@ -1094,5 +1132,34 @@ test "it returns notifications from muted threads when with_muted is set" do
|
||||||
{:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
|
{:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
|
||||||
assert length(Notification.for_user(user, %{with_muted: true})) == 1
|
assert length(Notification.for_user(user, %{with_muted: true})) == 1
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue