commit: d3660b24d37862bb58cf309c582cfe7432fd7bb6
parent 572363793f27895903a8c156fd614ec5c7493cd1
Author: rinpatch <rin@patch.cx>
Date: Mon, 22 Mar 2021 20:07:07 +0300
Copy emoji in the subject from parent post
Sometimes people put emoji in the subject, which results in the subject
looking broken if someone replies to it from a server that does not
have the said emoji under the same shortcode. This patch solves the problem
by extending the emoji set available in the summary to that of the parent
post.
Diffstat:
4 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex
@@ -5,6 +5,7 @@
defmodule Pleroma.Web.CommonAPI.ActivityDraft do
alias Pleroma.Activity
alias Pleroma.Conversation.Participation
+ alias Pleroma.Object
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils
@@ -186,6 +187,32 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
defp object(draft) do
emoji = Map.merge(Pleroma.Emoji.Formatter.get_emoji_map(draft.full_payload), draft.emoji)
+ # Sometimes people create posts with subject containing emoji,
+ # since subjects are usually copied this will result in a broken
+ # subject when someone replies from an instance that does not have
+ # the emoji or has it under different shortcode. This is an attempt
+ # to mitigate this by copying emoji from inReplyTo if they are present
+ # in the subject.
+ summary_emoji =
+ with %Activity{} <- draft.in_reply_to,
+ %Object{data: %{"tag" => [_ | _] = tag}} <- Object.normalize(draft.in_reply_to) do
+ Enum.reduce(tag, %{}, fn
+ %{"type" => "Emoji", "name" => name, "icon" => %{"url" => url}}, acc ->
+ if String.contains?(draft.summary, name) do
+ Map.put(acc, name, url)
+ else
+ acc
+ end
+
+ _, acc ->
+ acc
+ end)
+ else
+ _ -> %{}
+ end
+
+ emoji = Map.merge(emoji, summary_emoji)
+
object =
Utils.make_note_data(draft)
|> Map.put("emoji", emoji)
diff --git a/test/fixtures/tesla_mock/emoji-in-summary.json b/test/fixtures/tesla_mock/emoji-in-summary.json
@@ -0,0 +1,49 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://patch.cx/schemas/litepub-0.1.jsonld",
+ {
+ "@language": "und"
+ }
+ ],
+ "actor": "https://patch.cx/users/rin",
+ "attachment": [],
+ "attributedTo": "https://patch.cx/users/rin",
+ "cc": [
+ "https://patch.cx/users/rin/followers"
+ ],
+ "content": ":joker_disapprove: <br><br>just grabbing a test fixture, nevermind me",
+ "context": "https://patch.cx/contexts/2c3ce4b4-18b1-4b1a-8965-3932027b5326",
+ "conversation": "https://patch.cx/contexts/2c3ce4b4-18b1-4b1a-8965-3932027b5326",
+ "id": "https://patch.cx/objects/a399c28e-c821-4820-bc3e-4afeb044c16f",
+ "published": "2021-03-22T16:54:46.461939Z",
+ "sensitive": null,
+ "source": ":joker_disapprove: \r\n\r\njust grabbing a test fixture, nevermind me",
+ "summary": ":joker_smile: ",
+ "tag": [
+ {
+ "icon": {
+ "type": "Image",
+ "url": "https://patch.cx/emoji/custom/joker_disapprove.png"
+ },
+ "id": "https://patch.cx/emoji/custom/joker_disapprove.png",
+ "name": ":joker_disapprove:",
+ "type": "Emoji",
+ "updated": "1970-01-01T00:00:00Z"
+ },
+ {
+ "icon": {
+ "type": "Image",
+ "url": "https://patch.cx/emoji/custom/joker_smile.png"
+ },
+ "id": "https://patch.cx/emoji/custom/joker_smile.png",
+ "name": ":joker_smile:",
+ "type": "Emoji",
+ "updated": "1970-01-01T00:00:00Z"
+ }
+ ],
+ "to": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "type": "Note"
+}
diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs
@@ -25,6 +25,11 @@ defmodule Pleroma.Web.CommonAPITest do
require Pleroma.Constants
+ setup_all do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ :ok
+ end
+
setup do: clear_config([:instance, :safe_dm_mentions])
setup do: clear_config([:instance, :limit])
setup do: clear_config([:instance, :max_pinned_statuses])
@@ -517,6 +522,27 @@ defmodule Pleroma.Web.CommonAPITest do
assert url == "#{Pleroma.Web.base_url()}/emoji/blank.png"
end
+ test "it copies emoji from the subject of the parent post" do
+ %Object{} =
+ object =
+ Object.normalize("https://patch.cx/objects/a399c28e-c821-4820-bc3e-4afeb044c16f",
+ fetch: true
+ )
+
+ activity = Activity.get_create_by_object_ap_id(object.data["id"])
+ user = insert(:user)
+
+ {:ok, reply_activity} =
+ CommonAPI.post(user, %{
+ in_reply_to_id: activity.id,
+ status: ":joker_disapprove:",
+ spoiler_text: ":joker_smile:"
+ })
+
+ assert Object.normalize(reply_activity).data["emoji"][":joker_smile:"]
+ refute Object.normalize(reply_activity).data["emoji"][":joker_disapprove:"]
+ end
+
test "deactivated users can't post" do
user = insert(:user, is_active: false)
assert {:error, _} = CommonAPI.post(user, %{status: "ye"})
diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex
@@ -1278,6 +1278,15 @@ defmodule HttpRequestMock do
}}
end
+ def get("https://patch.cx/objects/a399c28e-c821-4820-bc3e-4afeb044c16f", _, _, _) do
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/emoji-in-summary.json"),
+ headers: activitypub_object_headers()
+ }}
+ end
+
def get(url, query, body, headers) do
{:error,
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{