Merge branch 'tusooa/3073-react-legacy' into 'develop'

Fix emoji reactions for legacy 2-tuple formats

Closes #3073

See merge request pleroma/pleroma!3861
This commit is contained in:
Haelwenn 2023-03-27 10:05:47 +00:00
commit 4f7c11b281
8 changed files with 147 additions and 14 deletions

View File

@ -425,4 +425,30 @@ def object_data_hashtags(%{"tag" => tags}) when is_list(tags) do
end end
def object_data_hashtags(_), do: [] def object_data_hashtags(_), do: []
def get_emoji_reactions(object) do
reactions = object.data["reactions"]
if is_list(reactions) or is_map(reactions) do
reactions
|> Enum.map(fn
[_emoji, users, _maybe_url] = item when is_list(users) ->
item
[emoji, users] when is_list(users) ->
[emoji, users, nil]
# This case is here to process the Map situation, which will happen
# only with the legacy two-value format.
{emoji, users} when is_list(users) ->
[emoji, users, nil]
_ ->
nil
end)
|> Enum.reject(&is_nil/1)
else
[]
end
end
end end

View File

@ -408,11 +408,7 @@ def remove_emoji_reaction_from_object(
end end
def get_cached_emoji_reactions(object) do def get_cached_emoji_reactions(object) do
if is_list(object.data["reactions"]) do Object.get_emoji_reactions(object)
object.data["reactions"]
else
[]
end
end end
@spec add_like_to_object(Activity.t(), Object.t()) :: @spec add_like_to_object(Activity.t(), Object.t()) ::

View File

@ -334,8 +334,8 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
end end
emoji_reactions = emoji_reactions =
object.data object
|> Map.get("reactions", []) |> Object.get_emoji_reactions()
|> EmojiReactionController.filter_allowed_users( |> EmojiReactionController.filter_allowed_users(
opts[:for], opts[:for],
Map.get(opts, :with_muted, false) Map.get(opts, :with_muted, false)

View File

@ -28,8 +28,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
def index(%{assigns: %{user: user}} = conn, %{id: activity_id} = params) do def index(%{assigns: %{user: user}} = conn, %{id: activity_id} = params) do
with true <- Pleroma.Config.get([:instance, :show_reactions]), with true <- Pleroma.Config.get([:instance, :show_reactions]),
%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{} = object <- Object.normalize(activity, fetch: false),
Object.normalize(activity, fetch: false) do reactions <- Object.get_emoji_reactions(object) do
reactions = reactions =
reactions reactions
|> filter(params) |> filter(params)
@ -60,9 +60,6 @@ def filter_allowed_users(reactions, user, with_muted) do
reactions reactions
|> Stream.map(fn |> Stream.map(fn
[emoji, users, url] when is_list(users) -> filter_emoji.(emoji, users, url) [emoji, users, url] when is_list(users) -> filter_emoji.(emoji, users, url)
{emoji, users, url} when is_list(users) -> filter_emoji.(emoji, users, url)
{emoji, users} when is_list(users) -> filter_emoji.(emoji, users, nil)
_ -> nil
end) end)
|> Stream.reject(&is_nil/1) |> Stream.reject(&is_nil/1)
end end

View File

@ -444,4 +444,42 @@ test "Hashtag records are created with Object record and updated on its change"
Enum.sort_by(object.hashtags, & &1.name) Enum.sort_by(object.hashtags, & &1.name)
end end
end end
describe "get_emoji_reactions/1" do
test "3-tuple current format" do
object = %Object{
data: %{
"reactions" => [
["x", ["https://some/user"], "https://some/emoji"]
]
}
}
assert Object.get_emoji_reactions(object) == object.data["reactions"]
end
test "2-tuple legacy format" do
object = %Object{
data: %{
"reactions" => [
["x", ["https://some/user"]]
]
}
}
assert Object.get_emoji_reactions(object) == [["x", ["https://some/user"], nil]]
end
test "Map format" do
object = %Object{
data: %{
"reactions" => %{
"x" => ["https://some/user"]
}
}
}
assert Object.get_emoji_reactions(object) == [["x", ["https://some/user"], nil]]
end
end
end end

View File

@ -587,15 +587,38 @@ test "removes actor from announcements" do
end end
describe "get_cached_emoji_reactions/1" do describe "get_cached_emoji_reactions/1" do
test "returns the data or an emtpy list" do test "returns the normalized data or an emtpy list" do
object = insert(:note) object = insert(:note)
assert Utils.get_cached_emoji_reactions(object) == [] assert Utils.get_cached_emoji_reactions(object) == []
object = insert(:note, data: %{"reactions" => [["x", ["lain"]]]}) object = insert(:note, data: %{"reactions" => [["x", ["lain"]]]})
assert Utils.get_cached_emoji_reactions(object) == [["x", ["lain"]]] assert Utils.get_cached_emoji_reactions(object) == [["x", ["lain"], nil]]
object = insert(:note, data: %{"reactions" => %{}}) object = insert(:note, data: %{"reactions" => %{}})
assert Utils.get_cached_emoji_reactions(object) == [] assert Utils.get_cached_emoji_reactions(object) == []
end end
end end
describe "add_emoji_reaction_to_object/1" do
test "works with legacy 2-tuple format" do
user = insert(:user)
other_user = insert(:user)
third_user = insert(:user)
note =
insert(:note,
user: user,
data: %{
"reactions" => [["😿", [other_user.ap_id]]]
}
)
_activity = insert(:note_activity, user: user, note: note)
Utils.add_emoji_reaction_to_object(
%Activity{data: %{"content" => "😿", "actor" => third_user.ap_id}},
note
)
end
end
end end

View File

@ -74,6 +74,27 @@ test "has an emoji reaction list" do
] ]
end end
test "works with legacy-formatted reactions" do
user = insert(:user)
other_user = insert(:user)
note =
insert(:note,
user: user,
data: %{
"reactions" => [["😿", [other_user.ap_id]]]
}
)
activity = insert(:note_activity, user: user, note: note)
status = StatusView.render("show.json", activity: activity, for: user)
assert status[:pleroma][:emoji_reactions] == [
%{name: "😿", count: 1, me: false, url: nil, account_ids: [other_user.id]}
]
end
test "works correctly with badly formatted emojis" do test "works correctly with badly formatted emojis" do
user = insert(:user) user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{status: "yo"}) {:ok, activity} = CommonAPI.post(user, %{status: "yo"})

View File

@ -245,6 +245,38 @@ test "GET /api/v1/pleroma/statuses/:id/reactions", %{conn: conn} do
result result
end end
test "GET /api/v1/pleroma/statuses/:id/reactions with legacy format", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
note =
insert(:note,
user: user,
data: %{
"reactions" => [["😿", [other_user.ap_id]]]
}
)
activity = insert(:note_activity, user: user, note: note)
result =
conn
|> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
|> json_response_and_validate_schema(200)
other_user_id = other_user.id
assert [
%{
"name" => "😿",
"count" => 1,
"me" => false,
"url" => nil,
"accounts" => [%{"id" => ^other_user_id}]
}
] = result
end
test "GET /api/v1/pleroma/statuses/:id/reactions?with_muted=true", %{conn: conn} do test "GET /api/v1/pleroma/statuses/:id/reactions?with_muted=true", %{conn: conn} do
user = insert(:user) user = insert(:user)
user2 = insert(:user) user2 = insert(:user)