forked from AkkomaGang/akkoma
Hide reactions from muted and blocked users
This commit is contained in:
parent
28da36975d
commit
fb41bd1a85
16 changed files with 461 additions and 31 deletions
|
@ -245,6 +245,18 @@ def unquote(:"#{outgoing_relation_target}_ap_ids")(user, restrict_deactivated? \
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cached_blocked_users_ap_ids(user) do
|
||||||
|
Cachex.fetch!(:user_cache, "blocked_users_ap_ids:#{user.ap_id}", fn _ ->
|
||||||
|
blocked_users_ap_ids(user)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cached_muted_users_ap_ids(user) do
|
||||||
|
Cachex.fetch!(:user_cache, "muted_users_ap_ids:#{user.ap_id}", fn _ ->
|
||||||
|
muted_users_ap_ids(user)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
defdelegate following_count(user), to: FollowingRelationship
|
defdelegate following_count(user), to: FollowingRelationship
|
||||||
defdelegate following(user), to: FollowingRelationship
|
defdelegate following(user), to: FollowingRelationship
|
||||||
defdelegate following?(follower, followed), to: FollowingRelationship
|
defdelegate following?(follower, followed), to: FollowingRelationship
|
||||||
|
@ -1036,6 +1048,8 @@ def invalidate_cache(user) do
|
||||||
Cachex.del(:user_cache, "ap_id:#{user.ap_id}")
|
Cachex.del(:user_cache, "ap_id:#{user.ap_id}")
|
||||||
Cachex.del(:user_cache, "nickname:#{user.nickname}")
|
Cachex.del(:user_cache, "nickname:#{user.nickname}")
|
||||||
Cachex.del(:user_cache, "friends_ap_ids:#{user.ap_id}")
|
Cachex.del(:user_cache, "friends_ap_ids:#{user.ap_id}")
|
||||||
|
Cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||||
|
Cachex.del(:user_cache, "muted_users_ap_ids:#{user.ap_id}")
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec get_cached_by_ap_id(String.t()) :: User.t() | nil
|
@spec get_cached_by_ap_id(String.t()) :: User.t() | nil
|
||||||
|
@ -1342,6 +1356,8 @@ def mute(%User{} = muter, %User{} = mutee, params \\ %{}) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
|
||||||
|
|
||||||
{:ok, Enum.filter([user_mute, user_notification_mute], & &1)}
|
{:ok, Enum.filter([user_mute, user_notification_mute], & &1)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1350,6 +1366,7 @@ def unmute(%User{} = muter, %User{} = mutee) do
|
||||||
with {:ok, user_mute} <- UserRelationship.delete_mute(muter, mutee),
|
with {:ok, user_mute} <- UserRelationship.delete_mute(muter, mutee),
|
||||||
{:ok, user_notification_mute} <-
|
{:ok, user_notification_mute} <-
|
||||||
UserRelationship.delete_notification_mute(muter, mutee) do
|
UserRelationship.delete_notification_mute(muter, mutee) do
|
||||||
|
Cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
|
||||||
{:ok, [user_mute, user_notification_mute]}
|
{:ok, [user_mute, user_notification_mute]}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2345,13 +2362,19 @@ def unblock_domain(user, domain_blocked) do
|
||||||
@spec add_to_block(User.t(), User.t()) ::
|
@spec add_to_block(User.t(), User.t()) ::
|
||||||
{:ok, UserRelationship.t()} | {:error, Ecto.Changeset.t()}
|
{:ok, UserRelationship.t()} | {:error, Ecto.Changeset.t()}
|
||||||
defp add_to_block(%User{} = user, %User{} = blocked) do
|
defp add_to_block(%User{} = user, %User{} = blocked) do
|
||||||
UserRelationship.create_block(user, blocked)
|
with {:ok, relationship} <- UserRelationship.create_block(user, blocked) do
|
||||||
|
Cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||||
|
{:ok, relationship}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec add_to_block(User.t(), User.t()) ::
|
@spec add_to_block(User.t(), User.t()) ::
|
||||||
{:ok, UserRelationship.t()} | {:ok, nil} | {:error, Ecto.Changeset.t()}
|
{:ok, UserRelationship.t()} | {:ok, nil} | {:error, Ecto.Changeset.t()}
|
||||||
defp remove_from_block(%User{} = user, %User{} = blocked) do
|
defp remove_from_block(%User{} = user, %User{} = blocked) do
|
||||||
UserRelationship.delete_block(user, blocked)
|
with {:ok, relationship} <- UserRelationship.delete_block(user, blocked) do
|
||||||
|
Cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||||
|
{:ok, relationship}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_invisible(user, invisible) do
|
def set_invisible(user, invisible) do
|
||||||
|
|
|
@ -139,6 +139,12 @@ def statuses_operation do
|
||||||
:query,
|
:query,
|
||||||
%Schema{type: :array, items: VisibilityScope},
|
%Schema{type: :array, items: VisibilityScope},
|
||||||
"Exclude visibilities"
|
"Exclude visibilities"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:with_muted,
|
||||||
|
:query,
|
||||||
|
BooleanLike,
|
||||||
|
"Include reactions from muted acccounts."
|
||||||
)
|
)
|
||||||
] ++ pagination_params(),
|
] ++ pagination_params(),
|
||||||
responses: %{
|
responses: %{
|
||||||
|
|
|
@ -24,6 +24,12 @@ def index_operation do
|
||||||
Operation.parameter(:id, :path, FlakeID, "Status ID", required: true),
|
Operation.parameter(:id, :path, FlakeID, "Status ID", required: true),
|
||||||
Operation.parameter(:emoji, :path, :string, "Filter by a single unicode emoji",
|
Operation.parameter(:emoji, :path, :string, "Filter by a single unicode emoji",
|
||||||
required: nil
|
required: nil
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:with_muted,
|
||||||
|
:query,
|
||||||
|
:boolean,
|
||||||
|
"Include reactions from muted acccounts."
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
security: [%{"oAuth" => ["read:statuses"]}],
|
security: [%{"oAuth" => ["read:statuses"]}],
|
||||||
|
|
|
@ -31,6 +31,12 @@ def index_operation do
|
||||||
:query,
|
:query,
|
||||||
%Schema{type: :array, items: FlakeID},
|
%Schema{type: :array, items: FlakeID},
|
||||||
"Array of status IDs"
|
"Array of status IDs"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:with_muted,
|
||||||
|
:query,
|
||||||
|
BooleanLike,
|
||||||
|
"Include reactions from muted acccounts."
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
operationId: "StatusController.index",
|
operationId: "StatusController.index",
|
||||||
|
@ -67,7 +73,15 @@ def show_operation do
|
||||||
description: "View information about a status",
|
description: "View information about a status",
|
||||||
operationId: "StatusController.show",
|
operationId: "StatusController.show",
|
||||||
security: [%{"oAuth" => ["read:statuses"]}],
|
security: [%{"oAuth" => ["read:statuses"]}],
|
||||||
parameters: [id_param()],
|
parameters: [
|
||||||
|
id_param(),
|
||||||
|
Operation.parameter(
|
||||||
|
:with_muted,
|
||||||
|
:query,
|
||||||
|
BooleanLike,
|
||||||
|
"Include reactions from muted acccounts."
|
||||||
|
)
|
||||||
|
],
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => status_response(),
|
200 => status_response(),
|
||||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||||
|
|
|
@ -292,7 +292,8 @@ def statuses(%{assigns: %{user: reading_user}} = conn, params) do
|
||||||
|> render("index.json",
|
|> render("index.json",
|
||||||
activities: activities,
|
activities: activities,
|
||||||
for: reading_user,
|
for: reading_user,
|
||||||
as: :activity
|
as: :activity,
|
||||||
|
with_muted: Map.get(params, :with_muted, false)
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
error -> user_visibility_error(conn, error)
|
error -> user_visibility_error(conn, error)
|
||||||
|
|
|
@ -109,7 +109,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
|
||||||
|
|
||||||
`ids` query param is required
|
`ids` query param is required
|
||||||
"""
|
"""
|
||||||
def index(%{assigns: %{user: user}} = conn, %{ids: ids} = _params) do
|
def index(%{assigns: %{user: user}} = conn, %{ids: ids} = params) do
|
||||||
limit = 100
|
limit = 100
|
||||||
|
|
||||||
activities =
|
activities =
|
||||||
|
@ -121,7 +121,8 @@ def index(%{assigns: %{user: user}} = conn, %{ids: ids} = _params) do
|
||||||
render(conn, "index.json",
|
render(conn, "index.json",
|
||||||
activities: activities,
|
activities: activities,
|
||||||
for: user,
|
for: user,
|
||||||
as: :activity
|
as: :activity,
|
||||||
|
with_muted: Map.get(params, :with_muted, false)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -189,13 +190,14 @@ def create(%{assigns: %{user: _user}, body_params: %{media_ids: _} = params} = c
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "GET /api/v1/statuses/:id"
|
@doc "GET /api/v1/statuses/:id"
|
||||||
def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
def show(%{assigns: %{user: user}} = conn, %{id: id} = params) do
|
||||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||||
true <- Visibility.visible_for_user?(activity, user) do
|
true <- Visibility.visible_for_user?(activity, user) do
|
||||||
try_render(conn, "show.json",
|
try_render(conn, "show.json",
|
||||||
activity: activity,
|
activity: activity,
|
||||||
for: user,
|
for: user,
|
||||||
with_direct_conversation_id: true
|
with_direct_conversation_id: true,
|
||||||
|
with_muted: Map.get(params, :with_muted, false)
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
_ -> {:error, :not_found}
|
_ -> {:error, :not_found}
|
||||||
|
|
|
@ -62,7 +62,8 @@ def home(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> render("index.json",
|
|> render("index.json",
|
||||||
activities: activities,
|
activities: activities,
|
||||||
for: user,
|
for: user,
|
||||||
as: :activity
|
as: :activity,
|
||||||
|
with_muted: Map.get(params, :with_muted, false)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -119,7 +120,8 @@ def public(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> render("index.json",
|
|> render("index.json",
|
||||||
activities: activities,
|
activities: activities,
|
||||||
for: user,
|
for: user,
|
||||||
as: :activity
|
as: :activity,
|
||||||
|
with_muted: Map.get(params, :with_muted, false)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -173,7 +175,8 @@ def hashtag(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> render("index.json",
|
|> render("index.json",
|
||||||
activities: activities,
|
activities: activities,
|
||||||
for: user,
|
for: user,
|
||||||
as: :activity
|
as: :activity,
|
||||||
|
with_muted: Map.get(params, :with_muted, false)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -202,7 +205,8 @@ def list(%{assigns: %{user: user}} = conn, %{list_id: id} = params) do
|
||||||
render(conn, "index.json",
|
render(conn, "index.json",
|
||||||
activities: activities,
|
activities: activities,
|
||||||
for: user,
|
for: user,
|
||||||
as: :activity
|
as: :activity,
|
||||||
|
with_muted: Map.get(params, :with_muted, false)
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
_e -> render_error(conn, :forbidden, "Error.")
|
_e -> render_error(conn, :forbidden, "Error.")
|
||||||
|
|
|
@ -19,6 +19,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
||||||
alias Pleroma.Web.MastodonAPI.PollView
|
alias Pleroma.Web.MastodonAPI.PollView
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
|
alias Pleroma.Web.PleromaAPI.EmojiReactionController
|
||||||
|
|
||||||
import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1, visible_for_user?: 2]
|
import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1, visible_for_user?: 2]
|
||||||
|
|
||||||
|
@ -294,21 +295,16 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
|
||||||
end
|
end
|
||||||
|
|
||||||
emoji_reactions =
|
emoji_reactions =
|
||||||
with %{data: %{"reactions" => emoji_reactions}} <- object do
|
object.data
|
||||||
Enum.map(emoji_reactions, fn
|
|> Map.get("reactions", [])
|
||||||
[emoji, users] when is_list(users) ->
|
|> EmojiReactionController.filter_allowed_users(
|
||||||
|
opts[:for],
|
||||||
|
Map.get(opts, :with_muted, false)
|
||||||
|
)
|
||||||
|
|> Stream.map(fn {emoji, users} ->
|
||||||
build_emoji_map(emoji, users, opts[:for])
|
build_emoji_map(emoji, users, opts[:for])
|
||||||
|
|
||||||
{emoji, users} when is_list(users) ->
|
|
||||||
build_emoji_map(emoji, users, opts[:for])
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
nil
|
|
||||||
end)
|
end)
|
||||||
|> Enum.reject(&is_nil/1)
|
|> Enum.to_list()
|
||||||
else
|
|
||||||
_ -> []
|
|
||||||
end
|
|
||||||
|
|
||||||
# Status muted state (would do 1 request per status unless user mutes are preloaded)
|
# Status muted state (would do 1 request per status unless user mutes are preloaded)
|
||||||
muted =
|
muted =
|
||||||
|
|
|
@ -140,8 +140,8 @@ def messages(%{assigns: %{user: user}} = conn, %{id: id} = params) do
|
||||||
|
|
||||||
def index(%{assigns: %{user: %{id: user_id} = user}} = conn, params) do
|
def index(%{assigns: %{user: %{id: user_id} = user}} = conn, params) do
|
||||||
exclude_users =
|
exclude_users =
|
||||||
User.blocked_users_ap_ids(user) ++
|
User.cached_blocked_users_ap_ids(user) ++
|
||||||
if params[:with_muted], do: [], else: User.muted_users_ap_ids(user)
|
if params[:with_muted], do: [], else: User.cached_muted_users_ap_ids(user)
|
||||||
|
|
||||||
chats =
|
chats =
|
||||||
user_id
|
user_id
|
||||||
|
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||||
|
@ -29,13 +30,42 @@ def index(%{assigns: %{user: user}} = conn, %{id: activity_id} = params) do
|
||||||
%Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
|
%Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
|
||||||
%Object{data: %{"reactions" => reactions}} when is_list(reactions) <-
|
%Object{data: %{"reactions" => reactions}} when is_list(reactions) <-
|
||||||
Object.normalize(activity) do
|
Object.normalize(activity) do
|
||||||
reactions = filter(reactions, params)
|
reactions =
|
||||||
|
reactions
|
||||||
|
|> filter(params)
|
||||||
|
|> filter_allowed_users(user, Map.get(params, :with_muted, false))
|
||||||
|
|
||||||
render(conn, "index.json", emoji_reactions: reactions, user: user)
|
render(conn, "index.json", emoji_reactions: reactions, user: user)
|
||||||
else
|
else
|
||||||
_e -> json(conn, [])
|
_e -> json(conn, [])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filter_allowed_users(reactions, user, with_muted) do
|
||||||
|
exclude_ap_ids =
|
||||||
|
if is_nil(user) do
|
||||||
|
[]
|
||||||
|
else
|
||||||
|
User.cached_blocked_users_ap_ids(user) ++
|
||||||
|
if not with_muted, do: User.cached_muted_users_ap_ids(user), else: []
|
||||||
|
end
|
||||||
|
|
||||||
|
filter_emoji = fn emoji, users ->
|
||||||
|
case Enum.reject(users, &(&1 in exclude_ap_ids)) do
|
||||||
|
[] -> nil
|
||||||
|
users -> {emoji, users}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
reactions
|
||||||
|
|> Stream.map(fn
|
||||||
|
[emoji, users] when is_list(users) -> filter_emoji.(emoji, users)
|
||||||
|
{emoji, users} when is_list(users) -> filter_emoji.(emoji, users)
|
||||||
|
_ -> nil
|
||||||
|
end)
|
||||||
|
|> Stream.reject(&is_nil/1)
|
||||||
|
end
|
||||||
|
|
||||||
defp filter(reactions, %{emoji: emoji}) when is_binary(emoji) do
|
defp filter(reactions, %{emoji: emoji}) when is_binary(emoji) do
|
||||||
Enum.filter(reactions, fn [e, _] -> e == emoji end)
|
Enum.filter(reactions, fn [e, _] -> e == emoji end)
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,7 @@ def render("index.json", %{emoji_reactions: emoji_reactions} = opts) do
|
||||||
render_many(emoji_reactions, __MODULE__, "show.json", opts)
|
render_many(emoji_reactions, __MODULE__, "show.json", opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("show.json", %{emoji_reaction: [emoji, user_ap_ids], user: user}) do
|
def render("show.json", %{emoji_reaction: {emoji, user_ap_ids}, user: user}) do
|
||||||
users = fetch_users(user_ap_ids)
|
users = fetch_users(user_ap_ids)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
|
@ -436,6 +436,39 @@ test "the user views their own timelines and excludes direct messages", %{
|
||||||
conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_visibilities[]=direct")
|
conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_visibilities[]=direct")
|
||||||
assert [%{"id" => ^public_activity_id}] = json_response_and_validate_schema(conn, 200)
|
assert [%{"id" => ^public_activity_id}] = json_response_and_validate_schema(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "muted reactions", %{user: user, conn: conn} do
|
||||||
|
user2 = insert(:user)
|
||||||
|
User.mute(user, user2)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "."})
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user2, "🎅")
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/statuses")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/statuses?with_muted=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp local_and_remote_activities(%{local: local, remote: remote}) do
|
defp local_and_remote_activities(%{local: local, remote: remote}) do
|
||||||
|
|
|
@ -1740,4 +1740,75 @@ test "expires_at is nil for another user" do
|
||||||
|> get("/api/v1/statuses/#{activity.id}")
|
|> get("/api/v1/statuses/#{activity.id}")
|
||||||
|> json_response_and_validate_schema(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "muted reactions" do
|
||||||
|
test "index" do
|
||||||
|
%{conn: conn, user: user} = oauth_access(["read:statuses"])
|
||||||
|
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "test"})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||||
|
User.mute(user, other_user)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/statuses/?ids[]=#{activity.id}")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/statuses/?ids[]=#{activity.id}&with_muted=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
end
|
||||||
|
|
||||||
|
test "show" do
|
||||||
|
# %{conn: conn, user: user, token: token} = oauth_access(["read:statuses"])
|
||||||
|
%{conn: conn, user: user, token: _token} = oauth_access(["read:statuses"])
|
||||||
|
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "test"})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||||
|
User.mute(user, other_user)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/statuses/#{activity.id}")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert %{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => []
|
||||||
|
}
|
||||||
|
} = result
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/statuses/#{activity.id}?with_muted=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert %{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||||
|
}
|
||||||
|
} = result
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -54,6 +54,42 @@ test "the home timeline when the direct messages are excluded", %{user: user, co
|
||||||
assert private_activity.id in status_ids
|
assert private_activity.id in status_ids
|
||||||
refute direct_activity.id in status_ids
|
refute direct_activity.id in status_ids
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "muted emotions", %{user: user, conn: conn} do
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "."})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||||
|
User.mute(user, other_user)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/timelines/home")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/timelines/home?with_muted=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "public" do
|
describe "public" do
|
||||||
|
@ -159,6 +195,48 @@ test "can be filtered by instance", %{conn: conn} do
|
||||||
|
|
||||||
assert length(json_response_and_validate_schema(conn, :ok)) == 1
|
assert length(json_response_and_validate_schema(conn, :ok)) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "muted emotions", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
token = insert(:oauth_token, user: user, scopes: ["read:statuses"])
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> assign(:token, token)
|
||||||
|
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "."})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||||
|
User.mute(user, other_user)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/timelines/public")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/timelines/public?with_muted=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp local_and_remote_activities do
|
defp local_and_remote_activities do
|
||||||
|
@ -428,6 +506,44 @@ test "list timeline does not leak non-public statuses for unfollowed users", %{
|
||||||
|
|
||||||
assert id == to_string(activity_one.id)
|
assert id == to_string(activity_one.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "muted emotions", %{user: user, conn: conn} do
|
||||||
|
user2 = insert(:user)
|
||||||
|
user3 = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user2, %{status: "."})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user3, "🎅")
|
||||||
|
User.mute(user, user3)
|
||||||
|
|
||||||
|
{:ok, list} = Pleroma.List.create("name", user)
|
||||||
|
{:ok, list} = Pleroma.List.follow(list, user2)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/timelines/list/#{list.id}")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/timelines/list/#{list.id}?with_muted=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "hashtag" do
|
describe "hashtag" do
|
||||||
|
@ -476,6 +592,48 @@ test "multi-hashtag timeline", %{conn: conn} do
|
||||||
|
|
||||||
assert [status_none] == json_response_and_validate_schema(all_test, :ok)
|
assert [status_none] == json_response_and_validate_schema(all_test, :ok)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "muted emotions", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
token = insert(:oauth_token, user: user, scopes: ["read:statuses"])
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> assign(:token, token)
|
||||||
|
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "test #2hu"})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||||
|
User.mute(user, other_user)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/timelines/tag/2hu")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/timelines/tag/2hu?with_muted=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] = result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "hashtag timeline handling of :restrict_unauthenticated setting" do
|
describe "hashtag timeline handling of :restrict_unauthenticated setting" do
|
||||||
|
|
|
@ -73,6 +73,50 @@ test "works correctly with badly formatted emojis" do
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "doesn't show reactions from muted and blocked users" do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
third_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "dae cofe??"})
|
||||||
|
|
||||||
|
{:ok, _} = User.mute(user, other_user)
|
||||||
|
{:ok, _} = User.block(other_user, third_user)
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
|
||||||
|
|
||||||
|
activity = Repo.get(Activity, activity.id)
|
||||||
|
status = StatusView.render("show.json", activity: activity)
|
||||||
|
|
||||||
|
assert status[:pleroma][:emoji_reactions] == [
|
||||||
|
%{name: "☕", count: 1, me: false}
|
||||||
|
]
|
||||||
|
|
||||||
|
status = StatusView.render("show.json", activity: activity, for: user)
|
||||||
|
|
||||||
|
assert status[:pleroma][:emoji_reactions] == []
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, third_user, "☕")
|
||||||
|
|
||||||
|
status = StatusView.render("show.json", activity: activity)
|
||||||
|
|
||||||
|
assert status[:pleroma][:emoji_reactions] == [
|
||||||
|
%{name: "☕", count: 2, me: false}
|
||||||
|
]
|
||||||
|
|
||||||
|
status = StatusView.render("show.json", activity: activity, for: user)
|
||||||
|
|
||||||
|
assert status[:pleroma][:emoji_reactions] == [
|
||||||
|
%{name: "☕", count: 1, me: false}
|
||||||
|
]
|
||||||
|
|
||||||
|
status = StatusView.render("show.json", activity: activity, for: other_user)
|
||||||
|
|
||||||
|
assert status[:pleroma][:emoji_reactions] == [
|
||||||
|
%{name: "☕", count: 1, me: true}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
|
test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,48 @@ test "GET /api/v1/pleroma/statuses/:id/reactions", %{conn: conn} do
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "GET /api/v1/pleroma/statuses/:id/reactions?with_muted=true", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
user2 = insert(:user)
|
||||||
|
user3 = insert(:user)
|
||||||
|
|
||||||
|
token = insert(:oauth_token, user: user, scopes: ["read:statuses"])
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user2, "🎅")
|
||||||
|
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user3, "🎅")
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> assign(:token, token)
|
||||||
|
|> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [%{"name" => "🎅", "count" => 2}] = result
|
||||||
|
|
||||||
|
User.mute(user, user3)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> assign(:token, token)
|
||||||
|
|> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [%{"name" => "🎅", "count" => 1}] = result
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> assign(:token, token)
|
||||||
|
|> get("/api/v1/pleroma/statuses/#{activity.id}/reactions?with_muted=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert [%{"name" => "🎅", "count" => 2}] = result
|
||||||
|
end
|
||||||
|
|
||||||
test "GET /api/v1/pleroma/statuses/:id/reactions with :show_reactions disabled", %{conn: conn} do
|
test "GET /api/v1/pleroma/statuses/:id/reactions with :show_reactions disabled", %{conn: conn} do
|
||||||
clear_config([:instance, :show_reactions], false)
|
clear_config([:instance, :show_reactions], false)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue