Merge branch 'feature/thread-muting' into 'develop'
Feature/thread muting See merge request pleroma/pleroma!796
This commit is contained in:
commit
39383a6b79
|
@ -10,6 +10,7 @@ defmodule Pleroma.Notification do
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
|
@ -117,7 +118,7 @@ def create_notifications(_), do: {:ok, []}
|
||||||
# TODO move to sql, too.
|
# TODO move to sql, too.
|
||||||
def create_notification(%Activity{} = activity, %User{} = user) do
|
def create_notification(%Activity{} = activity, %User{} = user) do
|
||||||
unless User.blocks?(user, %{ap_id: activity.data["actor"]}) or
|
unless User.blocks?(user, %{ap_id: activity.data["actor"]}) or
|
||||||
user.ap_id == activity.data["actor"] or
|
CommonAPI.thread_muted?(user, activity) or user.ap_id == activity.data["actor"] or
|
||||||
(activity.data["type"] == "Follow" and
|
(activity.data["type"] == "Follow" and
|
||||||
Enum.any?(Notification.for_user(user), fn notif ->
|
Enum.any?(Notification.for_user(user), fn notif ->
|
||||||
notif.activity.data["type"] == "Follow" and
|
notif.activity.data["type"] == "Follow" and
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.ThreadMute do
|
||||||
|
use Ecto.Schema
|
||||||
|
alias Pleroma.{Repo, User, ThreadMute}
|
||||||
|
require Ecto.Query
|
||||||
|
|
||||||
|
schema "thread_mutes" do
|
||||||
|
belongs_to(:user, User, type: Pleroma.FlakeId)
|
||||||
|
field(:context, :string)
|
||||||
|
end
|
||||||
|
|
||||||
|
def changeset(mute, params \\ %{}) do
|
||||||
|
mute
|
||||||
|
|> Ecto.Changeset.cast(params, [:user_id, :context])
|
||||||
|
|> Ecto.Changeset.foreign_key_constraint(:user_id)
|
||||||
|
|> Ecto.Changeset.unique_constraint(:user_id, name: :unique_index)
|
||||||
|
end
|
||||||
|
|
||||||
|
def query(user_id, context) do
|
||||||
|
user_id = Pleroma.FlakeId.from_string(user_id)
|
||||||
|
|
||||||
|
ThreadMute
|
||||||
|
|> Ecto.Query.where(user_id: ^user_id)
|
||||||
|
|> Ecto.Query.where(context: ^context)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_mute(user_id, context) do
|
||||||
|
%ThreadMute{}
|
||||||
|
|> changeset(%{user_id: user_id, context: context})
|
||||||
|
|> Repo.insert()
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_mute(user_id, context) do
|
||||||
|
query(user_id, context)
|
||||||
|
|> Repo.delete_all()
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_muted(user_id, context) do
|
||||||
|
query(user_id, context)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.ThreadMute
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
alias Pleroma.Formatter
|
alias Pleroma.Formatter
|
||||||
|
@ -219,4 +220,27 @@ def unpin(id_or_ap_id, user) do
|
||||||
{:error, "Could not unpin"}
|
{:error, "Could not unpin"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_mute(user, activity) do
|
||||||
|
with {:ok, _} <- ThreadMute.add_mute(user.id, activity.data["context"]) do
|
||||||
|
{:ok, activity}
|
||||||
|
else
|
||||||
|
{:error, _} -> {:error, "conversation is already muted"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_mute(user, activity) do
|
||||||
|
ThreadMute.remove_mute(user.id, activity.data["context"])
|
||||||
|
{:ok, activity}
|
||||||
|
end
|
||||||
|
|
||||||
|
def thread_muted?(%{id: nil} = _user, _activity), do: false
|
||||||
|
|
||||||
|
def thread_muted?(user, activity) do
|
||||||
|
with [] <- ThreadMute.check_muted(user.id, activity.data["context"]) do
|
||||||
|
false
|
||||||
|
else
|
||||||
|
_ -> true
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -456,6 +456,31 @@ def unbookmark_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
|
activity = Activity.get_by_id(id)
|
||||||
|
|
||||||
|
with {:ok, activity} <- CommonAPI.add_mute(user, activity) do
|
||||||
|
conn
|
||||||
|
|> put_view(StatusView)
|
||||||
|
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
||||||
|
else
|
||||||
|
{:error, reason} ->
|
||||||
|
conn
|
||||||
|
|> put_resp_content_type("application/json")
|
||||||
|
|> send_resp(:bad_request, Jason.encode!(%{"error" => reason}))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unmute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
|
activity = Activity.get_by_id(id)
|
||||||
|
|
||||||
|
with {:ok, activity} <- CommonAPI.remove_mute(user, activity) do
|
||||||
|
conn
|
||||||
|
|> put_view(StatusView)
|
||||||
|
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def notifications(%{assigns: %{user: user}} = conn, params) do
|
def notifications(%{assigns: %{user: user}} = conn, params) do
|
||||||
notifications = Notification.for_user(user, params)
|
notifications = Notification.for_user(user, params)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
||||||
alias Pleroma.HTML
|
alias Pleroma.HTML
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
|
@ -160,7 +161,7 @@ def render("status.json", %{activity: %{data: %{"object" => object}} = activity}
|
||||||
reblogged: present?(repeated),
|
reblogged: present?(repeated),
|
||||||
favourited: present?(favorited),
|
favourited: present?(favorited),
|
||||||
bookmarked: present?(bookmarked),
|
bookmarked: present?(bookmarked),
|
||||||
muted: false,
|
muted: CommonAPI.thread_muted?(user, activity),
|
||||||
pinned: pinned?(activity, user),
|
pinned: pinned?(activity, user),
|
||||||
sensitive: sensitive,
|
sensitive: sensitive,
|
||||||
spoiler_text: object["summary"] || "",
|
spoiler_text: object["summary"] || "",
|
||||||
|
|
|
@ -198,6 +198,8 @@ defmodule Pleroma.Web.Router do
|
||||||
post("/statuses/:id/unpin", MastodonAPIController, :unpin_status)
|
post("/statuses/:id/unpin", MastodonAPIController, :unpin_status)
|
||||||
post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status)
|
post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status)
|
||||||
post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status)
|
post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status)
|
||||||
|
post("/statuses/:id/mute", MastodonAPIController, :mute_conversation)
|
||||||
|
post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation)
|
||||||
|
|
||||||
post("/notifications/clear", MastodonAPIController, :clear_notifications)
|
post("/notifications/clear", MastodonAPIController, :clear_notifications)
|
||||||
post("/notifications/dismiss", MastodonAPIController, :dismiss_notification)
|
post("/notifications/dismiss", MastodonAPIController, :dismiss_notification)
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.CreateThreadMutes do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:thread_mutes) do
|
||||||
|
add :user_id, references(:users, type: :uuid, on_delete: :delete_all)
|
||||||
|
add :context, :string
|
||||||
|
end
|
||||||
|
|
||||||
|
create unique_index(:thread_mutes, [:user_id, :context], name: :unique_index)
|
||||||
|
end
|
||||||
|
end
|
|
@ -164,4 +164,30 @@ test "should unpin when deleting a status", %{user: user, activity: activity} do
|
||||||
assert %User{info: %{pinned_activities: []}} = user
|
assert %User{info: %{pinned_activities: []}} = user
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "mute tests" do
|
||||||
|
setup do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
|
||||||
|
[user: user, activity: activity]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "add mute", %{user: user, activity: activity} do
|
||||||
|
{:ok, _} = CommonAPI.add_mute(user, activity)
|
||||||
|
assert CommonAPI.thread_muted?(user, activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "remove mute", %{user: user, activity: activity} do
|
||||||
|
CommonAPI.add_mute(user, activity)
|
||||||
|
{:ok, _} = CommonAPI.remove_mute(user, activity)
|
||||||
|
refute CommonAPI.thread_muted?(user, activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "check that mutes can't be duplicate", %{user: user, activity: activity} do
|
||||||
|
CommonAPI.add_mute(user, activity)
|
||||||
|
{:error, _} = CommonAPI.add_mute(user, activity)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1749,4 +1749,36 @@ test "bookmarks" do
|
||||||
|
|
||||||
assert [json_response(response2, 200)] == json_response(bookmarks, 200)
|
assert [json_response(response2, 200)] == json_response(bookmarks, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "conversation muting" do
|
||||||
|
setup do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
|
||||||
|
|
||||||
|
[user: user, activity: activity]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "mute conversation", %{conn: conn, user: user, activity: activity} do
|
||||||
|
id_str = to_string(activity.id)
|
||||||
|
|
||||||
|
assert %{"id" => ^id_str, "muted" => true} =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/statuses/#{activity.id}/mute")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "unmute conversation", %{conn: conn, user: user, activity: activity} do
|
||||||
|
{:ok, _} = CommonAPI.add_mute(user, activity)
|
||||||
|
|
||||||
|
id_str = to_string(activity.id)
|
||||||
|
user = refresh_record(user)
|
||||||
|
|
||||||
|
assert %{"id" => ^id_str, "muted" => false} =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/statuses/#{activity.id}/unmute")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue