include_types parameter in /api/v1/notifications
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Wed, 18 Mar 2020 14:37:54 +0000 (17:37 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Fri, 20 Mar 2020 10:18:12 +0000 (13:18 +0300)
CHANGELOG.md
docs/API/differences_in_mastoapi_responses.md
lib/pleroma/web/mastodon_api/mastodon_api.ex
lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
test/web/mastodon_api/controllers/notification_controller_test.exs

index e3be2ea0847a4a7834695b743c5464bd48f8627f..a27200895c0813513776a6f35536758272c5e1a9 100644 (file)
@@ -10,6 +10,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 ### Removed
 - **Breaking:** removed `with_move` parameter from notifications timeline.
 
+### Added
+- NodeInfo: `pleroma:api/v1/notifications:include_types_filter` to the `features` list.
+<details>
+  <summary>API Changes</summary>
+- Mastodon API: Support for `include_types` in `/api/v1/notifications`.
+</details>
+
 ## [2.0.0] - 2019-03-08
 ### Security
 - Mastodon API: Fix being able to request enourmous amount of statuses in timelines leading to DoS. Now limited to 40 per request.
index b12d3092cc1947c77754bc8aaaa1d8f389398169..dc8f54d2a3498ea59e935b053739c232946b0a1f 100644 (file)
@@ -117,6 +117,7 @@ The `type` value is `pleroma:emoji_reaction`. Has these fields:
 Accepts additional parameters:
 
 - `exclude_visibilities`: will exclude the notifications for activities with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`). Usage example: `GET /api/v1/notifications?exclude_visibilities[]=direct&exclude_visibilities[]=private`.
+- `include_types`: will include the notifications for activities with the given types. The parameter accepts an array of types (`mention`, `follow`, `reblog`, `favourite`, `move`, `pleroma:emoji_reaction`). Usage example: `GET /api/v1/notifications?include_types[]=mention&include_types[]=reblog`.
 
 ## POST `/api/v1/statuses`
 
index a2dc9bc71cc5efaa5014765bf5a3a6146e848b07..70da64a7a8f0fe8d7e7e36181f263a942109e1e9 100644 (file)
@@ -55,6 +55,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
 
     user
     |> Notification.for_user_query(options)
+    |> restrict(:include_types, options)
     |> restrict(:exclude_types, options)
     |> restrict(:account_ap_id, options)
     |> Pagination.fetch_paginated(params)
@@ -69,6 +70,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
   defp cast_params(params) do
     param_types = %{
       exclude_types: {:array, :string},
+      include_types: {:array, :string},
       exclude_visibilities: {:array, :string},
       reblogs: :boolean,
       with_muted: :boolean,
@@ -79,14 +81,16 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
     changeset.changes
   end
 
+  defp restrict(query, :include_types, %{include_types: mastodon_types = [_ | _]}) do
+    ap_types = convert_and_filter_mastodon_types(mastodon_types)
+
+    where(query, [q, a], fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data))
+  end
+
   defp restrict(query, :exclude_types, %{exclude_types: mastodon_types = [_ | _]}) do
-    ap_types =
-      mastodon_types
-      |> Enum.map(&Activity.from_mastodon_notification_type/1)
-      |> Enum.filter(& &1)
+    ap_types = convert_and_filter_mastodon_types(mastodon_types)
 
-    query
-    |> where([q, a], not fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data))
+    where(query, [q, a], not fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data))
   end
 
   defp restrict(query, :account_ap_id, %{account_ap_id: account_ap_id}) do
@@ -94,4 +98,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
   end
 
   defp restrict(query, _, _), do: query
+
+  defp convert_and_filter_mastodon_types(types) do
+    types
+    |> Enum.map(&Activity.from_mastodon_notification_type/1)
+    |> Enum.filter(& &1)
+  end
 end
index 18eb413338e223c6aa64b5204b6bccd87effc5e9..30838b1eb76d467845144f1437c49a42eb38a6ea 100644 (file)
@@ -60,6 +60,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
         "pleroma_explicit_addressing",
         "shareable_emoji_packs",
         "multifetch",
+        "pleroma:api/v1/notifications:include_types_filter",
         if Config.get([:media_proxy, :enabled]) do
           "media_proxy"
         end,
index dbe9a7fd7bf302beaeebc82bc87fc6459534318e..7a001164633d0f2934e479fda610a287d0a774e3 100644 (file)
@@ -304,6 +304,51 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
   end
 
+  test "filters notifications using include_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(create_activity.id, other_user)
+    {: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 = get(conn, "/api/v1/notifications", %{include_types: ["follow"]})
+
+    assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
+
+    conn_res = get(conn, "/api/v1/notifications", %{include_types: ["mention"]})
+
+    assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
+
+    conn_res = get(conn, "/api/v1/notifications", %{include_types: ["favourite"]})
+
+    assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
+
+    conn_res = get(conn, "/api/v1/notifications", %{include_types: ["reblog"]})
+
+    assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
+
+    result = conn |> get("/api/v1/notifications") |> json_response(200)
+
+    assert length(result) == 4
+
+    result =
+      conn
+      |> get("/api/v1/notifications", %{
+        include_types: ["follow", "mention", "favourite", "reblog"]
+      })
+      |> json_response(200)
+
+    assert length(result) == 4
+  end
+
   test "destroy multiple" do
     %{user: user, conn: conn} = oauth_access(["read:notifications", "write:notifications"])
     other_user = insert(:user)