From 439b192829424aa897cda406180b58aa40f3b9b8 Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Thu, 25 Aug 2022 16:45:31 +0100 Subject: [PATCH 1/5] Rearrange custom emoji processing --- lib/pleroma/web/activity_pub/builder.ex | 63 +++++++++++++++---------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index 97ceaf08e..1dcd60da0 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -55,37 +55,50 @@ def follow(follower, followed) do {:ok, data, []} end + defp unicode_emoji_react(object, data, emoji) do + data + |> Map.put("content", emoji) + |> Map.put("type", "EmojiReact") + end + + defp custom_emoji_react(object, data, emoji) do + if String.contains?("@") do + # Attempt to resolve remote emoji + [emoji_code, instance] = String.split(emoji, "@") + else + with %{} = emojo <- Emoji.get(emoji) do + path = emojo |> Map.get(:file) + url = "#{Endpoint.url()}#{path}" + + data + |> Map.put("content", emoji) + |> Map.put("type", "EmojiReact") + |> Map.put("tag", [ + %{} + |> Map.put("id", url) + |> Map.put("type", "Emoji") + |> Map.put("name", emojo.code) + |> Map.put( + "icon", + %{} + |> Map.put("type", "Image") + |> Map.put("url", url) + ) + ]) + else + _ -> {:error, "Emoji does not exist"} + end + end + end + @spec emoji_react(User.t(), Object.t(), String.t()) :: {:ok, map(), keyword()} def emoji_react(actor, object, emoji) do with {:ok, data, meta} <- object_action(actor, object) do data = if Emoji.is_unicode_emoji?(emoji) do - data - |> Map.put("content", emoji) - |> Map.put("type", "EmojiReact") + unicode_emoji_react(object, data, emoji) else - with %{} = emojo <- Emoji.get(emoji) do - path = emojo |> Map.get(:file) - url = "#{Endpoint.url()}#{path}" - - data - |> Map.put("content", emoji) - |> Map.put("type", "EmojiReact") - |> Map.put("tag", [ - %{} - |> Map.put("id", url) - |> Map.put("type", "Emoji") - |> Map.put("name", emojo.code) - |> Map.put( - "icon", - %{} - |> Map.put("type", "Image") - |> Map.put("url", url) - ) - ]) - else - _ -> {:error, "Emoji does not exist"} - end + custom_emoji_react(object, data, emoji) end {:ok, data, meta} -- 2.43.0 From e40d45a585aa13ccf5de47819a2120d32f8833da Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Sat, 27 Aug 2022 11:13:54 +0100 Subject: [PATCH 2/5] allow reacting with remote custom emoji --- lib/pleroma/web/activity_pub/builder.ex | 81 ++++++++++++------- .../emoji_react_validator.ex | 2 +- lib/pleroma/web/common_api.ex | 4 +- .../web/mastodon_api/views/status_view.ex | 2 +- .../pleroma_api/views/emoji_reaction_view.ex | 14 +++- 5 files changed, 72 insertions(+), 31 deletions(-) diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index 1dcd60da0..67bd461a2 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -55,39 +55,66 @@ def follow(follower, followed) do {:ok, data, []} end - defp unicode_emoji_react(object, data, emoji) do + defp unicode_emoji_react(_object, data, emoji) do data |> Map.put("content", emoji) |> Map.put("type", "EmojiReact") end - defp custom_emoji_react(object, data, emoji) do - if String.contains?("@") do - # Attempt to resolve remote emoji - [emoji_code, instance] = String.split(emoji, "@") - else - with %{} = emojo <- Emoji.get(emoji) do - path = emojo |> Map.get(:file) - url = "#{Endpoint.url()}#{path}" + defp add_emoji_content(data, emoji, url) do + data + |> Map.put("content", Emoji.maybe_quote(emoji)) + |> Map.put("type", "EmojiReact") + |> Map.put("tag", [ + %{} + |> Map.put("id", url) + |> Map.put("type", "Emoji") + |> Map.put("name", Emoji.maybe_quote(emoji)) + |> Map.put( + "icon", + %{} + |> Map.put("type", "Image") + |> Map.put("url", url) + ) + ]) + end - data - |> Map.put("content", emoji) - |> Map.put("type", "EmojiReact") - |> Map.put("tag", [ - %{} - |> Map.put("id", url) - |> Map.put("type", "Emoji") - |> Map.put("name", emojo.code) - |> Map.put( - "icon", - %{} - |> Map.put("type", "Image") - |> Map.put("url", url) - ) - ]) - else - _ -> {:error, "Emoji does not exist"} - end + defp remote_custom_emoji_react(object, data, emoji) do + [emoji_code, instance] = String.split(Emoji.stripped_name(emoji), "@") + %{data: %{"reactions" => existing_reactions}} = object + + matching_reaction = + Enum.find( + existing_reactions, + fn [name, _, url] -> + url = URI.parse(url) + url.host == instance && name == emoji_code + end + ) + + if matching_reaction do + [name, _, url] = matching_reaction + add_emoji_content(data, name, url) + else + {:error, "Could not react"} + end + end + + defp local_custom_emoji_react(data, emoji) do + with %{} = emojo <- Emoji.get(emoji) do + path = emojo |> Map.get(:file) + url = "#{Endpoint.url()}#{path}" + add_emoji_content(data, emojo.code, url) + else + _ -> {:error, "Emoji does not exist"} + end + end + + defp custom_emoji_react(object, data, emoji) do + if String.contains?(emoji, "@") do + remote_custom_emoji_react(object, data, emoji) + else + local_custom_emoji_react(data, emoji) end end diff --git a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex index 306a57a93..6109a0355 100644 --- a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex @@ -13,7 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations @primary_key false - @emoji_regex ~r/:[A-Za-z0-9_-]+:/ + @emoji_regex ~r/:[A-Za-z0-9_-]+(@.+)?:/ embedded_schema do quote do diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex index bc5e26cf7..9158605d4 100644 --- a/lib/pleroma/web/common_api.ex +++ b/lib/pleroma/web/common_api.ex @@ -209,7 +209,9 @@ def react_with_emoji(id, user, emoji) do {:ok, activity, _} <- Pipeline.common_pipeline(emoji_react, local: true) do {:ok, activity} else - _ -> {:error, dgettext("errors", "Could not add reaction emoji")} + e -> + IO.inspect(e) + {:error, dgettext("errors", "Could not add reaction emoji")} end end diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index d838c4673..0d2571ab8 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -587,7 +587,7 @@ defp pin_data(%Object{data: %{"id" => object_id}}, %User{pinned_objects: pinned_ defp build_emoji_map(emoji, users, url, current_user) do %{ - name: emoji, + name: Pleroma.Web.PleromaAPI.EmojiReactionView.emoji_name(emoji, url), count: length(users), url: MediaProxy.url(url), me: !!(current_user && current_user.ap_id in users), diff --git a/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex index 9993480db..9186de9e7 100644 --- a/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex +++ b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex @@ -8,6 +8,18 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionView do alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MediaProxy + def emoji_name(emoji, nil), do: emoji + + def emoji_name(emoji, url) do + url = URI.parse(url) + + if url.host == Endpoint.host() do + emoji + else + "#{emoji}@#{url.host}" + end + end + def render("index.json", %{emoji_reactions: emoji_reactions} = opts) do render_many(emoji_reactions, __MODULE__, "show.json", opts) end @@ -16,7 +28,7 @@ def render("show.json", %{emoji_reaction: {emoji, user_ap_ids, url}, user: user} users = fetch_users(user_ap_ids) %{ - name: emoji, + name: emoji_name(emoji, url), count: length(users), accounts: render(AccountView, "index.json", users: users, for: user), url: MediaProxy.url(url), -- 2.43.0 From 8de9033e18f273f9b61d7dadd7681f111b39f727 Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Sat, 27 Aug 2022 16:53:09 +0100 Subject: [PATCH 3/5] ensure emoji reactions are fully-qualified --- lib/pleroma/web/activity_pub/utils.ex | 10 ++-------- lib/pleroma/web/common_api.ex | 3 +-- .../controllers/emoji_reaction_controller.ex | 10 +++++++++- .../web/pleroma_api/views/emoji_reaction_view.ex | 2 +- .../controllers/emoji_reaction_controller_test.exs | 9 +++++---- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 5e5df4888..78139e5fd 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -329,7 +329,7 @@ def add_emoji_reaction_to_object( object ) do reactions = get_cached_emoji_reactions(object) - emoji = stripped_emoji_name(emoji) + emoji = Pleroma.Emoji.stripped_name(emoji) url = emoji_url(emoji, activity) new_reactions = @@ -356,12 +356,6 @@ def add_emoji_reaction_to_object( update_element_in_object("reaction", new_reactions, object, count) end - defp stripped_emoji_name(name) do - name - |> String.replace_leading(":", "") - |> String.replace_trailing(":", "") - end - defp emoji_url( name, %Activity{ @@ -384,7 +378,7 @@ def remove_emoji_reaction_from_object( %Activity{data: %{"content" => emoji, "actor" => actor}} = activity, object ) do - emoji = stripped_emoji_name(emoji) + emoji = Pleroma.Emoji.stripped_name(emoji) reactions = get_cached_emoji_reactions(object) url = emoji_url(emoji, activity) diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex index 9158605d4..23d353dc2 100644 --- a/lib/pleroma/web/common_api.ex +++ b/lib/pleroma/web/common_api.ex @@ -209,8 +209,7 @@ def react_with_emoji(id, user, emoji) do {:ok, activity, _} <- Pipeline.common_pipeline(emoji_react, local: true) do {:ok, activity} else - e -> - IO.inspect(e) + _ -> {:error, dgettext("errors", "Could not add reaction emoji")} end end diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex index 91658587a..0933363a6 100644 --- a/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex @@ -74,7 +74,10 @@ defp filter(reactions, %{emoji: emoji}) when is_binary(emoji) do defp filter(reactions, _), do: reactions def create(%{assigns: %{user: user}} = conn, %{id: activity_id, emoji: emoji}) do - emoji = Pleroma.Emoji.maybe_quote(emoji) + emoji = + emoji + |> Pleroma.Emoji.fully_qualify_emoji() + |> Pleroma.Emoji.maybe_quote() with {:ok, _activity} <- CommonAPI.react_with_emoji(activity_id, user, emoji) do activity = Activity.get_by_id(activity_id) @@ -86,6 +89,11 @@ def create(%{assigns: %{user: user}} = conn, %{id: activity_id, emoji: emoji}) d end def delete(%{assigns: %{user: user}} = conn, %{id: activity_id, emoji: emoji}) do + emoji = + emoji + |> Pleroma.Emoji.fully_qualify_emoji() + |> Pleroma.Emoji.maybe_quote() + with {:ok, _activity} <- CommonAPI.unreact_with_emoji(activity_id, user, emoji) do activity = Activity.get_by_id(activity_id) diff --git a/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex index 9186de9e7..4335228b6 100644 --- a/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex +++ b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex @@ -13,7 +13,7 @@ def emoji_name(emoji, nil), do: emoji def emoji_name(emoji, url) do url = URI.parse(url) - if url.host == Endpoint.host() do + if url.host == Pleroma.Web.Endpoint.host() do emoji else "#{emoji}@#{url.host}" diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs index 4898179e6..8ff2ef51f 100644 --- a/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs @@ -17,22 +17,23 @@ test "PUT /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"}) + note = insert(:note, user: user, reactions: %{reactions: %{"👍" => [other_user.ap_id]}}) + activity = insert(:note_activity, note: note, user: user) result = conn |> assign(:user, other_user) |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"])) - |> put("/api/v1/pleroma/statuses/#{activity.id}/reactions/☕") + |> put("/api/v1/pleroma/statuses/#{activity.id}/reactions/\u26A0") |> json_response_and_validate_schema(200) # We return the status, but this our implementation detail. assert %{"id" => id} = result assert to_string(activity.id) == id - + IO.inspect(result) assert result["pleroma"]["emoji_reactions"] == [ %{ - "name" => "☕", + "name" => "\u26A0\uFE0F", "count" => 1, "me" => true, "url" => nil, -- 2.43.0 From f1a7123fdec3f51a397f3c3ef4a9b243f7255fb1 Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Sun, 4 Sep 2022 20:00:53 +0100 Subject: [PATCH 4/5] add tests for remote custom emoji --- lib/pleroma/web/activity_pub/builder.ex | 11 ++++- .../emoji_reaction_controller_test.exs | 40 +++++++++++++++++-- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index 67bd461a2..71ccbdef5 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -79,9 +79,12 @@ defp add_emoji_content(data, emoji, url) do ]) end - defp remote_custom_emoji_react(object, data, emoji) do + defp remote_custom_emoji_react( + %{data: %{"reactions" => existing_reactions}} = object, + data, + emoji + ) do [emoji_code, instance] = String.split(Emoji.stripped_name(emoji), "@") - %{data: %{"reactions" => existing_reactions}} = object matching_reaction = Enum.find( @@ -100,6 +103,10 @@ defp remote_custom_emoji_react(object, data, emoji) do end end + defp remote_custom_emoji_react(_object, data, emoji) do + {:error, "Could not react"} + end + defp local_custom_emoji_react(data, emoji) do with %{} = emojo <- Emoji.get(emoji) do path = emojo |> Map.get(:file) diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs index 8ff2ef51f..9fb683262 100644 --- a/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs @@ -17,7 +17,7 @@ test "PUT /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do user = insert(:user) other_user = insert(:user) - note = insert(:note, user: user, reactions: %{reactions: %{"👍" => [other_user.ap_id]}}) + note = insert(:note, user: user, data: %{"reactions" => [["👍", [other_user.ap_id], nil]]}) activity = insert(:note_activity, note: note, user: user) result = @@ -27,11 +27,17 @@ test "PUT /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do |> put("/api/v1/pleroma/statuses/#{activity.id}/reactions/\u26A0") |> json_response_and_validate_schema(200) - # We return the status, but this our implementation detail. assert %{"id" => id} = result assert to_string(activity.id) == id - IO.inspect(result) + assert result["pleroma"]["emoji_reactions"] == [ + %{ + "name" => "👍", + "count" => 1, + "me" => true, + "url" => nil, + "account_ids" => [other_user.id] + }, %{ "name" => "\u26A0\uFE0F", "count" => 1, @@ -44,6 +50,7 @@ test "PUT /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"}) ObanHelpers.perform_all() + # Reacting with a custom emoji result = conn @@ -52,7 +59,6 @@ test "PUT /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do |> put("/api/v1/pleroma/statuses/#{activity.id}/reactions/:dinosaur:") |> json_response_and_validate_schema(200) - # We return the status, but this our implementation detail. assert %{"id" => id} = result assert to_string(activity.id) == id @@ -66,6 +72,32 @@ test "PUT /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do } ] + # Reacting with a remote emoji + note = + insert(:note, + user: user, + data: %{"reactions" => [["wow", [other_user.ap_id], "https://remote/emoji/wow"]]} + ) + + activity = insert(:note_activity, note: note, user: user) + + result = + conn + |> assign(:user, user) + |> assign(:token, insert(:oauth_token, user: user, scopes: ["write:statuses"])) + |> put("/api/v1/pleroma/statuses/#{activity.id}/reactions/:wow@remote:") + |> json_response(200) + + assert result["pleroma"]["emoji_reactions"] == [ + %{ + "name" => "wow@remote", + "count" => 2, + "me" => true, + "url" => "https://remote/emoji/wow", + "account_ids" => [user.id, other_user.id] + } + ] + # Reacting with a non-emoji assert conn |> assign(:user, other_user) -- 2.43.0 From ea1b1f4a6ca99d8b8e6294cdcff119e9da09f33a Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Sun, 4 Sep 2022 21:05:13 +0100 Subject: [PATCH 5/5] add tests for removing emoji --- lib/pleroma/web/activity_pub/utils.ex | 22 +++++++- .../emoji_reaction_controller_test.exs | 55 ++++++++++++++++++- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index b15be8b22..008aec475 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -507,19 +507,37 @@ def fetch_latest_undo(%User{ap_id: ap_id}) do def get_latest_reaction(internal_activity_id, %{ap_id: ap_id}, emoji) do %{data: %{"object" => object_ap_id}} = Activity.get_by_id(internal_activity_id) - emoji = Pleroma.Emoji.maybe_quote(emoji) "EmojiReact" |> Activity.Queries.by_type() |> where(actor: ^ap_id) - |> where([activity], fragment("?->>'content' = ?", activity.data, ^emoji)) + |> custom_emoji_discriminator(emoji) |> Activity.Queries.by_object_id(object_ap_id) |> order_by([activity], fragment("? desc nulls last", activity.id)) |> limit(1) |> Repo.one() end + defp custom_emoji_discriminator(query, emoji) do + if String.contains?(emoji, "@") do + stripped = Pleroma.Emoji.stripped_name(emoji) + [name, domain] = String.split(stripped, "@") + domain_pattern = "%" <> domain <> "%" + emoji_pattern = Pleroma.Emoji.maybe_quote(name) + + query + |> where([activity], fragment("?->>'content' = ? + AND EXISTS ( + SELECT FROM jsonb_array_elements(?->'tag') elem + WHERE elem->>'id' ILIKE ? + )", activity.data, ^emoji_pattern, activity.data, ^domain_pattern)) + else + query + |> where([activity], fragment("?->>'content' = ?", activity.data, ^emoji)) + end + end + #### Announce-related helpers @doc """ diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs index 9fb683262..6864b37cb 100644 --- a/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/emoji_reaction_controller_test.exs @@ -98,6 +98,20 @@ test "PUT /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do } ] + # Reacting with a remote custom emoji that hasn't been reacted with yet + note = + insert(:note, + user: user + ) + + activity = insert(:note_activity, note: note, user: user) + + assert conn + |> assign(:user, user) + |> assign(:token, insert(:oauth_token, user: user, scopes: ["write:statuses"])) + |> put("/api/v1/pleroma/statuses/#{activity.id}/reactions/:wow@remote:") + |> json_response(400) + # Reacting with a non-emoji assert conn |> assign(:user, other_user) @@ -110,10 +124,22 @@ test "DELETE /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"}) + note = + insert(:note, + user: user, + data: %{"reactions" => [["wow", [user.ap_id], "https://remote/emoji/wow"]]} + ) + + activity = insert(:note_activity, note: note, user: user) + + ObanHelpers.perform_all() + {:ok, _reaction_activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕") {:ok, _reaction_activity} = CommonAPI.react_with_emoji(activity.id, other_user, ":dinosaur:") + {:ok, _reaction_activity} = + CommonAPI.react_with_emoji(activity.id, other_user, ":wow@remote:") + ObanHelpers.perform_all() result = @@ -140,7 +166,32 @@ test "DELETE /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do object = Object.get_by_ap_id(activity.data["object"]) - assert object.data["reaction_count"] == 0 + assert object.data["reaction_count"] == 2 + + # Remove custom remote emoji + result = + conn + |> assign(:user, other_user) + |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"])) + |> delete("/api/v1/pleroma/statuses/#{activity.id}/reactions/:wow@remote:") + |> json_response(200) + + assert result["pleroma"]["emoji_reactions"] == [ + %{ + "name" => "wow@remote", + "count" => 1, + "me" => false, + "url" => "https://remote/emoji/wow", + "account_ids" => [user.id] + } + ] + + # Remove custom remote emoji that hasn't been reacted with yet + assert conn + |> assign(:user, other_user) + |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"])) + |> delete("/api/v1/pleroma/statuses/#{activity.id}/reactions/:zoop@remote:") + |> json_response(400) end test "GET /api/v1/pleroma/statuses/:id/reactions", %{conn: conn} do -- 2.43.0