X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fnotification.ex;h=0b171563b291873000182e7345711fb2939fc1d5;hb=f21b6ebd5d71b77b1f2b7c8918005c3b70752c15;hp=5c8994e358e3f4ef9069982aaef8d51f7a4ff619;hpb=9fa3f0b156f92ba575b58b191685fa068a83f4d2;p=akkoma diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 5c8994e35..0b171563b 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -31,7 +31,7 @@ defmodule Pleroma.Notification do schema "notifications" do field(:seen, :boolean, default: false) # This is an enum type in the database. If you add a new notification type, - # remembert to add a migration to add it to the `notifications_type` enum + # remember to add a migration to add it to the `notifications_type` enum # as well. field(:type, :string) belongs_to(:user, User, type: FlakeId.Ecto.CompatType) @@ -40,26 +40,6 @@ defmodule Pleroma.Notification do timestamps() end - def fill_in_notification_types do - query = - from(n in __MODULE__, - where: is_nil(n.type), - preload: :activity - ) - - query - |> Repo.all() - |> Enum.each(fn notification -> - type = - notification.activity - |> type_from_activity(no_cachex: true) - - notification - |> changeset(%{type: type}) - |> Repo.update() - end) - end - def update_notification_type(user, activity) do with %__MODULE__{} = notification <- Repo.get_by(__MODULE__, user_id: user.id, activity_id: activity.id) do @@ -81,9 +61,21 @@ defmodule Pleroma.Notification do |> Repo.aggregate(:count, :id) end + @notification_types ~w{ + favourite + follow + follow_request + mention + move + pleroma:chat_mention + pleroma:emoji_reaction + reblog + } + def changeset(%Notification{} = notification, attrs) do notification |> cast(attrs, [:seen, :type]) + |> validate_inclusion(:type, @notification_types) end @spec last_read_query(User.t()) :: Ecto.Queryable.t() @@ -138,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 @@ -166,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}) @@ -174,8 +181,16 @@ defmodule Pleroma.Notification do query |> join(:left, [n, a], mutated_activity in Pleroma.Activity, on: - fragment("?->>'context'", a.data) == - fragment("?->>'context'", mutated_activity.data) and + fragment( + "COALESCE((?->'object')->>'id', ?->>'object')", + a.data, + a.data + ) == + fragment( + "COALESCE((?->'object')->>'id', ?->>'object')", + mutated_activity.data, + mutated_activity.data + ) and fragment("(?->>'type' = 'Like' or ?->>'type' = 'Announce')", a.data, a.data) and fragment("?->>'type'", mutated_activity.data) == "Create", as: :mutated_activity @@ -337,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 @@ -367,27 +383,15 @@ defmodule Pleroma.Notification do do_send = do_send && user in enabled_receivers create_notification(activity, user, do_send) end) + |> Enum.reject(&is_nil/1) {:ok, notifications} end - defp type_from_activity(%{data: %{"type" => type}} = activity, opts \\ []) do + defp type_from_activity(%{data: %{"type" => type}} = activity) do case type do "Follow" -> - accepted_function = - if Keyword.get(opts, :no_cachex, false) do - # A special function to make this usable in a migration. - fn activity -> - with %User{} = follower <- User.get_by_ap_id(activity.data["actor"]), - %User{} = followed <- User.get_by_ap_id(activity.data["object"]) do - Pleroma.FollowingRelationship.following?(follower, followed) - end - end - else - &Activity.follow_accepted?/1 - end - - if accepted_function.(activity) do + if Activity.follow_accepted?(activity) do "follow" else "follow_request" @@ -493,6 +497,10 @@ defmodule Pleroma.Notification do end end + def get_potential_receiver_ap_ids(%{data: %{"type" => "Follow", "object" => object_id}}) do + [object_id] + end + def get_potential_receiver_ap_ids(activity) do [] |> Utils.maybe_notify_to_recipients(activity) @@ -562,11 +570,10 @@ defmodule Pleroma.Notification do def skip?(%Activity{} = activity, %User{} = user) do [ :self, - :followers, - :follows, - :non_followers, - :non_follows, - :recently_followed + :invisible, + :block_from_strangers, + :recently_followed, + :filtered ] |> Enum.find(&skip?(&1, activity, user)) end @@ -578,46 +585,22 @@ defmodule Pleroma.Notification do activity.data["actor"] == user.ap_id end - def skip?( - :followers, - %Activity{} = activity, - %User{notification_settings: %{followers: false}} = user - ) do + def skip?(:invisible, %Activity{} = activity, _) do actor = activity.data["actor"] - follower = User.get_cached_by_ap_id(actor) - User.following?(follower, user) + user = User.get_cached_by_ap_id(actor) + User.invisible?(user) end def skip?( - :non_followers, + :block_from_strangers, %Activity{} = activity, - %User{notification_settings: %{non_followers: false}} = user + %User{notification_settings: %{block_from_strangers: true}} = user ) do actor = activity.data["actor"] follower = User.get_cached_by_ap_id(actor) !User.following?(follower, user) end - def skip?( - :follows, - %Activity{} = activity, - %User{notification_settings: %{follows: false}} = user - ) do - actor = activity.data["actor"] - followed = User.get_cached_by_ap_id(actor) - User.following?(user, followed) - end - - def skip?( - :non_follows, - %Activity{} = activity, - %User{notification_settings: %{non_follows: false}} = user - ) do - actor = activity.data["actor"] - followed = User.get_cached_by_ap_id(actor) - !User.following?(user, followed) - end - # To do: consider defining recency in hours and checking FollowingRelationship with a single SQL def skip?(:recently_followed, %Activity{data: %{"type" => "Follow"}} = activity, %User{} = user) do actor = activity.data["actor"] @@ -629,6 +612,26 @@ 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) + + 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