|> 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
|> 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})
:follows,
:non_followers,
:non_follows,
- :recently_followed
+ :recently_followed,
+ :filtered
]
|> Enum.find(&skip?(&1, activity, user))
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 for_user_and_activity(user, activity) 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
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)
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)
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)
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")
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}"})
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)
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)
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")
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}"})
{: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