From fc7ca2ccf4fe593bf47c90f26484cff8b5d99269 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Tue, 18 Mar 2025 15:25:54 +0400 Subject: [PATCH 1/5] Federator: More specific logging for rejections --- lib/pleroma/web/federator.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pleroma/web/federator.ex b/lib/pleroma/web/federator.ex index 58260afa8..676fc5137 100644 --- a/lib/pleroma/web/federator.ex +++ b/lib/pleroma/web/federator.ex @@ -122,6 +122,10 @@ defmodule Pleroma.Web.Federator do Logger.debug("Unhandled actor #{actor}, #{inspect(e)}") {:error, e} + {:reject, reason} = e -> + Logger.debug("Rejected by MRF: #{inspect(reason)}") + {:error, e} + e -> # Just drop those for now Logger.debug(fn -> "Unhandled activity\n" <> Jason.encode!(params, pretty: true) end) From e19ca7606dc25ccb5a68c276dbe95eebe372a677 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Tue, 18 Mar 2025 15:53:27 +0400 Subject: [PATCH 2/5] Transmogrifier: Also accept mitra emoji likes. --- .../web/activity_pub/transmogrifier.ex | 13 ++++- test/fixtures/misskey-custom-emoji-like.json | 54 +++++++++++++++++++ test/fixtures/mitra-custom-emoji-like.json | 46 ++++++++++++++++ .../transmogrifier/like_handling_test.exs | 51 ++++++++++++++++++ 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/misskey-custom-emoji-like.json create mode 100644 test/fixtures/mitra-custom-emoji-like.json diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 1e6ee7dc8..19d036c0d 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -495,12 +495,23 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do defp handle_incoming_normalized( %{ "type" => "Like", - "_misskey_reaction" => reaction + "content" => _ } = data, options ) do data |> Map.put("type", "EmojiReact") + |> handle_incoming_normalized(options) + end + + defp handle_incoming_normalized( + %{ + "type" => "Like", + "_misskey_reaction" => reaction + } = data, + options + ) do + data |> Map.put("content", @misskey_reactions[reaction] || reaction) |> handle_incoming_normalized(options) end diff --git a/test/fixtures/misskey-custom-emoji-like.json b/test/fixtures/misskey-custom-emoji-like.json new file mode 100644 index 000000000..51a825d42 --- /dev/null +++ b/test/fixtures/misskey-custom-emoji-like.json @@ -0,0 +1,54 @@ + { + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + { + "Emoji": "toot:Emoji", + "Hashtag": "as:Hashtag", + "PropertyValue": "schema:PropertyValue", + "_misskey_content": "misskey:_misskey_content", + "_misskey_quote": "misskey:_misskey_quote", + "_misskey_reaction": "misskey:_misskey_reaction", + "_misskey_summary": "misskey:_misskey_summary", + "_misskey_votes": "misskey:_misskey_votes", + "backgroundUrl": "sharkey:backgroundUrl", + "discoverable": "toot:discoverable", + "featured": "toot:featured", + "fedibird": "http://fedibird.com/ns#", + "firefish": "https://joinfirefish.org/ns#", + "isCat": "misskey:isCat", + "listenbrainz": "sharkey:listenbrainz", + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", + "misskey": "https://misskey-hub.net/ns#", + "quoteUri": "fedibird:quoteUri", + "quoteUrl": "as:quoteUrl", + "schema": "http://schema.org#", + "sensitive": "as:sensitive", + "sharkey": "https://joinsharkey.org/ns#", + "speakAsCat": "firefish:speakAsCat", + "toot": "http://joinmastodon.org/ns#", + "value": "schema:value", + "vcard": "http://www.w3.org/2006/vcard/ns#" + } + ], + "_misskey_reaction": ":blobwtfnotlikethis:", + "actor": "https://mai.waifuism.life/users/9otxaeemjqy70001", + "content": ":blobwtfnotlikethis:", + "id": "https://mai.waifuism.life/likes/9q2xifhrdnb0001b", + "object": "https://bungle.online/notes/9q2xi2sy4k", + "tag": [ + { + "icon": { + "mediaType": "image/png", + "type": "Image", + "url": "https://mai.waifuism.life/files/1b0510f2-1fb4-43f5-a399-10053bbd8f0f" + }, + "id": "https://mai.waifuism.life/emojis/blobwtfnotlikethis", + "name": ":blobwtfnotlikethis:", + "type": "Emoji", + "updated": "2024-02-07T02:21:46.497Z" + } + ], + "type": "Like" +} + diff --git a/test/fixtures/mitra-custom-emoji-like.json b/test/fixtures/mitra-custom-emoji-like.json new file mode 100644 index 000000000..4d727febd --- /dev/null +++ b/test/fixtures/mitra-custom-emoji-like.json @@ -0,0 +1,46 @@ +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + "https://w3id.org/security/data-integrity/v1", + { + "Emoji": "toot:Emoji", + "Hashtag": "as:Hashtag", + "sensitive": "as:sensitive", + "toot": "http://joinmastodon.org/ns#" + } + ], + "actor": "https://mitra.social/users/silverpill", + "cc": [], + "content": ":ablobcatheartsqueeze:", + "id": "https://mitra.social/activities/like/0195a89a-a3a0-ead4-3a1c-aa6311397cfd", + "object": "https://framapiaf.org/users/peertube/statuses/114182703352270287", + "proof": { + "created": "2025-03-18T09:34:21.610678375Z", + "cryptosuite": "eddsa-jcs-2022", + "proofPurpose": "assertionMethod", + "proofValue": "z5AvpwkXQGFpTneRVDNeF48Jo9qYG6PgrE5HaPPpQNdNyc31ULMN4Vxd4aFXELo4Rk5Y9hd9nDy254xP8v5uGGWp1", + "type": "DataIntegrityProof", + "verificationMethod": "https://mitra.social/users/silverpill#ed25519-key" + }, + "tag": [ + { + "attributedTo": "https://mitra.social/actor", + "icon": { + "mediaType": "image/png", + "type": "Image", + "url": "https://mitra.social/media/a08e153441b25e512ab1b2e8922f5d8cd928322c8b79958cd48297ac722a4117.png" + }, + "id": "https://mitra.social/objects/emojis/ablobcatheartsqueeze", + "name": ":ablobcatheartsqueeze:", + "type": "Emoji", + "updated": "1970-01-01T00:00:00Z" + } + ], + "to": [ + "https://framapiaf.org/users/peertube", + "https://www.w3.org/ns/activitystreams#Public" + ], + "type": "Like" +} + diff --git a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs index c02f66d77..560f31dac 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs @@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do use Pleroma.DataCase, async: true alias Pleroma.Activity + alias Pleroma.Object alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.CommonAPI @@ -75,4 +76,54 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do assert activity_data["object"] == activity.data["object"] assert activity_data["content"] == "⭐" end + + test "it works for misskey likes with custom emoji" do + user = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{status: "hello"}) + + data = + File.read!("test/fixtures/misskey-custom-emoji-like.json") + |> Jason.decode!() + |> Map.put("object", activity.data["object"]) + + _actor = insert(:user, ap_id: data["actor"], local: false) + + {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data) + + assert activity_data["actor"] == data["actor"] + assert activity_data["type"] == "EmojiReact" + assert activity_data["id"] == data["id"] + assert activity_data["object"] == activity.data["object"] + assert activity_data["content"] == ":blobwtfnotlikethis:" + + assert [["blobwtfnotlikethis", _, _]] = + Object.get_by_ap_id(activity.data["object"]) + |> Object.get_emoji_reactions() + end + + test "it works for mitra likes with custom emoji" do + user = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{status: "hello"}) + + data = + File.read!("test/fixtures/mitra-custom-emoji-like.json") + |> Jason.decode!() + |> Map.put("object", activity.data["object"]) + + _actor = insert(:user, ap_id: data["actor"], local: false) + + {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data) + + assert activity_data["actor"] == data["actor"] + assert activity_data["type"] == "EmojiReact" + assert activity_data["id"] == data["id"] + assert activity_data["object"] == activity.data["object"] + assert activity_data["content"] == ":ablobcatheartsqueeze:" + + assert [["ablobcatheartsqueeze", _, _]] = + Object.get_by_ap_id(activity.data["object"]) + |> Object.get_emoji_reactions() + end end From ef216c922fbd2b96de2f1e99bae8d4ddb3700fdc Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Tue, 18 Mar 2025 15:54:33 +0400 Subject: [PATCH 3/5] Add changelog --- changelog.d/emoji_likes.add | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/emoji_likes.add diff --git a/changelog.d/emoji_likes.add b/changelog.d/emoji_likes.add new file mode 100644 index 000000000..13c91a950 --- /dev/null +++ b/changelog.d/emoji_likes.add @@ -0,0 +1 @@ +Support Mitra-style emoji likes. From 950bf60765cd4eff8f29717dd7a487b8cdf395f8 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Wed, 19 Mar 2025 15:57:08 +0400 Subject: [PATCH 4/5] LikeHandlingTest: Add test for invalid content --- .../transmogrifier/like_handling_test.exs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs index 560f31dac..023c2530f 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs @@ -126,4 +126,20 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do Object.get_by_ap_id(activity.data["object"]) |> Object.get_emoji_reactions() end + + test "it works for likes with wrong content" do + user = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{status: "hello"}) + + data = + File.read!("test/fixtures/mitra-custom-emoji-like.json") + |> Jason.decode!() + |> Map.put("object", activity.data["object"]) + |> Map.put("content", 1) + + _actor = insert(:user, ap_id: data["actor"], local: false) + + assert {:error, _} = Transmogrifier.handle_incoming(data) + end end From f9bff8f5e5408e0b8eee9a7b0019e4c92c54e1f9 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Wed, 19 Mar 2025 16:00:27 +0400 Subject: [PATCH 5/5] Transmogrifier: Keep likes as likes if the content is obviously wrong --- lib/pleroma/web/activity_pub/transmogrifier.ex | 5 +++-- .../web/activity_pub/transmogrifier/like_handling_test.exs | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 19d036c0d..6517f5eff 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -495,10 +495,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do defp handle_incoming_normalized( %{ "type" => "Like", - "content" => _ + "content" => content } = data, options - ) do + ) + when is_binary(content) do data |> Map.put("type", "EmojiReact") |> handle_incoming_normalized(options) diff --git a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs index 023c2530f..fc04c1391 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs @@ -140,6 +140,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do _actor = insert(:user, ap_id: data["actor"], local: false) - assert {:error, _} = Transmogrifier.handle_incoming(data) + assert {:ok, activity} = Transmogrifier.handle_incoming(data) + assert activity.data["type"] == "Like" end end