Feature/1072 muting notifications
This commit is contained in:
parent
9f211838ec
commit
e7c39b7ac8
13 changed files with 390 additions and 64 deletions
|
|
@ -11,7 +11,6 @@ defmodule Pleroma.Notification do
|
|||
alias Pleroma.Pagination
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.Push
|
||||
alias Pleroma.Web.Streamer
|
||||
|
|
@ -32,31 +31,47 @@ defmodule Pleroma.Notification do
|
|||
|> cast(attrs, [:seen])
|
||||
end
|
||||
|
||||
def for_user_query(user) do
|
||||
Notification
|
||||
|> where(user_id: ^user.id)
|
||||
|> where(
|
||||
[n, a],
|
||||
fragment(
|
||||
"? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')",
|
||||
a.actor
|
||||
)
|
||||
)
|
||||
|> join(:inner, [n], activity in assoc(n, :activity))
|
||||
|> join(:left, [n, a], object in Object,
|
||||
on:
|
||||
def for_user_query(user, opts) do
|
||||
query =
|
||||
Notification
|
||||
|> where(user_id: ^user.id)
|
||||
|> where(
|
||||
[n, a],
|
||||
fragment(
|
||||
"(?->>'id') = COALESCE((? -> 'object'::text) ->> 'id'::text)",
|
||||
object.data,
|
||||
a.data
|
||||
"? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')",
|
||||
a.actor
|
||||
)
|
||||
)
|
||||
|> preload([n, a, o], activity: {a, object: o})
|
||||
)
|
||||
|> join(:inner, [n], activity in assoc(n, :activity))
|
||||
|> join(:left, [n, a], object in Object,
|
||||
on:
|
||||
fragment(
|
||||
"(?->>'id') = COALESCE((? -> 'object'::text) ->> 'id'::text)",
|
||||
object.data,
|
||||
a.data
|
||||
)
|
||||
)
|
||||
|> preload([n, a, o], activity: {a, object: o})
|
||||
|
||||
if opts[:with_muted] do
|
||||
query
|
||||
else
|
||||
where(query, [n, a], a.actor not in ^user.info.muted_notifications)
|
||||
|> where([n, a], a.actor not in ^user.info.blocks)
|
||||
|> where(
|
||||
[n, a],
|
||||
fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks
|
||||
)
|
||||
|> 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.id))
|
||||
end
|
||||
end
|
||||
|
||||
def for_user(user, opts \\ %{}) do
|
||||
user
|
||||
|> for_user_query()
|
||||
|> for_user_query(opts)
|
||||
|> Pagination.fetch_paginated(opts)
|
||||
end
|
||||
|
||||
|
|
@ -179,11 +194,10 @@ defmodule Pleroma.Notification do
|
|||
|
||||
def get_notified_from_activity(_, _local_only), do: []
|
||||
|
||||
@spec skip?(Activity.t(), User.t()) :: boolean()
|
||||
def skip?(activity, user) do
|
||||
[
|
||||
:self,
|
||||
:blocked,
|
||||
:muted,
|
||||
:followers,
|
||||
:follows,
|
||||
:non_followers,
|
||||
|
|
@ -193,21 +207,11 @@ defmodule Pleroma.Notification do
|
|||
|> Enum.any?(&skip?(&1, activity, user))
|
||||
end
|
||||
|
||||
@spec skip?(atom(), Activity.t(), User.t()) :: boolean()
|
||||
def skip?(:self, activity, user) do
|
||||
activity.data["actor"] == user.ap_id
|
||||
end
|
||||
|
||||
def skip?(:blocked, activity, user) do
|
||||
actor = activity.data["actor"]
|
||||
User.blocks?(user, %{ap_id: actor})
|
||||
end
|
||||
|
||||
def skip?(:muted, activity, user) do
|
||||
actor = activity.data["actor"]
|
||||
|
||||
User.mutes?(user, %{ap_id: actor}) or CommonAPI.thread_muted?(user, activity)
|
||||
end
|
||||
|
||||
def skip?(
|
||||
:followers,
|
||||
activity,
|
||||
|
|
|
|||
|
|
@ -749,10 +749,13 @@ defmodule Pleroma.User do
|
|||
|> Repo.all()
|
||||
end
|
||||
|
||||
def mute(muter, %User{ap_id: ap_id}) do
|
||||
@spec mute(User.t(), User.t(), boolean()) :: {:ok, User.t()} | {:error, String.t()}
|
||||
def mute(muter, %User{ap_id: ap_id}, notifications? \\ true) do
|
||||
info = muter.info
|
||||
|
||||
info_cng =
|
||||
muter.info
|
||||
|> User.Info.add_to_mutes(ap_id)
|
||||
User.Info.add_to_mutes(info, ap_id)
|
||||
|> User.Info.add_to_muted_notifications(info, ap_id, notifications?)
|
||||
|
||||
cng =
|
||||
change(muter)
|
||||
|
|
@ -762,9 +765,11 @@ defmodule Pleroma.User do
|
|||
end
|
||||
|
||||
def unmute(muter, %{ap_id: ap_id}) do
|
||||
info = muter.info
|
||||
|
||||
info_cng =
|
||||
muter.info
|
||||
|> User.Info.remove_from_mutes(ap_id)
|
||||
User.Info.remove_from_mutes(info, ap_id)
|
||||
|> User.Info.remove_from_muted_notifications(info, ap_id)
|
||||
|
||||
cng =
|
||||
change(muter)
|
||||
|
|
@ -860,6 +865,12 @@ defmodule Pleroma.User do
|
|||
def mutes?(nil, _), do: false
|
||||
def mutes?(user, %{ap_id: ap_id}), do: Enum.member?(user.info.mutes, ap_id)
|
||||
|
||||
@spec muted_notifications?(User.t() | nil, User.t() | map()) :: boolean()
|
||||
def muted_notifications?(nil, _), do: false
|
||||
|
||||
def muted_notifications?(user, %{ap_id: ap_id}),
|
||||
do: Enum.member?(user.info.muted_notifications, ap_id)
|
||||
|
||||
def blocks?(%User{info: info} = _user, %{ap_id: ap_id}) do
|
||||
blocks = info.blocks
|
||||
domain_blocks = info.domain_blocks
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ defmodule Pleroma.User.Info do
|
|||
field(:domain_blocks, {:array, :string}, default: [])
|
||||
field(:mutes, {:array, :string}, default: [])
|
||||
field(:muted_reblogs, {:array, :string}, default: [])
|
||||
field(:muted_notifications, {:array, :string}, default: [])
|
||||
field(:subscribers, {:array, :string}, default: [])
|
||||
field(:deactivated, :boolean, default: false)
|
||||
field(:no_rich_text, :boolean, default: false)
|
||||
|
|
@ -120,6 +121,16 @@ defmodule Pleroma.User.Info do
|
|||
|> validate_required([:mutes])
|
||||
end
|
||||
|
||||
@spec set_notification_mutes(Changeset.t(), [String.t()], boolean()) :: Changeset.t()
|
||||
def set_notification_mutes(changeset, muted_notifications, notifications?) do
|
||||
if notifications? do
|
||||
put_change(changeset, :muted_notifications, muted_notifications)
|
||||
|> validate_required([:muted_notifications])
|
||||
else
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
def set_blocks(info, blocks) do
|
||||
params = %{blocks: blocks}
|
||||
|
||||
|
|
@ -136,14 +147,31 @@ defmodule Pleroma.User.Info do
|
|||
|> validate_required([:subscribers])
|
||||
end
|
||||
|
||||
@spec add_to_mutes(Info.t(), String.t()) :: Changeset.t()
|
||||
def add_to_mutes(info, muted) do
|
||||
set_mutes(info, Enum.uniq([muted | info.mutes]))
|
||||
end
|
||||
|
||||
@spec add_to_muted_notifications(Changeset.t(), Info.t(), String.t(), boolean()) ::
|
||||
Changeset.t()
|
||||
def add_to_muted_notifications(changeset, info, muted, notifications?) do
|
||||
set_notification_mutes(
|
||||
changeset,
|
||||
Enum.uniq([muted | info.muted_notifications]),
|
||||
notifications?
|
||||
)
|
||||
end
|
||||
|
||||
@spec remove_from_mutes(Info.t(), String.t()) :: Changeset.t()
|
||||
def remove_from_mutes(info, muted) do
|
||||
set_mutes(info, List.delete(info.mutes, muted))
|
||||
end
|
||||
|
||||
@spec remove_from_muted_notifications(Changeset.t(), Info.t(), String.t()) :: Changeset.t()
|
||||
def remove_from_muted_notifications(changeset, info, muted) do
|
||||
set_notification_mutes(changeset, List.delete(info.muted_notifications, muted), true)
|
||||
end
|
||||
|
||||
def add_to_block(info, blocked) do
|
||||
set_blocks(info, Enum.uniq([blocked | info.blocks]))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
|||
options = cast_params(params)
|
||||
|
||||
user
|
||||
|> Notification.for_user_query()
|
||||
|> Notification.for_user_query(options)
|
||||
|> restrict(:exclude_types, options)
|
||||
|> Pagination.fetch_paginated(params)
|
||||
end
|
||||
|
|
@ -67,7 +67,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
|||
defp cast_params(params) do
|
||||
param_types = %{
|
||||
exclude_types: {:array, :string},
|
||||
reblogs: :boolean
|
||||
reblogs: :boolean,
|
||||
with_muted: :boolean
|
||||
}
|
||||
|
||||
changeset = cast({%{}, param_types}, params, Map.keys(param_types))
|
||||
|
|
|
|||
|
|
@ -1068,9 +1068,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
end
|
||||
|
||||
def mute(%{assigns: %{user: muter}} = conn, %{"id" => id}) do
|
||||
def mute(%{assigns: %{user: muter}} = conn, %{"id" => id} = params) do
|
||||
notifications =
|
||||
if Map.has_key?(params, "notifications"),
|
||||
do: params["notifications"] in [true, "True", "true", "1"],
|
||||
else: true
|
||||
|
||||
with %User{} = muted <- User.get_cached_by_id(id),
|
||||
{:ok, muter} <- User.mute(muter, muted) do
|
||||
{:ok, muter} <- User.mute(muter, muted, notifications) do
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("relationship.json", %{user: muter, target: muted})
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
followed_by: User.following?(target, user),
|
||||
blocking: User.blocks?(user, target),
|
||||
muting: User.mutes?(user, target),
|
||||
muting_notifications: false,
|
||||
muting_notifications: User.muted_notifications?(user, target),
|
||||
subscribing: User.subscribed_to?(user, target),
|
||||
requested: requested,
|
||||
domain_blocking: false,
|
||||
|
|
|
|||
|
|
@ -192,6 +192,13 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
|||
end
|
||||
|
||||
def notifications(%{assigns: %{user: user}} = conn, params) do
|
||||
params =
|
||||
if Map.has_key?(params, "with_muted") do
|
||||
Map.put(params, :with_muted, params["with_muted"] in [true, "True", "true", "1"])
|
||||
else
|
||||
params
|
||||
end
|
||||
|
||||
notifications = Notification.for_user(user, params)
|
||||
|
||||
conn
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue