Feature/1072 muting notifications
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Sun, 14 Jul 2019 13:29:31 +0000 (13:29 +0000)
committerkaniini <ariadne@dereferenced.org>
Sun, 14 Jul 2019 13:29:31 +0000 (13:29 +0000)
13 files changed:
CHANGELOG.md
lib/pleroma/notification.ex
lib/pleroma/user.ex
lib/pleroma/user/info.ex
lib/pleroma/web/mastodon_api/mastodon_api.ex
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/mastodon_api/views/account_view.ex
lib/pleroma/web/twitter_api/twitter_api_controller.ex
priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs [new file with mode: 0644]
test/notification_test.exs
test/user_test.exs
test/web/mastodon_api/mastodon_api_controller_test.exs
test/web/twitter_api/twitter_api_controller_test.exs

index 694097878d9d76b6ee27e7d10f42a5cf30896db7..0cec3bf5c50b1b823f0ca52259f3a22d8a3e5861 100644 (file)
@@ -27,13 +27,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Mastodon API: Support for the [`tagged` filter](https://github.com/tootsuite/mastodon/pull/9755) in [`GET /api/v1/accounts/:id/statuses`](https://docs.joinmastodon.org/api/rest/accounts/#get-api-v1-accounts-id-statuses)
 - Mastodon API, streaming: Add support for passing the token in the `Sec-WebSocket-Protocol` header
 - Mastodon API, extension: Ability to reset avatar, profile banner, and background
+- Mastodon API: Add support for categories for custom emojis by reusing the group feature. <https://github.com/tootsuite/mastodon/pull/11196>
+- Mastodon API: Add support for muting/unmuting notifications
 - Admin API: Return users' tags when querying reports
 - Admin API: Return avatar and display name when querying users
 - Admin API: Allow querying user by ID
 - Admin API: Added support for `tuples`.
 - Added synchronization of following/followers counters for external users
 - Configuration: `enabled` option for `Pleroma.Emails.Mailer`, defaulting to `false`.
-- Mastodon API: Add support for categories for custom emojis by reusing the group feature. <https://github.com/tootsuite/mastodon/pull/11196>
 - Configuration: Pleroma.Plugs.RateLimiter `bucket_name`, `params` options.
 
 ### Changed
index a414afbbfe9e4107b30ce10306cef0e00960e3cc..ee7b37aab35bc3cc193b3835bfc7597f59d3370a 100644 (file)
@@ -11,7 +11,6 @@ defmodule Pleroma.Notification do
   alias Pleroma.Pagination
   alias Pleroma.Repo
   alias Pleroma.User
-  alias Pleroma.Web.CommonAPI
   alias Pleroma.Web.CommonAPI.Utils
   alias Pleroma.Web.Push
   alias Pleroma.Web.Streamer
@@ -32,31 +31,47 @@ defmodule Pleroma.Notification do
     |> cast(attrs, [:seen])
   end
 
-  def for_user_query(user) do
-    Notification
-    |> where(user_id: ^user.id)
-    |> where(
-      [n, a],
-      fragment(
-        "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')",
-        a.actor
-      )
-    )
-    |> join(:inner, [n], activity in assoc(n, :activity))
-    |> join(:left, [n, a], object in Object,
-      on:
+  def for_user_query(user, opts) do
+    query =
+      Notification
+      |> where(user_id: ^user.id)
+      |> where(
+        [n, a],
         fragment(
-          "(?->>'id') = COALESCE((? -> 'object'::text) ->> 'id'::text)",
-          object.data,
-          a.data
+          "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')",
+          a.actor
         )
-    )
-    |> preload([n, a, o], activity: {a, object: o})
+      )
+      |> join(:inner, [n], activity in assoc(n, :activity))
+      |> join(:left, [n, a], object in Object,
+        on:
+          fragment(
+            "(?->>'id') = COALESCE((? -> 'object'::text) ->> 'id'::text)",
+            object.data,
+            a.data
+          )
+      )
+      |> preload([n, a, o], activity: {a, object: o})
+
+    if opts[:with_muted] do
+      query
+    else
+      where(query, [n, a], a.actor not in ^user.info.muted_notifications)
+      |> where([n, a], a.actor not in ^user.info.blocks)
+      |> where(
+        [n, a],
+        fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks
+      )
+      |> join(:left, [n, a], tm in Pleroma.ThreadMute,
+        on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
+      )
+      |> where([n, a, o, tm], is_nil(tm.id))
+    end
   end
 
   def for_user(user, opts \\ %{}) do
     user
-    |> for_user_query()
+    |> for_user_query(opts)
     |> Pagination.fetch_paginated(opts)
   end
 
@@ -179,11 +194,10 @@ defmodule Pleroma.Notification do
 
   def get_notified_from_activity(_, _local_only), do: []
 
+  @spec skip?(Activity.t(), User.t()) :: boolean()
   def skip?(activity, user) do
     [
       :self,
-      :blocked,
-      :muted,
       :followers,
       :follows,
       :non_followers,
@@ -193,21 +207,11 @@ defmodule Pleroma.Notification do
     |> Enum.any?(&skip?(&1, activity, user))
   end
 
+  @spec skip?(atom(), Activity.t(), User.t()) :: boolean()
   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?(: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,
index e5a6c252993d2ecfd165e441ba2844ecf9b24dc0..29c87d4a9a26481a57cd9e784ab695711e9752fd 100644 (file)
@@ -749,10 +749,13 @@ defmodule Pleroma.User do
     |> Repo.all()
   end
 
-  def mute(muter, %User{ap_id: ap_id}) do
+  @spec mute(User.t(), User.t(), boolean()) :: {:ok, User.t()} | {:error, String.t()}
+  def mute(muter, %User{ap_id: ap_id}, notifications? \\ true) do
+    info = muter.info
+
     info_cng =
-      muter.info
-      |> User.Info.add_to_mutes(ap_id)
+      User.Info.add_to_mutes(info, ap_id)
+      |> User.Info.add_to_muted_notifications(info, ap_id, notifications?)
 
     cng =
       change(muter)
@@ -762,9 +765,11 @@ defmodule Pleroma.User do
   end
 
   def unmute(muter, %{ap_id: ap_id}) do
+    info = muter.info
+
     info_cng =
-      muter.info
-      |> User.Info.remove_from_mutes(ap_id)
+      User.Info.remove_from_mutes(info, ap_id)
+      |> User.Info.remove_from_muted_notifications(info, ap_id)
 
     cng =
       change(muter)
@@ -860,6 +865,12 @@ defmodule Pleroma.User do
   def mutes?(nil, _), do: false
   def mutes?(user, %{ap_id: ap_id}), do: Enum.member?(user.info.mutes, ap_id)
 
+  @spec muted_notifications?(User.t() | nil, User.t() | map()) :: boolean()
+  def muted_notifications?(nil, _), do: false
+
+  def muted_notifications?(user, %{ap_id: ap_id}),
+    do: Enum.member?(user.info.muted_notifications, ap_id)
+
   def blocks?(%User{info: info} = _user, %{ap_id: ap_id}) do
     blocks = info.blocks
     domain_blocks = info.domain_blocks
index 08e43ff0fb9129e90cf1eceb7a6616207e3a5d1b..9beb3ddbd2caba9f25f582378c6042be80859543 100644 (file)
@@ -24,6 +24,7 @@ defmodule Pleroma.User.Info do
     field(:domain_blocks, {:array, :string}, default: [])
     field(:mutes, {:array, :string}, default: [])
     field(:muted_reblogs, {:array, :string}, default: [])
+    field(:muted_notifications, {:array, :string}, default: [])
     field(:subscribers, {:array, :string}, default: [])
     field(:deactivated, :boolean, default: false)
     field(:no_rich_text, :boolean, default: false)
@@ -120,6 +121,16 @@ defmodule Pleroma.User.Info do
     |> validate_required([:mutes])
   end
 
+  @spec set_notification_mutes(Changeset.t(), [String.t()], boolean()) :: Changeset.t()
+  def set_notification_mutes(changeset, muted_notifications, notifications?) do
+    if notifications? do
+      put_change(changeset, :muted_notifications, muted_notifications)
+      |> validate_required([:muted_notifications])
+    else
+      changeset
+    end
+  end
+
   def set_blocks(info, blocks) do
     params = %{blocks: blocks}
 
@@ -136,14 +147,31 @@ defmodule Pleroma.User.Info do
     |> validate_required([:subscribers])
   end
 
+  @spec add_to_mutes(Info.t(), String.t()) :: Changeset.t()
   def add_to_mutes(info, muted) do
     set_mutes(info, Enum.uniq([muted | info.mutes]))
   end
 
+  @spec add_to_muted_notifications(Changeset.t(), Info.t(), String.t(), boolean()) ::
+          Changeset.t()
+  def add_to_muted_notifications(changeset, info, muted, notifications?) do
+    set_notification_mutes(
+      changeset,
+      Enum.uniq([muted | info.muted_notifications]),
+      notifications?
+    )
+  end
+
+  @spec remove_from_mutes(Info.t(), String.t()) :: Changeset.t()
   def remove_from_mutes(info, muted) do
     set_mutes(info, List.delete(info.mutes, muted))
   end
 
+  @spec remove_from_muted_notifications(Changeset.t(), Info.t(), String.t()) :: Changeset.t()
+  def remove_from_muted_notifications(changeset, info, muted) do
+    set_notification_mutes(changeset, List.delete(info.muted_notifications, muted), true)
+  end
+
   def add_to_block(info, blocked) do
     set_blocks(info, Enum.uniq([blocked | info.blocks]))
   end
index c82b201233e31b5c1079fd7df8d28e0a1c667694..46944dcbc1381390eda5fbb48d45f401236f4b1b 100644 (file)
@@ -53,7 +53,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
     options = cast_params(params)
 
     user
-    |> Notification.for_user_query()
+    |> Notification.for_user_query(options)
     |> restrict(:exclude_types, options)
     |> Pagination.fetch_paginated(params)
   end
@@ -67,7 +67,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
   defp cast_params(params) do
     param_types = %{
       exclude_types: {:array, :string},
-      reblogs: :boolean
+      reblogs: :boolean,
+      with_muted: :boolean
     }
 
     changeset = cast({%{}, param_types}, params, Map.keys(param_types))
index 8a7b75025700e9fc64913abba3bd800e581e7faa..b3513b5bfda12a1b786cd042748e79cfb1ba1e2f 100644 (file)
@@ -1068,9 +1068,14 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     end
   end
 
-  def mute(%{assigns: %{user: muter}} = conn, %{"id" => id}) do
+  def mute(%{assigns: %{user: muter}} = conn, %{"id" => id} = params) do
+    notifications =
+      if Map.has_key?(params, "notifications"),
+        do: params["notifications"] in [true, "True", "true", "1"],
+        else: true
+
     with %User{} = muted <- User.get_cached_by_id(id),
-         {:ok, muter} <- User.mute(muter, muted) do
+         {:ok, muter} <- User.mute(muter, muted, notifications) do
       conn
       |> put_view(AccountView)
       |> render("relationship.json", %{user: muter, target: muted})
index 62c516f8eb97989538a1b3e3c3b0e050574ce50d..65bab40629dd765859b02943bee872fe2d3cb330 100644 (file)
@@ -52,7 +52,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
       followed_by: User.following?(target, user),
       blocking: User.blocks?(user, target),
       muting: User.mutes?(user, target),
-      muting_notifications: false,
+      muting_notifications: User.muted_notifications?(user, target),
       subscribing: User.subscribed_to?(user, target),
       requested: requested,
       domain_blocking: false,
index 45ef7be3d277bdc14f7468012ad3ad5f28794e92..0313560a8d9493b5ce02efa88270a752b01c4ac6 100644 (file)
@@ -192,6 +192,13 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
   end
 
   def notifications(%{assigns: %{user: user}} = conn, params) do
+    params =
+      if Map.has_key?(params, "with_muted") do
+        Map.put(params, :with_muted, params["with_muted"] in [true, "True", "true", "1"])
+      else
+        params
+      end
+
     notifications = Notification.for_user(user, params)
 
     conn
diff --git a/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs b/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs
new file mode 100644 (file)
index 0000000..5066990
--- /dev/null
@@ -0,0 +1,24 @@
+defmodule Pleroma.Repo.Migrations.CopyMutedToMutedNotifications do
+  use Ecto.Migration
+  alias Pleroma.User
+
+  def change do
+    query =
+      User.Query.build(%{
+        local: true,
+        active: true,
+        order_by: :id
+      })
+
+    Pleroma.Repo.stream(query)
+    |> Enum.each(fn
+      %{info: %{mutes: mutes} = info} = user ->
+        info_cng =
+          Ecto.Changeset.cast(info, %{muted_notifications: mutes}, [:muted_notifications])
+
+        Ecto.Changeset.change(user)
+        |> Ecto.Changeset.put_embed(:info, info_cng)
+        |> Pleroma.Repo.update()
+    end)
+  end
+end
index 1d36f14bfcb076de8b113a6371ad6bf606f61f58..dda570b499b5841ba3ebaff7b5cd01d771cba954 100644 (file)
@@ -74,26 +74,37 @@ defmodule Pleroma.NotificationTest do
       Task.await(task_user_notification)
     end
 
-    test "it doesn't create a notification for user if the user blocks the activity author" do
+    test "it creates a notification for user if the user blocks the activity author" do
       activity = insert(:note_activity)
       author = User.get_cached_by_ap_id(activity.data["actor"])
       user = insert(:user)
       {:ok, user} = User.block(user, author)
 
-      refute Notification.create_notification(activity, user)
+      assert Notification.create_notification(activity, user)
     end
 
-    test "it doesn't create a notificatin for the user if the user mutes the activity author" do
+    test "it creates 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}"})
 
-      refute Notification.create_notification(activity, muter)
+      assert Notification.create_notification(activity, muter)
     end
 
-    test "it doesn't create a notification for an activity from a muted thread" do
+    test "notification created if user is muted without notifications" do
+      muter = insert(:user)
+      muted = insert(:user)
+
+      {:ok, muter} = User.mute(muter, muted, false)
+
+      {:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
+
+      assert Notification.create_notification(activity, muter)
+    end
+
+    test "it creates a notification for an activity from a muted thread" do
       muter = insert(:user)
       other_user = insert(:user)
       {:ok, activity} = CommonAPI.post(muter, %{"status" => "hey"})
@@ -105,7 +116,7 @@ defmodule Pleroma.NotificationTest do
           "in_reply_to_status_id" => activity.id
         })
 
