Implement muting, add it to the mastodon API
authorEkaterina Vaartis <vaartis@cock.li>
Wed, 5 Sep 2018 20:49:15 +0000 (23:49 +0300)
committerEkaterina Vaartis <vaartis@cock.li>
Tue, 19 Feb 2019 18:49:55 +0000 (21:49 +0300)
lib/pleroma/user.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/mastodon_api/views/account_view.ex
lib/pleroma/web/router.ex

index 18bb566674a34dcf9c91d37d3533f2f53a0013ec..9a774e7b7da9e793ab16ce44c7216c1cfb00026c 100644 (file)
@@ -888,6 +888,28 @@ defmodule Pleroma.User do
     )
   end
 
+  def mute(muter, %User{ap_id: ap_id} = muted) do
+    if following?(muter, muter) do
+      unfollow(muter, muter)
+    end
+
+    mutes = muter.info["mutes"] || []
+    new_mutes = Enum.uniq([ap_id | mutes])
+    new_info = Map.put(muter.info, "mutes", new_mutes)
+
+    cs = User.info_changeset(muter, %{info: new_info})
+    update_and_set_cache(cs)
+  end
+
+  def unmute(user, %{ap_id: ap_id}) do
+    mutes = user.info["mutes"] || []
+    new_mutes = List.delete(mutes, ap_id)
+    new_info = Map.put(user.info, "mutes", new_mutes)
+
+    cs = User.info_changeset(user, %{info: new_info})
+    update_and_set_cache(cs)
+  end
+
   def block(blocker, %User{ap_id: ap_id} = blocked) do
     # sever any follow relationships to prevent leaks per activitypub (Pleroma issue #213)
     blocker =
@@ -930,6 +952,8 @@ defmodule Pleroma.User do
     update_and_set_cache(cng)
   end
 
+  def mutes?(user, %{ap_id: ap_id}), do: Enum.member?(user.info["mutes"] || [], ap_id)
+
   def blocks?(user, %{ap_id: ap_id}) do
     blocks = user.info.blocks
     domain_blocks = user.info.domain_blocks
index 8d311683949e834638296861df7e6a21cde82a27..36e5e23bff61fb6ce97eae51f855452964e1ddbe 100644 (file)
@@ -576,6 +576,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   defp restrict_reblogs(query, _), do: query
 
+  defp restrict_muted(query, %{"muting_user" => %User{info: info}}) do
+    mutes = info["mutes"] || []
+
+    from(
+      activity in query,
+      where: fragment("not (? = ANY(?))", activity.actor, ^mutes),
+      where: fragment("not (?->'to' \\?| ?)", activity.data, ^mutes)
+    )
+  end
+
+  defp restrict_muted(query, _), do: query
+
   defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do
     blocks = info.blocks || []
     domain_blocks = info.domain_blocks || []
@@ -629,6 +641,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     |> restrict_type(opts)
     |> restrict_favorited_by(opts)
     |> restrict_blocked(opts)
+    |> restrict_muted(opts)
     |> restrict_media(opts)
     |> restrict_visibility(opts)
     |> restrict_replies(opts)
index e2715bd08ab2a4c1a32e88db6c6db3cec7dc6e38..af16264eeb996883cbc02db3169b6fc9290e60d3 100644 (file)
@@ -232,6 +232,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
       params
       |> Map.put("type", ["Create", "Announce"])
       |> Map.put("blocking_user", user)
+      |> Map.put("muting_user", user)
       |> Map.put("user", user)
 
     activities =
@@ -254,6 +255,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
       |> Map.put("type", ["Create", "Announce"])
       |> Map.put("local_only", local_only)
       |> Map.put("blocking_user", user)
+      |> Map.put("muting_user", user)
       |> ActivityPub.fetch_public_activities()
       |> Enum.reverse()
 
@@ -620,6 +622,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
       |> Map.put("type", "Create")
       |> Map.put("local_only", local_only)
       |> Map.put("blocking_user", user)
+      |> Map.put("muting_user", user)
       |> Map.put("tag", tags)
       |> Map.put("tag_all", tag_all)
       |> Map.put("tag_reject", tag_reject)
@@ -763,6 +766,20 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     end
   end
 
+  def mute(%{assigns: %{user: muter}} = conn, %{"id" => id}) do
+    with %User{} = muted <- Repo.get(User, id),
+         {:ok, muter} <- User.mute(muter, muted) do
+      render(conn, AccountView, "relationship.json", %{user: muter, target: muted})
+    end
+  end
+
+  def unmute(%{assigns: %{user: muter}} = conn, %{"id" => id}) do
+    with %User{} = muted <- Repo.get(User, id),
+         {:ok, muter} <- User.unmute(muter, muted) do
+      render(conn, AccountView, "relationship.json", %{user: muter, target: muted})
+    end
+  end
+
   def block(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
     with %User{} = blocked <- Repo.get(User, id),
          {:ok, blocker} <- User.block(blocker, blocked),
@@ -1018,6 +1035,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
         params
         |> Map.put("type", "Create")
         |> Map.put("blocking_user", user)
+        |> Map.put("muting_user", user)
 
       # we must filter the following list for the user to avoid leaking statuses the user
       # does not actually have permission to see (for more info, peruse security issue #270).
index 9df9f14b2a04ff352750e2d7f85a73a6224d09d3..91b3e034fcbcae9c02be58de4543672917a1d53f 100644 (file)
@@ -47,6 +47,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
       following: User.following?(user, target),
       followed_by: User.following?(target, user),
       blocking: User.blocks?(user, target),
+      muting: User.mutes?(user, target),
       muting: false,
       muting_notifications: false,
       requested: requested,
index 9a6cf22328c641ee45748cf43f905176f1d8fc33..fb7a8d4489bc24b79e52e4022ac2cc3b63ec8f35 100644 (file)
@@ -166,8 +166,8 @@ defmodule Pleroma.Web.Router do
     post("/accounts/:id/unfollow", MastodonAPIController, :unfollow)
     post("/accounts/:id/block", MastodonAPIController, :block)
     post("/accounts/:id/unblock", MastodonAPIController, :unblock)
-    post("/accounts/:id/mute", MastodonAPIController, :relationship_noop)
-    post("/accounts/:id/unmute", MastodonAPIController, :relationship_noop)
+    post("/accounts/:id/mute", MastodonAPIController, :mute)
+    post("/accounts/:id/unmute", MastodonAPIController, :unmute)
     get("/accounts/:id/lists", MastodonAPIController, :account_lists)
 
     get("/follow_requests", MastodonAPIController, :follow_requests)