commit: 254b31bf1caee1f3ad1407e477ea7c304c8c8f3b
parent 81960dccf298fa8f6913f4551b7868c8b75950de
Author: lain <lain@soykaf.club>
Date: Thu, 20 Mar 2025 09:12:09 +0000
Merge branch 'more-emoji-likes' into 'develop'
More emoji likes
Closes #3364
See merge request pleroma/pleroma!4342
Diffstat:
6 files changed, 186 insertions(+), 1 deletion(-)
diff --git a/changelog.d/emoji_likes.add b/changelog.d/emoji_likes.add
@@ -0,0 +1 @@
+Support Mitra-style emoji likes.
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -495,12 +495,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
defp handle_incoming_normalized(
%{
"type" => "Like",
+ "content" => content
+ } = data,
+ options
+ )
+ when is_binary(content) 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("type", "EmojiReact")
|> Map.put("content", @misskey_reactions[reaction] || reaction)
|> handle_incoming_normalized(options)
end
diff --git 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)
diff --git a/test/fixtures/misskey-custom-emoji-like.json 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
@@ -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
@@ -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,71 @@ 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
+
+ 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 {:ok, activity} = Transmogrifier.handle_incoming(data)
+ assert activity.data["type"] == "Like"
+ end
end