X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fnotification.ex;h=66e91fcef08272489133150458023012336c9fc1;hb=5ebffd5224729413e53a55ddda9a1f86224d7d73;hp=d145f8d5b5a42c8ba3b685196754e45a1eaf682e;hpb=2473702be22a44070fcff439ac901f5b9bb0586a;p=akkoma diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index d145f8d5b..66e91fcef 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -21,6 +21,8 @@ defmodule Pleroma.Notification do @type t :: %__MODULE__{} + @include_muted_option :with_muted + schema "notifications" do field(:seen, :boolean, default: false) belongs_to(:user, User, type: FlakeId.Ecto.CompatType) @@ -34,13 +36,31 @@ defmodule Pleroma.Notification do |> cast(attrs, [:seen]) end - def for_user_query(user, opts \\ []) do + defp for_user_query_ap_id_opts(user, opts) do + ap_id_relations = + [:block] ++ + if opts[@include_muted_option], do: [], else: [:notification_mute] + + preloaded_ap_ids = User.outgoing_relations_ap_ids(user, ap_id_relations) + + exclude_blocked_opts = Map.merge(%{blocked_users_ap_ids: preloaded_ap_ids[:block]}, opts) + + exclude_notification_muted_opts = + Map.merge(%{notification_muted_users_ap_ids: preloaded_ap_ids[:notification_mute]}, opts) + + {exclude_blocked_opts, exclude_notification_muted_opts} + end + + def for_user_query(user, opts \\ %{}) do + {exclude_blocked_opts, exclude_notification_muted_opts} = + for_user_query_ap_id_opts(user, opts) + Notification |> where(user_id: ^user.id) |> where( [n, a], fragment( - "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')", + "? not in (SELECT ap_id FROM users WHERE deactivated = 'true')", a.actor ) ) @@ -54,38 +74,75 @@ defmodule Pleroma.Notification do ) ) |> preload([n, a, o], activity: {a, object: o}) - |> exclude_muted(user, opts) + |> exclude_notification_muted(user, exclude_notification_muted_opts) + |> exclude_blocked(user, exclude_blocked_opts) |> exclude_visibility(opts) + |> exclude_move(opts) end - defp exclude_muted(query, _, %{with_muted: true}) do - query - end + defp exclude_blocked(query, user, opts) do + blocked_ap_ids = opts[:blocked_users_ap_ids] || User.blocked_users_ap_ids(user) - defp exclude_muted(query, user, _opts) do query - |> where([n, a], a.actor not in ^user.info.muted_notifications) - |> where([n, a], a.actor not in ^user.info.blocks) + |> where([n, a], a.actor not in ^blocked_ap_ids) |> where( [n, a], - fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks + fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.domain_blocks ) + end + + defp exclude_notification_muted(query, _, %{@include_muted_option => true}) do + query + end + + defp exclude_notification_muted(query, user, opts) do + notification_muted_ap_ids = + opts[:notification_muted_users_ap_ids] || User.notification_muted_users_ap_ids(user) + + query + |> where([n, a], a.actor not in ^notification_muted_ap_ids) |> join(:left, [n, a], tm in Pleroma.ThreadMute, on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data) ) |> where([n, a, o, tm], is_nil(tm.user_id)) end + defp exclude_move(query, %{with_move: true}) do + query + end + + defp exclude_move(query, _opts) do + where(query, [n, a], fragment("?->>'type' != 'Move'", a.data)) + end + @valid_visibilities ~w[direct unlisted public private] defp exclude_visibility(query, %{exclude_visibilities: visibility}) when is_list(visibility) do if Enum.all?(visibility, &(&1 in @valid_visibilities)) do query + |> join(:left, [n, a], mutated_activity in Pleroma.Activity, + on: + fragment("?->>'context'", a.data) == + fragment("?->>'context'", mutated_activity.data) and + fragment("(?->>'type' = 'Like' or ?->>'type' = 'Announce')", a.data, a.data) and + fragment("?->>'type'", mutated_activity.data) == "Create", + as: :mutated_activity + ) |> where( - [n, a], + [n, a, mutated_activity: mutated_activity], not fragment( - "activity_visibility(?, ?, ?) = ANY (?)", + """ + CASE WHEN (?->>'type') = 'Like' or (?->>'type') = 'Announce' + THEN (activity_visibility(?, ?, ?) = ANY (?)) + ELSE (activity_visibility(?, ?, ?) = ANY (?)) END + """, + a.data, + a.data, + mutated_activity.actor, + mutated_activity.recipients, + mutated_activity.data, + ^visibility, a.actor, a.recipients, a.data, @@ -100,17 +157,7 @@ defmodule Pleroma.Notification do defp exclude_visibility(query, %{exclude_visibilities: visibility}) when visibility in @valid_visibilities do - query - |> where( - [n, a], - not fragment( - "activity_visibility(?, ?, ?) = (?)", - a.actor, - a.recipients, - a.data, - ^visibility - ) - ) + exclude_visibility(query, [visibility]) end defp exclude_visibility(query, %{exclude_visibilities: visibility}) @@ -246,10 +293,13 @@ defmodule Pleroma.Notification do end end - def create_notifications(%Activity{data: %{"to" => _, "type" => type}} = activity) - when type in ["Like", "Announce", "Follow"] do - users = get_notified_from_activity(activity) - notifications = Enum.map(users, fn user -> create_notification(activity, user) end) + def create_notifications(%Activity{data: %{"type" => type}} = activity) + when type in ["Like", "Announce", "Follow", "Move", "EmojiReact"] do + notifications = + activity + |> get_notified_from_activity() + |> Enum.map(&create_notification(activity, &1)) + {:ok, notifications} end @@ -271,19 +321,15 @@ defmodule Pleroma.Notification do def get_notified_from_activity(activity, local_only \\ true) - def get_notified_from_activity( - %Activity{data: %{"to" => _, "type" => type} = _data} = activity, - local_only - ) - when type in ["Create", "Like", "Announce", "Follow"] do - recipients = - [] - |> Utils.maybe_notify_to_recipients(activity) - |> Utils.maybe_notify_mentioned_recipients(activity) - |> Utils.maybe_notify_subscribers(activity) - |> Enum.uniq() - - User.get_users_from_set(recipients, local_only) + def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only) + when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact"] do + [] + |> Utils.maybe_notify_to_recipients(activity) + |> Utils.maybe_notify_mentioned_recipients(activity) + |> Utils.maybe_notify_subscribers(activity) + |> Utils.maybe_notify_followers(activity) + |> Enum.uniq() + |> User.get_users_from_set(local_only) end def get_notified_from_activity(_, _local_only), do: [] @@ -309,7 +355,7 @@ defmodule Pleroma.Notification do def skip?( :followers, activity, - %{info: %{notification_settings: %{"followers" => false}}} = user + %{notification_settings: %{followers: false}} = user ) do actor = activity.data["actor"] follower = User.get_cached_by_ap_id(actor) @@ -319,14 +365,14 @@ defmodule Pleroma.Notification do def skip?( :non_followers, activity, - %{info: %{notification_settings: %{"non_followers" => false}}} = user + %{notification_settings: %{non_followers: false}} = user ) do actor = activity.data["actor"] follower = User.get_cached_by_ap_id(actor) !User.following?(follower, user) end - def skip?(:follows, activity, %{info: %{notification_settings: %{"follows" => false}}} = user) do + def skip?(:follows, activity, %{notification_settings: %{follows: false}} = user) do actor = activity.data["actor"] followed = User.get_cached_by_ap_id(actor) User.following?(user, followed) @@ -335,7 +381,7 @@ defmodule Pleroma.Notification do def skip?( :non_follows, activity, - %{info: %{notification_settings: %{"non_follows" => false}}} = user + %{notification_settings: %{non_follows: false}} = user ) do actor = activity.data["actor"] followed = User.get_cached_by_ap_id(actor)