-      refute Notification.create_notification(activity, muter)
+      assert Notification.create_notification(activity, muter)
     end
 
     test "it disables notifications from followers" do
@@ -532,4 +543,98 @@ defmodule Pleroma.NotificationTest do
       assert Enum.empty?(Notification.for_user(user))
     end
   end
+
+  describe "for_user" do
+    test "it returns notifications for muted user without notifications" do
+      user = insert(:user)
+      muted = insert(:user)
+      {:ok, user} = User.mute(user, muted, false)
+
+      {:ok, _activity} = TwitterAPI.create_status(muted, %{"status" => "hey @#{user.nickname}"})
+
+      assert length(Notification.for_user(user)) == 1
+    end
+
+    test "it doesn't return notifications for muted user with notifications" do
+      user = insert(:user)
+      muted = insert(:user)
+      {:ok, user} = User.mute(user, muted)
+
+      {:ok, _activity} = TwitterAPI.create_status(muted, %{"status" => "hey @#{user.nickname}"})
+
+      assert Notification.for_user(user) == []
+    end
+
+    test "it doesn't return notifications for blocked user" do
+      user = insert(:user)
+      blocked = insert(:user)
+      {:ok, user} = User.block(user, blocked)
+
+      {:ok, _activity} = TwitterAPI.create_status(blocked, %{"status" => "hey @#{user.nickname}"})
+
+      assert Notification.for_user(user) == []
+    end
+
+    test "it doesn't return notificatitons for blocked domain" do
+      user = insert(:user)
+      blocked = insert(:user, ap_id: "http://some-domain.com")
+      {:ok, user} = User.block_domain(user, "some-domain.com")
+
+      {:ok, _activity} = TwitterAPI.create_status(blocked, %{"status" => "hey @#{user.nickname}"})
+
+      assert Notification.for_user(user) == []
+    end
+
+    test "it doesn't return notifications for muted thread" do
+      user = insert(:user)
+      another_user = insert(:user)
+
+      {:ok, activity} =
+        TwitterAPI.create_status(another_user, %{"status" => "hey @#{user.nickname}"})
+
+      {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
+      assert Notification.for_user(user) == []
+    end
+
+    test "it returns notifications for muted user with notifications and with_muted parameter" do
+      user = insert(:user)
+      muted = insert(:user)
+      {:ok, user} = User.mute(user, muted)
+
+      {:ok, _activity} = TwitterAPI.create_status(muted, %{"status" => "hey @#{user.nickname}"})
+
+      assert length(Notification.for_user(user, %{with_muted: true})) == 1
+    end
+
+    test "it returns notifications for blocked user and with_muted parameter" do
+      user = insert(:user)
+      blocked = insert(:user)
+      {:ok, user} = User.block(user, blocked)
+
+      {:ok, _activity} = TwitterAPI.create_status(blocked, %{"status" => "hey @#{user.nickname}"})
+
+      assert length(Notification.for_user(user, %{with_muted: true})) == 1
+    end
+
+    test "it returns notificatitons for blocked domain and with_muted parameter" do
+      user = insert(:user)
+      blocked = insert(:user, ap_id: "http://some-domain.com")
+      {:ok, user} = User.block_domain(user, "some-domain.com")
+
+      {:ok, _activity} = TwitterAPI.create_status(blocked, %{"status" => "hey @#{user.nickname}"})
+
+      assert length(Notification.for_user(user, %{with_muted: true})) == 1
+    end
+
+    test "it returns notifications for muted thread with_muted parameter" do
+      user = insert(:user)
+      another_user = insert(:user)
+
+      {:ok, activity} =
+        TwitterAPI.create_status(another_user, %{"status" => "hey @#{user.nickname}"})
+
+      {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
+      assert length(Notification.for_user(user, %{with_muted: true})) == 1
+    end
+  end
 end
index 7c3fe976d5d53a831e9c58e5f4e223a1f0ca4ca0..264b7a40e8918d6f3ad9f55bd74eb67c1d79f73e 100644 (file)
@@ -687,10 +687,12 @@ defmodule Pleroma.UserTest do
       muted_user = insert(:user)
 
       refute User.mutes?(user, muted_user)
+      refute User.muted_notifications?(user, muted_user)
 
       {:ok, user} = User.mute(user, muted_user)
 
       assert User.mutes?(user, muted_user)
+      assert User.muted_notifications?(user, muted_user)
     end
 
     test "it unmutes users" do
@@ -701,6 +703,20 @@ defmodule Pleroma.UserTest do
       {:ok, user} = User.unmute(user, muted_user)
 
       refute User.mutes?(user, muted_user)
+      refute User.muted_notifications?(user, muted_user)
+    end
+
+    test "it mutes user without notifications" do
+      user = insert(:user)
+      muted_user = insert(:user)
+
+      refute User.mutes?(user, muted_user)
+      refute User.muted_notifications?(user, muted_user)
+
+      {:ok, user} = User.mute(user, muted_user, false)
+
+      assert User.mutes?(user, muted_user)
+      refute User.muted_notifications?(user, muted_user)
     end
   end
 
index b7c050dbf30d6b235ede5b7ab0f056f2b6f6ff9c..6ffa64dc8bdf192c0d7956d545be79cb8d1f9a4d 100644 (file)
@@ -1274,6 +1274,71 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       result = json_response(conn_res, 200)
       assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
     end
+
+    test "doesn't see notifications after muting user with notifications", %{conn: conn} do
+      user = insert(:user)
+      user2 = insert(:user)
+
+      {:ok, _, _, _} = CommonAPI.follow(user, user2)
+      {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
+
+      conn = assign(conn, :user, user)
+
+      conn = get(conn, "/api/v1/notifications")
+
+      assert length(json_response(conn, 200)) == 1
+
+      {:ok, user} = User.mute(user, user2)
+
+      conn = assign(build_conn(), :user, user)
+      conn = get(conn, "/api/v1/notifications")
+
+      assert json_response(conn, 200) == []
+    end
+
+    test "see notifications after muting user without notifications", %{conn: conn} do
+      user = insert(:user)
+      user2 = insert(:user)
+
+      {:ok, _, _, _} = CommonAPI.follow(user, user2)
+      {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
+
+      conn = assign(conn, :user, user)
+
+      conn = get(conn, "/api/v1/notifications")
+
+      assert length(json_response(conn, 200)) == 1
+
+      {:ok, user} = User.mute(user, user2, false)
+
+      conn = assign(build_conn(), :user, user)
+      conn = get(conn, "/api/v1/notifications")
+
+      assert length(json_response(conn, 200)) == 1
+    end
+
+    test "see notifications after muting user with notifications and with_muted parameter", %{
+      conn: conn
+    } do
+      user = insert(:user)
+      user2 = insert(:user)
+
+      {:ok, _, _, _} = CommonAPI.follow(user, user2)
+      {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
+
+      conn = assign(conn, :user, user)
+
+      conn = get(conn, "/api/v1/notifications")
+
+      assert length(json_response(conn, 200)) == 1
+
+      {:ok, user} = User.mute(user, user2)
+
+      conn = assign(build_conn(), :user, user)
+      conn = get(conn, "/api/v1/notifications", %{"with_muted" => "true"})
+
+      assert length(json_response(conn, 200)) == 1
+    end
   end
 
   describe "reblogging" do
@@ -2105,25 +2170,52 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     assert %{"error" => "Record not found"} = json_response(conn_res, 404)
   end
 
-  test "muting / unmuting a user", %{conn: conn} do
-    user = insert(:user)
-    other_user = insert(:user)
+  describe "mute/unmute" do
+    test "with notifications", %{conn: conn} do
+      user = insert(:user)
+      other_user = insert(:user)
 
-    conn =
-      conn
-      |> assign(:user, user)
-      |> post("/api/v1/accounts/#{other_user.id}/mute")
+      conn =
+        conn
+        |> assign(:user, user)
+        |> post("/api/v1/accounts/#{other_user.id}/mute")
 
-    assert %{"id" => _id, "muting" => true} = json_response(conn, 200)
+      response = json_response(conn, 200)
 
-    user = User.get_cached_by_id(user.id)
+      assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response
+      user = User.get_cached_by_id(user.id)
 
-    conn =
-      build_conn()
-      |> assign(:user, user)
-      |> post("/api/v1/accounts/#{other_user.id}/unmute")
+      conn =
+        build_conn()
+        |> assign(:user, user)
+        |> post("/api/v1/accounts/#{other_user.id}/unmute")
 
-    assert %{"id" => _id, "muting" => false} = json_response(conn, 200)
+      response = json_response(conn, 200)
+      assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
+    end
+
+    test "without notifications", %{conn: conn} do
+      user = insert(:user)
+      other_user = insert(:user)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
+
+      response = json_response(conn, 200)
+
+      assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response
+      user = User.get_cached_by_id(user.id)
+
+      conn =
+        build_conn()
+        |> assign(:user, user)
+        |> post("/api/v1/accounts/#{other_user.id}/unmute")
+
+      response = json_response(conn, 200)
+      assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
+    end
   end
 
   test "subscribing / unsubscribing to a user", %{conn: conn} do
index 7ec0e101d52b4ba771a384f40f3792a6a6a285e1..de61775752cb9ffee95a171545411b652bfc1b29 100644 (file)
@@ -521,6 +521,38 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
                  for: current_user
                })
     end
+
+    test "muted user", %{conn: conn, user: current_user} do
+      other_user = insert(:user)
+
+      {:ok, current_user} = User.mute(current_user, other_user)
+
+      {:ok, _activity} =
+        ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
+
+      conn =
+        conn
+        |> with_credentials(current_user.nickname, "test")
+        |> get("/api/qvitter/statuses/notifications.json")
+
+      assert json_response(conn, 200) == []
+    end
+
+    test "muted user with with_muted parameter", %{conn: conn, user: current_user} do
+      other_user = insert(:user)
+
+      {:ok, current_user} = User.mute(current_user, other_user)
+
+      {:ok, _activity} =
+        ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
+
+      conn =
+        conn
+        |> with_credentials(current_user.nickname, "test")
+        |> get("/api/qvitter/statuses/notifications.json", %{"with_muted" => "true"})
+
+      assert length(json_response(conn, 200)) == 1
+    end
   end
 
   describe "POST /api/qvitter/statuses/notifications/read" do