From 4a8c26654eb7ca7ce049dd4c485c16672b5837a6 Mon Sep 17 00:00:00 2001 From: Sergey Suprunenko Date: Sat, 16 Nov 2019 22:54:13 +0100 Subject: Restrict statuses that contain user's irreversible filters --- lib/pleroma/filter.ex | 42 ++++++++++++++++++++-- lib/pleroma/web/activity_pub/activity_pub.ex | 22 ++++++++++++ .../mastodon_api/controllers/filter_controller.ex | 2 +- 3 files changed, 63 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/filter.ex b/lib/pleroma/filter.ex index 4d61b3650..91884c6b3 100644 --- a/lib/pleroma/filter.ex +++ b/lib/pleroma/filter.ex @@ -34,10 +34,18 @@ defmodule Pleroma.Filter do Repo.one(query) end - def get_filters(%User{id: user_id} = _user) do + def get_active(query) do + from(f in query, where: is_nil(f.expires_at) or f.expires_at > ^NaiveDateTime.utc_now()) + end + + def get_irreversible(query) do + from(f in query, where: f.hide) + end + + def get_by_user(query, %User{id: user_id} = _user) do query = from( - f in Pleroma.Filter, + f in query, where: f.user_id == ^user_id, order_by: [desc: :id] ) @@ -95,4 +103,34 @@ defmodule Pleroma.Filter do |> validate_required([:phrase, :context]) |> Repo.update() end + + def compose_regex(user_or_filters, format \\ :postgres) + + def compose_regex(%User{} = user, format) do + __MODULE__ + |> get_active() + |> get_irreversible() + |> get_by_user(user) + |> compose_regex(format) + end + + def compose_regex([_ | _] = filters, format) do + phrases = + filters + |> Enum.map(& &1.phrase) + |> Enum.join("|") + + case format do + :postgres -> + "\\y(#{phrases})\\y" + + :re -> + ~r/\b#{phrases}\b/i + + _ -> + nil + end + end + + def compose_regex(_, _), do: nil end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 94117202c..31353c866 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do alias Pleroma.Constants alias Pleroma.Conversation alias Pleroma.Conversation.Participation + alias Pleroma.Filter alias Pleroma.Maps alias Pleroma.Notification alias Pleroma.Object @@ -961,6 +962,26 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_instance(query, _), do: query + defp restrict_filtered(query, %{user: %User{} = user}) do + case Filter.compose_regex(user) do + nil -> + query + + regex -> + from([activity, object] in query, + where: + fragment("not(?->>'content' ~* ?)", object.data, ^regex) or + activity.actor == ^user.ap_id + ) + end + end + + defp restrict_filtered(query, %{blocking_user: %User{} = user}) do + restrict_filtered(query, %{user: user}) + end + + defp restrict_filtered(query, _), do: query + defp exclude_poll_votes(query, %{include_poll_votes: true}), do: query defp exclude_poll_votes(query, _) do @@ -1099,6 +1120,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> restrict_muted_reblogs(restrict_muted_reblogs_opts) |> restrict_instance(opts) |> restrict_announce_object_actor(opts) + |> restrict_filtered(opts) |> Activity.restrict_deactivated_users() |> exclude_poll_votes(opts) |> exclude_chat_messages(opts) diff --git a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex index abbf0ce02..db1ff3189 100644 --- a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex @@ -22,7 +22,7 @@ defmodule Pleroma.Web.MastodonAPI.FilterController do @doc "GET /api/v1/filters" def index(%{assigns: %{user: user}} = conn, _) do - filters = Filter.get_filters(user) + filters = Filter.get_by_user(Filter, user) render(conn, "index.json", filters: filters) end -- cgit v1.2.3 From 5af1bf443dfd21a6b0be9efc1f55a73e590f6ba3 Mon Sep 17 00:00:00 2001 From: Sergey Suprunenko Date: Fri, 22 Nov 2019 19:52:50 +0100 Subject: Skip notifications for statuses that contain an irreversible filtered word --- lib/pleroma/notification.ex | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'lib') 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 -- cgit v1.2.3 From 8277b29790dfd283d94b995539dcb28e51131150 Mon Sep 17 00:00:00 2001 From: Sergey Suprunenko Date: Mon, 25 Nov 2019 16:59:55 +0100 Subject: Restrict thread statuses that contain user's irreversible filters --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 31353c866..8abbef487 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -447,6 +447,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> maybe_set_thread_muted_field(opts) |> restrict_blocked(opts) |> restrict_recipients(recipients, opts[:user]) + |> restrict_filtered(opts) |> where( [activity], fragment( @@ -1112,6 +1113,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> restrict_favorited_by(opts) |> restrict_blocked(restrict_blocked_opts) |> restrict_muted(restrict_muted_opts) + |> restrict_filtered(opts) |> restrict_media(opts) |> restrict_visibility(opts) |> restrict_thread_visibility(opts, config) -- cgit v1.2.3 From 6558f31cda07b8472ed99823ed0f46deffa584cc Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Fri, 7 Feb 2020 18:16:39 +0300 Subject: don't filter notifications for follow and move types --- lib/pleroma/notification.ex | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 3f749cace..d439f51bc 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -640,6 +640,8 @@ defmodule Pleroma.Notification do end) end + def skip?(:filtered, %{data: %{"type" => type}}, _) when type in ["Follow", "Move"], do: false + def skip?(:filtered, activity, user) do object = Object.normalize(activity) -- cgit v1.2.3 From 771748db1fa01a71c52c20b890e1b80bfcf1e230 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 26 Feb 2020 13:59:07 +0000 Subject: Apply suggestion to lib/pleroma/filter.ex --- lib/pleroma/filter.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/filter.ex b/lib/pleroma/filter.ex index 91884c6b3..98cb575a9 100644 --- a/lib/pleroma/filter.ex +++ b/lib/pleroma/filter.ex @@ -42,7 +42,7 @@ defmodule Pleroma.Filter do from(f in query, where: f.hide) end - def get_by_user(query, %User{id: user_id} = _user) do + def get_filters(query \\ __MODULE__, %User{id: user_id}) do query = from( f in query, -- cgit v1.2.3 From 20c27bef4083330a2415f1c0a04e4cad128b267a Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 26 Feb 2020 17:50:56 +0300 Subject: renaming back and reject nil on create --- lib/pleroma/filter.ex | 2 +- lib/pleroma/notification.ex | 1 + lib/pleroma/web/mastodon_api/controllers/filter_controller.ex | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/filter.ex b/lib/pleroma/filter.ex index 98cb575a9..5d6df9530 100644 --- a/lib/pleroma/filter.ex +++ b/lib/pleroma/filter.ex @@ -110,7 +110,7 @@ defmodule Pleroma.Filter do __MODULE__ |> get_active() |> get_irreversible() - |> get_by_user(user) + |> get_filters(user) |> compose_regex(format) end diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index d439f51bc..fcb2144ae 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -352,6 +352,7 @@ defmodule Pleroma.Notification do end end + @spec create_notifications(Activity.t(), keyword()) :: {:ok, [Notification.t()] | []} def create_notifications(activity, options \\ []) def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = activity, options) do diff --git a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex index db1ff3189..abbf0ce02 100644 --- a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex @@ -22,7 +22,7 @@ defmodule Pleroma.Web.MastodonAPI.FilterController do @doc "GET /api/v1/filters" def index(%{assigns: %{user: user}} = conn, _) do - filters = Filter.get_by_user(Filter, user) + filters = Filter.get_filters(user) render(conn, "index.json", filters: filters) end -- cgit v1.2.3