forked from AkkomaGang/akkoma
Notification controls
Allow users to configure whether they want to receive notifications from people they follow / who follow them, people from remote / local instances
This commit is contained in:
parent
926bf114b7
commit
55d086b520
3 changed files with 131 additions and 7 deletions
|
@ -122,13 +122,7 @@ def create_notifications(_), do: {:ok, []}
|
||||||
|
|
||||||
# TODO move to sql, too.
|
# TODO move to sql, too.
|
||||||
def create_notification(%Activity{} = activity, %User{} = user) do
|
def create_notification(%Activity{} = activity, %User{} = user) do
|
||||||
unless User.blocks?(user, %{ap_id: activity.data["actor"]}) or
|
unless skip?(activity, user) do
|
||||||
CommonAPI.thread_muted?(user, activity) or user.ap_id == activity.data["actor"] or
|
|
||||||
(activity.data["type"] == "Follow" and
|
|
||||||
Enum.any?(Notification.for_user(user), fn notif ->
|
|
||||||
notif.activity.data["type"] == "Follow" and
|
|
||||||
notif.activity.data["actor"] == activity.data["actor"]
|
|
||||||
end)) do
|
|
||||||
notification = %Notification{user_id: user.id, activity: activity}
|
notification = %Notification{user_id: user.id, activity: activity}
|
||||||
{:ok, notification} = Repo.insert(notification)
|
{:ok, notification} = Repo.insert(notification)
|
||||||
Pleroma.Web.Streamer.stream("user", notification)
|
Pleroma.Web.Streamer.stream("user", notification)
|
||||||
|
@ -154,4 +148,61 @@ def get_notified_from_activity(
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_notified_from_activity(_, _local_only), do: []
|
def get_notified_from_activity(_, _local_only), do: []
|
||||||
|
|
||||||
|
def skip?(activity, user) do
|
||||||
|
[:self, :blocked, :local, :muted, :followers, :follows, :recently_followed]
|
||||||
|
|> Enum.any?(&skip?(&1, activity, user))
|
||||||
|
end
|
||||||
|
|
||||||
|
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?(:local, %{local: true}, user) do
|
||||||
|
user.info.notification_settings["local"] == false
|
||||||
|
end
|
||||||
|
|
||||||
|
def skip?(:local, %{local: false}, user) do
|
||||||
|
user.info.notification_settings["remote"] == false
|
||||||
|
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,
|
||||||
|
%{info: %{notification_settings: %{"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
|
||||||
|
actor = activity.data["actor"]
|
||||||
|
followed = User.get_by_ap_id(actor)
|
||||||
|
User.following?(user, followed)
|
||||||
|
end
|
||||||
|
|
||||||
|
def skip?(:recently_followed, activity, user) do
|
||||||
|
actor = activity.data["actor"]
|
||||||
|
|
||||||
|
Notification.for_user(user)
|
||||||
|
|> Enum.any?(fn
|
||||||
|
%{activity: %{data: %{"type" => "Follow", "actor" => ^actor}}} -> true
|
||||||
|
_ -> false
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def skip?(_, _, _), do: false
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,6 +40,10 @@ defmodule Pleroma.User.Info do
|
||||||
field(:pinned_activities, {:array, :string}, default: [])
|
field(:pinned_activities, {:array, :string}, default: [])
|
||||||
field(:flavour, :string, default: nil)
|
field(:flavour, :string, default: nil)
|
||||||
|
|
||||||
|
field(:notification_settings, :map,
|
||||||
|
default: %{"remote" => true, "local" => true, "followers" => true, "follows" => true}
|
||||||
|
)
|
||||||
|
|
||||||
# Found in the wild
|
# Found in the wild
|
||||||
# ap_id -> Where is this used?
|
# ap_id -> Where is this used?
|
||||||
# bio -> Where is this used?
|
# bio -> Where is this used?
|
||||||
|
|
|
@ -41,6 +41,75 @@ test "it doesn't create a notification for user if the user blocks the activity
|
||||||
assert nil == Notification.create_notification(activity, user)
|
assert nil == Notification.create_notification(activity, user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it doesn't create a notificatin for the user if the user mutes the activity author" do
|
||||||
|
muter = insert(:user)
|
||||||
|
muted = insert(:user)
|
||||||
|
{:ok, _} = User.mute(muter, muted)
|
||||||
|
muter = Repo.get(User, muter.id)
|
||||||
|
{:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
|
||||||
|
|
||||||
|
assert nil == Notification.create_notification(activity, muter)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it doesn't create a notification for an activity from a muted thread" do
|
||||||
|
muter = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(muter, %{"status" => "hey"})
|
||||||
|
CommonAPI.add_mute(muter, activity)
|
||||||
|
|
||||||
|
{:ok, activity} =
|
||||||
|
CommonAPI.post(other_user, %{
|
||||||
|
"status" => "Hi @#{muter.nickname}",
|
||||||
|
"in_reply_to_status_id" => activity.id
|
||||||
|
})
|
||||||
|
|
||||||
|
assert nil == Notification.create_notification(activity, muter)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it disables notifications from people on remote instances" do
|
||||||
|
user = insert(:user, info: %{notification_settings: %{"remote" => false}})
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
create_activity = %{
|
||||||
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
|
"type" => "Create",
|
||||||
|
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||||
|
"actor" => other_user.ap_id,
|
||||||
|
"object" => %{
|
||||||
|
"type" => "Note",
|
||||||
|
"content" => "Hi @#{user.nickname}",
|
||||||
|
"attributedTo" => other_user.ap_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{:ok, %{local: false} = activity} = Transmogrifier.handle_incoming(create_activity)
|
||||||
|
assert nil == Notification.create_notification(activity, user)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it disables notifications from people on the local instance" do
|
||||||
|
user = insert(:user, info: %{notification_settings: %{"local" => false}})
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
|
||||||
|
assert nil == Notification.create_notification(activity, user)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it disables notifications from followers" do
|
||||||
|
follower = insert(:user)
|
||||||
|
followed = insert(:user, info: %{notification_settings: %{"followers" => false}})
|
||||||
|
User.follow(follower, followed)
|
||||||
|
{:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
|
||||||
|
assert nil == Notification.create_notification(activity, followed)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it disables notifications from people the user follows" do
|
||||||
|
follower = insert(:user, info: %{notification_settings: %{"follows" => false}})
|
||||||
|
followed = insert(:user)
|
||||||
|
User.follow(follower, followed)
|
||||||
|
follower = Repo.get(User, follower.id)
|
||||||
|
{:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
|
||||||
|
assert nil == Notification.create_notification(activity, follower)
|
||||||
|
end
|
||||||
|
|
||||||
test "it doesn't create a notification for user if he is the activity author" do
|
test "it doesn't create a notification for user if he is the activity author" do
|
||||||
activity = insert(:note_activity)
|
activity = insert(:note_activity)
|
||||||
author = User.get_by_ap_id(activity.data["actor"])
|
author = User.get_by_ap_id(activity.data["actor"])
|
||||||
|
|
Loading…
Reference in a new issue