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.
This commit is contained in:
rinpatch 2021-03-22 20:07:07 +03:00
parent 572363793f
commit d3660b24d3
4 changed files with 111 additions and 0 deletions

View file

@ -5,6 +5,7 @@
defmodule Pleroma.Web.CommonAPI.ActivityDraft do defmodule Pleroma.Web.CommonAPI.ActivityDraft do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Conversation.Participation alias Pleroma.Conversation.Participation
alias Pleroma.Object
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.CommonAPI.Utils
@ -186,6 +187,32 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
defp object(draft) do defp object(draft) do
emoji = Map.merge(Pleroma.Emoji.Formatter.get_emoji_map(draft.full_payload), draft.emoji) 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 = object =
Utils.make_note_data(draft) Utils.make_note_data(draft)
|> Map.put("emoji", emoji) |> Map.put("emoji", emoji)

View file

@ -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"
}

View file

@ -25,6 +25,11 @@ defmodule Pleroma.Web.CommonAPITest do
require Pleroma.Constants 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, :safe_dm_mentions])
setup do: clear_config([:instance, :limit]) setup do: clear_config([:instance, :limit])
setup do: clear_config([:instance, :max_pinned_statuses]) 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" assert url == "#{Pleroma.Web.base_url()}/emoji/blank.png"
end 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 test "deactivated users can't post" do
user = insert(:user, is_active: false) user = insert(:user, is_active: false)
assert {:error, _} = CommonAPI.post(user, %{status: "ye"}) assert {:error, _} = CommonAPI.post(user, %{status: "ye"})

View file

@ -1278,6 +1278,15 @@ defmodule HttpRequestMock do
}} }}
end 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 def get(url, query, body, headers) do
{:error, {:error,
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{ "Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{