summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Strizhakov <alex.strizhakov@gmail.com>2020-06-16 08:41:57 +0300
committerAlexander Strizhakov <alex.strizhakov@gmail.com>2021-03-10 16:46:52 +0300
commit16bcffd64adad9e205fa1f85b1366efca31e020d (patch)
treee5aa3840c71d632b5df15b828c5ecfcfad0fe997
parent7f413139fb2d4dc008ef351560bada800b4b26a0 (diff)
unify notification settings
-rw-r--r--docs/development/API/differences_in_mastoapi_responses.md6
-rw-r--r--docs/development/API/pleroma_api.md12
-rw-r--r--lib/pleroma/notification.ex2
-rw-r--r--lib/pleroma/user/notification_setting.ex14
-rw-r--r--lib/pleroma/web/masto_fe_controller.ex19
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api.ex9
-rw-r--r--lib/pleroma/web/push/impl.ex5
-rw-r--r--lib/pleroma/web/push/subscription.ex3
-rw-r--r--lib/pleroma/web/streamer.ex11
-rw-r--r--priv/repo/migrations/20200602101826_add_exclude_types_into_user_notification_settings.exs11
-rw-r--r--test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs77
-rw-r--r--test/pleroma/web/mastodon_api/masto_fe_controller_test.exs97
-rw-r--r--test/pleroma/web/mastodon_api/views/account_view_test.exs6
-rw-r--r--test/pleroma/web/push/impl_test.exs21
-rw-r--r--test/pleroma/web/twitter_api/util_controller_test.exs9
15 files changed, 283 insertions, 19 deletions
diff --git a/docs/development/API/differences_in_mastoapi_responses.md b/docs/development/API/differences_in_mastoapi_responses.md
index a14fcb416..75382bb3c 100644
--- a/docs/development/API/differences_in_mastoapi_responses.md
+++ b/docs/development/API/differences_in_mastoapi_responses.md
@@ -334,6 +334,12 @@ 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
+
+Has additional field in parameters:
+
+- `pleroma:emoji_reaction`: Receive emoji reaction notifications?
+
## 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.
diff --git a/docs/development/API/pleroma_api.md b/docs/development/API/pleroma_api.md
index d896f0ce7..9f93494ec 100644
--- a/docs/development/API/pleroma_api.md
+++ b/docs/development/API/pleroma_api.md
@@ -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.
+ * `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`
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index 7efbdc49a..246993f4d 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -74,6 +74,8 @@ defmodule Pleroma.Notification do
reblog
}
+ def types, do: @notification_types
+
def changeset(%Notification{} = notification, attrs) do
notification
|> cast(attrs, [:seen, :type])
diff --git a/lib/pleroma/user/notification_setting.ex b/lib/pleroma/user/notification_setting.ex
index a7cd61499..820ed903c 100644
--- a/lib/pleroma/user/notification_setting.ex
+++ b/lib/pleroma/user/notification_setting.ex
@@ -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
diff --git a/lib/pleroma/web/masto_fe_controller.ex b/lib/pleroma/web/masto_fe_controller.ex
index e788ab37a..6ec6fa951 100644
--- a/lib/pleroma/web/masto_fe_controller.ex
+++ b/lib/pleroma/web/masto_fe_controller.ex
@@ -53,7 +53,24 @@ defmodule Pleroma.Web.MastoFEController do
@doc "PUT /api/web/settings: Backend-obscure settings blob for MastoFE, don't parse/reuse elsewhere"
def put_settings(%{assigns: %{user: user}} = conn, %{"data" => settings} = _params) do
- with {:ok, _} <- User.mastodon_settings_update(user, settings) do
+ with {:ok, user} <- User.mastodon_settings_update(user, settings) do
+ if settings = get_in(user.settings, ["notifications", "shows"]) do
+ notify_settings =
+ Enum.map(settings, fn {k, v} ->
+ if v == false do
+ k
+ end
+ end)
+ |> Enum.filter(& &1)
+
+ notification_settings =
+ user.notification_settings
+ |> Map.from_struct()
+ |> Map.put(:exclude_types, notify_settings)
+
+ User.update_notification_settings(user, notification_settings)
+ end
+
json(conn, %{})
else
e ->
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex
index 71479550e..17cfc5443 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex
@@ -52,6 +52,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
def get_notifications(user, params \\ %{}) do
options = cast_params(params)
+ user_exclude_types = user.notification_settings.exclude_types
+
+ options =
+ if (!options[:exclude_types] or options[:exclude_types] == []) and user_exclude_types != [] do
+ Map.put(options, :exclude_types, user_exclude_types)
+ else
+ options
+ end
+
user
|> Notification.for_user_query(options)
|> restrict(:include_types, options)
diff --git a/lib/pleroma/web/push/impl.ex b/lib/pleroma/web/push/impl.ex
index 83cbdc870..ec68b40f8 100644
--- a/lib/pleroma/web/push/impl.ex
+++ b/lib/pleroma/web/push/impl.ex
@@ -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
diff --git a/lib/pleroma/web/push/subscription.ex b/lib/pleroma/web/push/subscription.ex
index 4f6c9bc9f..7ea32b258 100644
--- a/lib/pleroma/web/push/subscription.ex
+++ b/lib/pleroma/web/push/subscription.ex
@@ -29,7 +29,8 @@ defmodule Pleroma.Web.Push.Subscription do
@supported_alert_types ~w[follow favourite mention reblog pleroma:chat_mention pleroma:emoji_reaction]a
defp alerts(%{data: %{alerts: alerts}}) do
- alerts = Map.take(alerts, @supported_alert_types)
+ types = Enum.map(Pleroma.Notification.types(), &String.to_atom/1)
+ alerts = Map.take(alerts, types)
%{"alerts" => alerts}
end
diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex
index fc3bbb130..6c77e4a57 100644
--- a/lib/pleroma/web/streamer.ex
+++ b/lib/pleroma/web/streamer.ex
@@ -171,8 +171,15 @@ defmodule Pleroma.Web.Streamer do
end
end
- def filtered_by_user?(%User{} = user, %Notification{activity: activity}, _) do
- filtered_by_user?(user, activity, :notification)
+ 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
defp do_stream("direct", item) do
diff --git a/priv/repo/migrations/20200602101826_add_exclude_types_into_user_notification_settings.exs b/priv/repo/migrations/20200602101826_add_exclude_types_into_user_notification_settings.exs
new file mode 100644
index 000000000..a9204b9cf
--- /dev/null
+++ b/priv/repo/migrations/20200602101826_add_exclude_types_into_user_notification_settings.exs
@@ -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
diff --git a/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs
index 2615912a8..f51f77946 100644
--- a/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs
+++ b/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs
@@ -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)
diff --git a/test/pleroma/web/mastodon_api/masto_fe_controller_test.exs b/test/pleroma/web/mastodon_api/masto_fe_controller_test.exs
index ea66c708f..c13b9cb73 100644
--- a/test/pleroma/web/mastodon_api/masto_fe_controller_test.exs
+++ b/test/pleroma/web/mastodon_api/masto_fe_controller_test.exs
@@ -11,19 +11,96 @@ defmodule Pleroma.Web.MastodonAPI.MastoFEControllerTest do
setup do: clear_config([:instance, :public])
- test "put settings", %{conn: conn} do
- user = insert(:user)
+ describe "put_settings/2" do
+ setup do
+ %{conn: conn, user: user} = oauth_access(["write:accounts"])
+ [conn: conn, user: user]
+ end
- conn =
- conn
- |> assign(:user, user)
- |> assign(:token, insert(:oauth_token, user: user, scopes: ["write:accounts"]))
- |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
+ test "common", %{conn: conn, user: user} do
+ assert conn
+ |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
+ |> json_response(200)
- assert _result = json_response(conn, 200)
+ user = User.get_cached_by_ap_id(user.ap_id)
+ assert user.mastofe_settings == %{"programming" => "socks"}
+ end
- user = User.get_cached_by_ap_id(user.ap_id)
- assert user.mastofe_settings == %{"programming" => "socks"}
+ test "saves notification settings", %{conn: conn, user: user} do
+ assert conn
+ |> put("/api/web/settings", %{
+ "data" => %{
+ "notifications" => %{
+ "alerts" => %{
+ "favourite" => true,
+ "follow" => true,
+ "follow_request" => true,
+ "mention" => true,
+ "poll" => true,
+ "reblog" => true
+ },
+ "quickFilter" => %{"active" => "all", "advanced" => true, "show" => true},
+ "shows" => %{
+ "favourite" => false,
+ "follow" => false,
+ "follow_request" => false,
+ "mention" => false,
+ "poll" => false,
+ "reblog" => false
+ },
+ "sounds" => %{
+ "favourite" => true,
+ "follow" => true,
+ "follow_request" => true,
+ "mention" => true,
+ "poll" => true,
+ "reblog" => true
+ }
+ }
+ }
+ })
+
+ user = User.get_cached_by_ap_id(user.ap_id)
+
+ assert user.settings == %{
+ "notifications" => %{
+ "alerts" => %{
+ "favourite" => true,
+ "follow" => true,
+ "follow_request" => true,
+ "mention" => true,
+ "poll" => true,
+ "reblog" => true
+ },
+ "quickFilter" => %{"active" => "all", "advanced" => true, "show" => true},
+ "shows" => %{
+ "favourite" => false,
+ "follow" => false,
+ "follow_request" => false,
+ "mention" => false,
+ "poll" => false,
+ "reblog" => false
+ },
+ "sounds" => %{
+ "favourite" => true,
+ "follow" => true,
+ "follow_request" => true,
+ "mention" => true,
+ "poll" => true,
+ "reblog" => true
+ }
+ }
+ }
+
+ assert user.notification_settings.exclude_types == [
+ "favourite",
+ "follow",
+ "follow_request",
+ "mention",
+ "poll",
+ "reblog"
+ ]
+ end
end
describe "index/2 redirections" do
diff --git a/test/pleroma/web/mastodon_api/views/account_view_test.exs b/test/pleroma/web/mastodon_api/views/account_view_test.exs
index 5373a17c3..a9c66e63e 100644
--- a/test/pleroma/web/mastodon_api/views/account_view_test.exs
+++ b/test/pleroma/web/mastodon_api/views/account_view_test.exs
@@ -125,6 +125,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
notification_settings = %{
block_from_strangers: false,
hide_notification_contents: false
+ followers: true,
+ follows: true,
+ non_followers: true,
+ non_follows: true,
+ privacy_option: false,
+ exclude_types: []
}
privacy = user.default_scope
diff --git a/test/pleroma/web/push/impl_test.exs b/test/pleroma/web/push/impl_test.exs
index b3ca1a337..a7c2431ed 100644
--- a/test/pleroma/web/push/impl_test.exs
+++ b/test/pleroma/web/push/impl_test.exs
@@ -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}
diff --git a/test/pleroma/web/twitter_api/util_controller_test.exs b/test/pleroma/web/twitter_api/util_controller_test.exs
index bdbc478c3..f6a552369 100644
--- a/test/pleroma/web/twitter_api/util_controller_test.exs
+++ b/test/pleroma/web/twitter_api/util_controller_test.exs
@@ -28,6 +28,9 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|> put("/api/pleroma/notification_settings", %{
"block_from_strangers" => true,
"bar" => 1
+ "followers" => false,
+ "bar" => 1,
+ "exclude_types" => ["follow"]
})
|> json_response(:ok)
@@ -36,6 +39,12 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
assert %Pleroma.User.NotificationSetting{
block_from_strangers: true,
hide_notification_contents: false
+ followers: false,
+ follows: true,
+ non_follows: true,
+ non_followers: true,
+ privacy_option: false,
+ exclude_types: ["follow"]
} == user.notification_settings
end