Compare commits
9 Commits
feature/sa
...
feature/18
Author | SHA1 | Date | |
---|---|---|---|
|
965f88cfc7 | ||
|
f1781c14eb | ||
|
af6725121f | ||
|
5361e40162 | ||
|
f6ae86a081 | ||
|
9f33c5fe63 | ||
|
46492a2aee | ||
|
a74d0f8b27 | ||
|
16bcffd64a |
@ -334,6 +334,10 @@ The message payload consist of:
|
||||
|
||||
Both user muting and thread muting can be done for only a certain time by adding an `expires_in` parameter to the API calls and giving the expiration time in seconds.
|
||||
|
||||
## Subscriptions
|
||||
|
||||
Subscription `alerts` field contains new boolean setting for emoji reactions - `pleroma:emoji_reaction`. Can be passed with other `alerts` settings in POST/PUT `/api/v1/push/subscription` endpoints.
|
||||
|
||||
## Not implemented
|
||||
|
||||
Pleroma is generally compatible with the Mastodon 2.7.2 API, but some newer features and non-essential features are omitted. These features usually return an HTTP 200 status code, but with an empty response. While they may be added in the future, they are considered low priority.
|
||||
|
@ -301,12 +301,20 @@ See [Admin-API](admin_api.md)
|
||||
Can only accept images - any attempt to upload non-image files will be met with `HTTP 415 Unsupported Media Type`.
|
||||
|
||||
## `/api/v1/pleroma/notification_settings`
|
||||
|
||||
### Updates user notification settings
|
||||
|
||||
* Method `PUT`
|
||||
* Authentication: required
|
||||
* Params:
|
||||
* `block_from_strangers`: BOOLEAN field, blocks notifications from accounts you do not follow
|
||||
* `hide_notification_contents`: BOOLEAN field. When set to true, it removes the contents of a message from the push notification.
|
||||
* `followers`: BOOLEAN field, receives notifications from followers
|
||||
* `follows`: BOOLEAN field, receives notifications from people the user follows
|
||||
* `remote`: BOOLEAN field, receives notifications from people on remote instances
|
||||
* `local`: BOOLEAN field, receives notifications from people on the local instance
|
||||
* `privacy_option`: BOOLEAN field. When set to true, it removes the contents of a message from the push notification.
|
||||
* `exclude_types`: ARRAY field. What notification types to exclude.
|
||||
* Response: JSON. Returns `{"status": "success"}` if the update was successful, otherwise returns `{"error": "error_msg"}`
|
||||
|
||||
## `/api/v1/pleroma/healthcheck`
|
||||
|
@ -5,6 +5,9 @@
|
||||
defmodule Pleroma.Notification do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Ecto.Multi
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.FollowingRelationship
|
||||
@ -20,15 +23,26 @@ defmodule Pleroma.Notification do
|
||||
alias Pleroma.Web.Push
|
||||
alias Pleroma.Web.Streamer
|
||||
|
||||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
||||
require Logger
|
||||
|
||||
@type t :: %__MODULE__{}
|
||||
|
||||
@include_muted_option :with_muted
|
||||
|
||||
@types ~w{
|
||||
favourite
|
||||
follow
|
||||
follow_request
|
||||
mention
|
||||
move
|
||||
pleroma:chat_mention
|
||||
pleroma:emoji_reaction
|
||||
pleroma:report
|
||||
reblog
|
||||
}
|
||||
|
||||
@types_excluding_chat_and_report @types -- ~w(pleroma:chat_mention pleroma:report)
|
||||
|
||||
@type t :: %__MODULE__{}
|
||||
|
||||
schema "notifications" do
|
||||
field(:seen, :boolean, default: false)
|
||||
# This is an enum type in the database. If you add a new notification type,
|
||||
@ -62,22 +76,16 @@ defmodule Pleroma.Notification do
|
||||
|> Repo.aggregate(:count, :id)
|
||||
end
|
||||
|
||||
@notification_types ~w{
|
||||
favourite
|
||||
follow
|
||||
follow_request
|
||||
mention
|
||||
move
|
||||
pleroma:chat_mention
|
||||
pleroma:emoji_reaction
|
||||
pleroma:report
|
||||
reblog
|
||||
}
|
||||
@spec types() :: [String.t()]
|
||||
def types, do: @types
|
||||
|
||||
@spec types_excluding_chat_and_report() :: [String.t()]
|
||||
def types_excluding_chat_and_report, do: @types_excluding_chat_and_report
|
||||
|
||||
def changeset(%Notification{} = notification, attrs) do
|
||||
notification
|
||||
|> cast(attrs, [:seen, :type])
|
||||
|> validate_inclusion(:type, @notification_types)
|
||||
|> validate_inclusion(:type, @types)
|
||||
end
|
||||
|
||||
@spec last_read_query(User.t()) :: Ecto.Queryable.t()
|
||||
|
@ -12,13 +12,25 @@ defmodule Pleroma.User.NotificationSetting do
|
||||
embedded_schema do
|
||||
field(:block_from_strangers, :boolean, default: false)
|
||||
field(:hide_notification_contents, :boolean, default: false)
|
||||
field(:followers, :boolean, default: true)
|
||||
field(:follows, :boolean, default: true)
|
||||
field(:non_follows, :boolean, default: true)
|
||||
field(:non_followers, :boolean, default: true)
|
||||
field(:privacy_option, :boolean, default: false)
|
||||
field(:exclude_types, {:array, :string}, default: [])
|
||||
end
|
||||
|
||||
def changeset(schema, params) do
|
||||
schema
|
||||
|> cast(prepare_attrs(params), [
|
||||
:block_from_strangers,
|
||||
:hide_notification_contents
|
||||
:hide_notification_contents,
|
||||
:followers,
|
||||
:follows,
|
||||
:non_follows,
|
||||
:non_followers,
|
||||
:privacy_option,
|
||||
:exclude_types
|
||||
])
|
||||
end
|
||||
|
||||
|
@ -42,19 +42,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
||||
end
|
||||
end
|
||||
|
||||
@default_notification_types ~w{
|
||||
mention
|
||||
follow
|
||||
follow_request
|
||||
reblog
|
||||
favourite
|
||||
move
|
||||
pleroma:emoji_reaction
|
||||
}
|
||||
def index(%{assigns: %{user: user}} = conn, params) do
|
||||
params =
|
||||
Map.new(params, fn {k, v} -> {to_string(k), v} end)
|
||||
|> Map.put_new("include_types", @default_notification_types)
|
||||
params
|
||||
|> Map.new(fn {k, v} -> {to_string(k), v} end)
|
||||
|> Map.put_new("include_types", Pleroma.Notification.types_excluding_chat_and_report())
|
||||
|
||||
notifications = MastodonAPI.get_notifications(user, params)
|
||||
|
||||
|
@ -50,7 +50,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
||||
end
|
||||
|
||||
def get_notifications(user, params \\ %{}) do
|
||||
options = cast_params(params)
|
||||
options =
|
||||
params
|
||||
|> Map.put_new("exclude_types", user.notification_settings.exclude_types)
|
||||
|> cast_params()
|
||||
|
||||
user
|
||||
|> Notification.for_user_query(options)
|
||||
|
@ -19,7 +19,7 @@ defmodule Pleroma.Web.Push.Impl do
|
||||
@types ["Create", "Follow", "Announce", "Like", "Move", "EmojiReact"]
|
||||
|
||||
@doc "Performs sending notifications for user subscriptions"
|
||||
@spec perform(Notification.t()) :: list(any) | :error | {:error, :unknown_type}
|
||||
@spec perform(Notification.t()) :: {:ok, list(any)} | {:error, :unknown_type}
|
||||
def perform(
|
||||
%{
|
||||
activity: %{data: %{"type" => activity_type}} = activity,
|
||||
@ -164,13 +164,14 @@ defmodule Pleroma.Web.Push.Impl do
|
||||
_object,
|
||||
mastodon_type
|
||||
)
|
||||
when type in ["Follow", "Like"] do
|
||||
when type in ["Follow", "Like", "EmojiReact"] do
|
||||
mastodon_type = mastodon_type || notification.type
|
||||
|
||||
case mastodon_type do
|
||||
"follow" -> "@#{actor.nickname} has followed you"
|
||||
"follow_request" -> "@#{actor.nickname} has requested to follow you"
|
||||
"favourite" -> "@#{actor.nickname} has favorited your post"
|
||||
"pleroma:emoji_reaction" -> "@#{actor.nickname} has reacted to your post"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -14,6 +14,8 @@ defmodule Pleroma.Web.Push.Subscription do
|
||||
|
||||
@type t :: %__MODULE__{}
|
||||
|
||||
@supported_alert_types Enum.map(Pleroma.Notification.types(), &String.to_atom/1)
|
||||
|
||||
schema "push_subscriptions" do
|
||||
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
||||
belongs_to(:token, Token)
|
||||
|
@ -171,7 +171,14 @@ defmodule Pleroma.Web.Streamer do
|
||||
end
|
||||
end
|
||||
|
||||
def filtered_by_user?(%User{} = user, %Notification{activity: activity}, _) do
|
||||
def filtered_by_user?(
|
||||
%User{} = user,
|
||||
%Notification{activity: activity, type: notification_type},
|
||||
_
|
||||
) do
|
||||
notification_settings = user.notification_settings
|
||||
|
||||
notification_type not in notification_settings.exclude_types and
|
||||
filtered_by_user?(user, activity, :notification)
|
||||
end
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
defmodule Pleroma.Repo.Migrations.AddExcludeTypesIntoUserNotificationSettings do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
execute("""
|
||||
UPDATE users SET notification_settings = jsonb_set(notification_settings, '{exclude_types}', '[]') WHERE local = true;
|
||||
""")
|
||||
end
|
||||
|
||||
def down, do: :ok
|
||||
end
|
@ -408,6 +408,83 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
||||
assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
end
|
||||
|
||||
defp update_notification_settings_and_conn(user, conn, exclude_types) do
|
||||
{:ok, user} =
|
||||
User.update_notification_settings(user, %{
|
||||
"exclude_types" => exclude_types
|
||||
})
|
||||
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/notifications")
|
||||
end
|
||||
|
||||
test "filters notifications with user settings for exclude_types" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
|
||||
{:ok, reblog_activity} = CommonAPI.repeat(create_activity.id, other_user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
mention_notification_id = get_notification_id_by_activity(mention_activity)
|
||||
favorite_notification_id = get_notification_id_by_activity(favorite_activity)
|
||||
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
|
||||
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
||||
|
||||
conn_res =
|
||||
update_notification_settings_and_conn(user, conn, ["mention", "favourite", "reblog"])
|
||||
|
||||
assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
conn_res =
|
||||
update_notification_settings_and_conn(user, conn, ["favourite", "reblog", "follow"])
|
||||
|
||||
assert [%{"id" => ^mention_notification_id}] =
|
||||
json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
conn_res = update_notification_settings_and_conn(user, conn, ["reblog", "follow", "mention"])
|
||||
|
||||
assert [%{"id" => ^favorite_notification_id}] =
|
||||
json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
conn_res =
|
||||
update_notification_settings_and_conn(user, conn, ["follow", "mention", "favourite"])
|
||||
|
||||
assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
end
|
||||
|
||||
test "exclude_types params have high priority than user settings" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, _favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
|
||||
{:ok, _reblog_activity} = CommonAPI.repeat(create_activity.id, other_user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
||||
|
||||
{:ok, user} =
|
||||
User.update_notification_settings(user, %{
|
||||
"exclude_types" => ["favourite", "reblog", "follow", "mention"]
|
||||
})
|
||||
|
||||
query = params_to_query(%{exclude_types: ["mention", "favourite", "reblog"]})
|
||||
|
||||
conn_res =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/notifications?" <> query)
|
||||
|
||||
assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
end
|
||||
|
||||
test "filters notifications using include_types" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
@ -124,7 +124,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
||||
|
||||
notification_settings = %{
|
||||
block_from_strangers: false,
|
||||
hide_notification_contents: false
|
||||
hide_notification_contents: false,
|
||||
followers: true,
|
||||
follows: true,
|
||||
non_followers: true,
|
||||
non_follows: true,
|
||||
privacy_option: false,
|
||||
exclude_types: []
|
||||
}
|
||||
|
||||
privacy = user.default_scope
|
||||
|
@ -69,6 +69,27 @@ defmodule Pleroma.Web.Push.ImplTest do
|
||||
assert Impl.perform(notif) == {:ok, [:ok, :ok]}
|
||||
end
|
||||
|
||||
test "notification for follow_request" do
|
||||
user = insert(:user)
|
||||
reaction_user = insert(:user)
|
||||
|
||||
insert(:push_subscription, user: user, data: %{alerts: %{"pleroma:emoji_reaction" => true}})
|
||||
insert(:push_subscription, user: user, data: %{alerts: %{"pleroma:emoji_reaction" => false}})
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "<Lorem ipsum dolor sit amet."})
|
||||
|
||||
{:ok, reaction_activity} = CommonAPI.react_with_emoji(activity.id, reaction_user, "☕")
|
||||
|
||||
notif =
|
||||
insert(:notification,
|
||||
user: user,
|
||||
activity: reaction_activity,
|
||||
type: "pleroma:emoji_reaction"
|
||||
)
|
||||
|
||||
assert Impl.perform(notif) == {:ok, [:ok]}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns error if notif does not match " do
|
||||
assert Impl.perform(%{}) == {:error, :unknown_type}
|
||||
|
@ -27,7 +27,9 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
||||
conn
|
||||
|> put("/api/pleroma/notification_settings", %{
|
||||
"block_from_strangers" => true,
|
||||
"bar" => 1
|
||||
"bar" => 1,
|
||||
"followers" => false,
|
||||
"exclude_types" => ["follow"]
|
||||
})
|
||||
|> json_response(:ok)
|
||||
|
||||
@ -35,7 +37,13 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
||||
|
||||
assert %Pleroma.User.NotificationSetting{
|
||||
block_from_strangers: true,
|
||||
hide_notification_contents: false
|
||||
hide_notification_contents: false,
|
||||
followers: false,
|
||||
follows: true,
|
||||
non_follows: true,
|
||||
non_followers: true,
|
||||
privacy_option: false,
|
||||
exclude_types: ["follow"]
|
||||
} == user.notification_settings
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user