Merge branch 'feature/1952-read-muted-notifications' into 'develop'

Automatically mark notifications about statuses from muted users and threads as read

Closes #1952

See merge request pleroma/pleroma!2893
This commit is contained in:
feld 2020-08-25 21:32:32 +00:00
commit fb33321fa2
5 changed files with 21 additions and 4 deletions

View file

@ -36,6 +36,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mastodon API: Add `pleroma.unread_count` to the Marker entity. - Mastodon API: Add `pleroma.unread_count` to the Marker entity.
- Mastodon API: Added `pleroma.metadata.post_formats` to /api/v1/instance - Mastodon API: Added `pleroma.metadata.post_formats` to /api/v1/instance
- Mastodon API (legacy): Allow query parameters for `/api/v1/domain_blocks`, e.g. `/api/v1/domain_blocks?domain=badposters.zone` - Mastodon API (legacy): Allow query parameters for `/api/v1/domain_blocks`, e.g. `/api/v1/domain_blocks?domain=badposters.zone`
- Mastodon API: Make notifications about statuses from muted users and threads read automatically
- Pleroma API: `/api/pleroma/captcha` responses now include `seconds_valid` with an integer value. - Pleroma API: `/api/pleroma/captcha` responses now include `seconds_valid` with an integer value.
</details> </details>

View file

@ -15,6 +15,7 @@ defmodule Pleroma.Notification do
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.ThreadMute alias Pleroma.ThreadMute
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.Push alias Pleroma.Web.Push
alias Pleroma.Web.Streamer alias Pleroma.Web.Streamer
@ -441,6 +442,7 @@ def create_notification(%Activity{} = activity, %User{} = user, do_send \\ true)
|> Multi.insert(:notification, %Notification{ |> Multi.insert(:notification, %Notification{
user_id: user.id, user_id: user.id,
activity: activity, activity: activity,
seen: mark_as_read?(activity, user),
type: type_from_activity(activity) type: type_from_activity(activity)
}) })
|> Marker.multi_set_last_read_id(user, "notifications") |> Marker.multi_set_last_read_id(user, "notifications")
@ -634,6 +636,11 @@ def skip?(:filtered, activity, user) do
def skip?(_, _, _), do: false def skip?(_, _, _), do: false
def mark_as_read?(activity, target_user) do
user = Activity.user_actor(activity)
User.mutes_user?(target_user, user) || CommonAPI.thread_muted?(target_user, activity)
end
def for_user_and_activity(user, activity) do def for_user_and_activity(user, activity) do
from(n in __MODULE__, from(n in __MODULE__,
where: n.user_id == ^user.id, where: n.user_id == ^user.id,

View file

@ -465,7 +465,7 @@ def remove_mute(user, activity) do
end end
def thread_muted?(%User{id: user_id}, %{data: %{"context" => context}}) def thread_muted?(%User{id: user_id}, %{data: %{"context" => context}})
when is_binary("context") do when is_binary(context) do
ThreadMute.exists?(user_id, context) ThreadMute.exists?(user_id, context)
end end

View file

@ -217,7 +217,10 @@ test "it creates a notification for the user if the user mutes the activity auth
muter = Repo.get(User, muter.id) muter = Repo.get(User, muter.id)
{:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"}) {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
assert Notification.create_notification(activity, muter) notification = Notification.create_notification(activity, muter)
assert notification.id
assert notification.seen
end end
test "notification created if user is muted without notifications" do test "notification created if user is muted without notifications" do
@ -243,7 +246,10 @@ test "it creates a notification for an activity from a muted thread" do
in_reply_to_status_id: activity.id in_reply_to_status_id: activity.id
}) })
assert Notification.create_notification(activity, muter) notification = Notification.create_notification(activity, muter)
assert notification.id
assert notification.seen
end end
test "it disables notifications from strangers" do test "it disables notifications from strangers" do
@ -317,6 +323,7 @@ test "it creates notifications if content matches with a not irreversible filter
{:ok, [notification]} = Notification.create_notifications(status) {:ok, [notification]} = Notification.create_notifications(status)
assert notification assert notification
refute notification.seen
end end
test "it creates notifications when someone likes user's status with a filtered word" do test "it creates notifications when someone likes user's status with a filtered word" do
@ -330,6 +337,7 @@ test "it creates notifications when someone likes user's status with a filtered
{:ok, [notification]} = Notification.create_notifications(activity_two) {:ok, [notification]} = Notification.create_notifications(activity_two)
assert notification assert notification
refute notification.seen
end end
end end
@ -1012,6 +1020,7 @@ test "it returns notifications for muted user without notifications", %{user: us
[notification] = Notification.for_user(user) [notification] = Notification.for_user(user)
assert notification.activity.object assert notification.activity.object
assert notification.seen
end end
test "it doesn't return notifications for muted user with notifications", %{user: user} do test "it doesn't return notifications for muted user with notifications", %{user: user} do

View file

@ -219,7 +219,7 @@ test "muted notification" do
expected = %{ expected = %{
id: to_string(notification.id), id: to_string(notification.id),
pleroma: %{is_seen: false, is_muted: true}, pleroma: %{is_seen: true, is_muted: true},
type: "favourite", type: "favourite",
account: AccountView.render("show.json", %{user: another_user, for: user}), account: AccountView.render("show.json", %{user: another_user, for: user}),
status: StatusView.render("show.json", %{activity: create_activity, for: user}), status: StatusView.render("show.json", %{activity: create_activity, for: user}),