From c8f31e0bc2764c924a4045e007e828052c837ac2 Mon Sep 17 00:00:00 2001 From: Karen Konou Date: Sat, 9 Mar 2019 14:08:41 +0100 Subject: [PATCH] Implement mastodon's reblog hiding feature --- lib/pleroma/user.ex | 4 ++++ lib/pleroma/user/info.ex | 13 +++++++++++++ lib/pleroma/web/activity_pub/activity_pub.ex | 10 +++++++++- lib/pleroma/web/common_api/common_api.ex | 16 ++++++++++++++++ .../web/mastodon_api/mastodon_api_controller.ex | 13 +++++++++++++ .../web/mastodon_api/views/account_view.ex | 2 +- 6 files changed, 56 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 1ce9882f6..467cb910b 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1385,4 +1385,8 @@ defp paginate(query, page, page_size) do offset: ^((page - 1) * page_size) ) end + + def showing_reblogs?(%User{} = user, %User{} = target) do + target.id not in user.info.muted_reblogs + end end diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index e3fd65a6e..35586e212 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -21,6 +21,7 @@ defmodule Pleroma.User.Info do field(:blocks, {:array, :string}, default: []) field(:domain_blocks, {:array, :string}, default: []) field(:mutes, {:array, :string}, default: []) + field(:muted_reblogs, {:array, :string}, default: []) field(:deactivated, :boolean, default: false) field(:no_rich_text, :boolean, default: false) field(:ap_enabled, :boolean, default: false) @@ -259,4 +260,16 @@ def roles(%Info{is_moderator: is_moderator, is_admin: is_admin}) do moderator: is_moderator } end + + def add_reblog_mute(info, id) do + params = %{muted_reblogs: info.muted_reblogs ++ [id]} + + cast(info, params, [:muted_reblogs]) + end + + def remove_reblog_mute(info, id) do + params = %{muted_reblogs: List.delete(info.muted_reblogs, id)} + + cast(info, params, [:muted_reblogs]) + end end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 70db419ca..779ee139b 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -951,9 +951,17 @@ def contain_broken_threads(%Activity{} = activity, %User{} = user) do entire_thread_visible_for_user?(activity, user) end + # filter out muted threads + def contain_muted_boosts(%Activity{data: %{"type" => "Announce"}} = activity, %User{} = user) do + id = User.get_by_ap_id(activity.actor).id + id not in user.info.muted_reblogs + end + + def contain_muted_boosts(%Activity{} = _activity, %User{} = _user), do: true + # do post-processing on a specific activity def contain_activity(%Activity{} = activity, %User{} = user) do - contain_broken_threads(activity, user) + contain_broken_threads(activity, user) and contain_muted_boosts(activity, user) end # do post-processing on a timeline diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index de0759fb0..035c59387 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -299,4 +299,20 @@ def report(user, data) do {:account, nil} -> {:error, "Account not found"} end end + + def hide_reblogs(user, id) do + if id not in user.info.muted_reblogs do + info_changeset = User.Info.add_reblog_mute(user.info, id) + changeset = Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset) + User.update_and_set_cache(changeset) + end + end + + def show_reblogs(user, id) do + if id in user.info.muted_reblogs do + info_changeset = User.Info.remove_reblog_mute(user.info, id) + changeset = Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset) + User.update_and_set_cache(changeset) + end + end end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 265bf837e..570bf0c0f 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -723,11 +723,24 @@ def reject_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) d def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do with %User{} = followed <- Repo.get(User, id), + false <- User.following?(follower, followed), {:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do conn |> put_view(AccountView) |> render("relationship.json", %{user: follower, target: followed}) else + true -> + case conn.params["reblogs"] do + true -> CommonAPI.show_reblogs(follower, id) + false -> CommonAPI.hide_reblogs(follower, id) + end + + followed = Repo.get(User, id) + + conn + |> put_view(AccountView) + |> render("relationship.json", %{user: follower, target: followed}) + {:error, message} -> conn |> put_resp_content_type("application/json") diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index c32f27be2..b5f3bbb9d 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -55,7 +55,7 @@ def render("relationship.json", %{user: %User{} = user, target: %User{} = target muting_notifications: false, requested: requested, domain_blocking: false, - showing_reblogs: false, + showing_reblogs: User.showing_reblogs?(user, target), endorsed: false } end