From ac3426cbca19c7ca39ab927afc79f27865d32061 Mon Sep 17 00:00:00 2001
From: Alex Gleason
Date: Fri, 28 Jan 2022 14:06:32 -0600
Subject: [PATCH 1/3] Transmogrifier: federate quotes with _misskey_quote field
---
lib/pleroma/web/activity_pub/transmogrifier.ex | 9 +++++++++
priv/static/schemas/litepub-0.1.jsonld | 2 ++
test/pleroma/web/activity_pub/transmogrifier_test.exs | 4 ++++
3 files changed, 15 insertions(+)
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 9548a5d20b..2adfd7d13f 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -661,6 +661,14 @@ def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_r
def set_reply_to_uri(obj), do: obj
+ # Misskey quotes
+ # Despite being underscored, it's potentially more reliable for interop.
+ def set_quote_url(%{"quoteUrl" => quote_url} = object) when is_binary(quote_url) do
+ Map.put(object, "_misskey_quote", quote_url)
+ end
+
+ def set_quote_url(obj), do: obj
+
@doc """
Serialized Mastodon-compatible `replies` collection containing _self-replies_.
Based on Mastodon's ActivityPub::NoteSerializer#replies.
@@ -715,6 +723,7 @@ def prepare_object(object) do
|> prepare_attachments
|> set_conversation
|> set_reply_to_uri
+ |> set_quote_url
|> set_replies
|> strip_internal_fields
|> strip_internal_tags
diff --git a/priv/static/schemas/litepub-0.1.jsonld b/priv/static/schemas/litepub-0.1.jsonld
index 7802b39467..07a36cceaa 100644
--- a/priv/static/schemas/litepub-0.1.jsonld
+++ b/priv/static/schemas/litepub-0.1.jsonld
@@ -17,6 +17,7 @@
"ostatus": "http://ostatus.org#",
"schema": "http://schema.org#",
"toot": "http://joinmastodon.org/ns#",
+ "misskey": "https://misskey-hub.net/ns#",
"value": "schema:value",
"sensitive": "as:sensitive",
"litepub": "http://litepub.social/ns#",
@@ -27,6 +28,7 @@
"@type": "@id"
},
"quoteUrl": "as:quoteUrl",
+ "_misskey_quote": "misskey:_misskey_quote",
"oauthRegistrationEndpoint": {
"@id": "litepub:oauthRegistrationEndpoint",
"@type": "@id"
diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs
index bae8f1d5eb..21dd86f732 100644
--- a/test/pleroma/web/activity_pub/transmogrifier_test.exs
+++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs
@@ -333,7 +333,11 @@ test "it prepares a quote post" do
{:ok, modified} = Transmogrifier.prepare_outgoing(quote_post.data)
quoted_post = Object.normalize(quoted_post)
+
assert modified["object"]["quoteUrl"] == quoted_post.data["id"]
+
+ # Add Misskey's quote as a fallback
+ assert modified["object"]["_misskey_quote"] == quoted_post.data["id"]
end
end
From b73a53ec69b5bc06c2ab31afa0ab5d6e168c4bad Mon Sep 17 00:00:00 2001
From: Alex Gleason
Date: Fri, 28 Jan 2022 15:55:52 -0600
Subject: [PATCH 2/3] Handle Fedibird's new quoteUri field
---
.../article_note_page_validator.ex | 8 ++-
.../web/activity_pub/transmogrifier.ex | 19 +++++--
priv/static/schemas/litepub-0.1.jsonld | 2 +
.../quote_post/fedibird_quote_uri.json | 54 +++++++++++++++++++
.../article_note_page_validator_test.exs | 10 ++++
.../web/activity_pub/transmogrifier_test.exs | 9 ++--
6 files changed, 92 insertions(+), 10 deletions(-)
create mode 100644 test/fixtures/quote_post/fedibird_quote_uri.json
diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
index 3568ca20a5..6c11dac6fa 100644
--- a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
@@ -67,7 +67,13 @@ defp fix_replies(data), do: data
defp fix_quote_url(%{"quoteUrl" => _quote_url} = data), do: data
- # Fix for Fedibird
+ # Fedibird
+ # https://github.com/fedibird/mastodon/commit/dbd7ae6cf58a92ec67c512296b4daaea0d01e6ac
+ defp fix_quote_url(%{"quoteUri" => quote_url} = data) do
+ Map.put(data, "quoteUrl", quote_url)
+ end
+
+ # Old Fedibird (bug)
# https://github.com/fedibird/mastodon/issues/9
defp fix_quote_url(%{"quoteURL" => quote_url} = data) do
Map.put(data, "quoteUrl", quote_url)
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 2adfd7d13f..22ff1a7abf 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -181,7 +181,15 @@ def fix_quote_url(%{"quoteUrl" => quote_url} = object, options)
end
end
- # Fix for Fedibird
+ # Fedibird
+ # https://github.com/fedibird/mastodon/commit/dbd7ae6cf58a92ec67c512296b4daaea0d01e6ac
+ def fix_quote_url(%{"quoteUri" => quote_url} = object, options) do
+ object
+ |> Map.put("quoteUrl", quote_url)
+ |> fix_quote_url(options)
+ end
+
+ # Old Fedibird (bug)
# https://github.com/fedibird/mastodon/issues/9
def fix_quote_url(%{"quoteURL" => quote_url} = object, options) do
object
@@ -661,10 +669,13 @@ def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_r
def set_reply_to_uri(obj), do: obj
- # Misskey quotes
- # Despite being underscored, it's potentially more reliable for interop.
def set_quote_url(%{"quoteUrl" => quote_url} = object) when is_binary(quote_url) do
- Map.put(object, "_misskey_quote", quote_url)
+ Map.merge(object, %{
+ # Fedibird quote
+ "quoteUri" => quote_url,
+ # Misskey quote
+ "_misskey_quote" => quote_url
+ })
end
def set_quote_url(obj), do: obj
diff --git a/priv/static/schemas/litepub-0.1.jsonld b/priv/static/schemas/litepub-0.1.jsonld
index 07a36cceaa..568a75ce0f 100644
--- a/priv/static/schemas/litepub-0.1.jsonld
+++ b/priv/static/schemas/litepub-0.1.jsonld
@@ -18,6 +18,7 @@
"schema": "http://schema.org#",
"toot": "http://joinmastodon.org/ns#",
"misskey": "https://misskey-hub.net/ns#",
+ "fedibird": "http://fedibird.com/ns#",
"value": "schema:value",
"sensitive": "as:sensitive",
"litepub": "http://litepub.social/ns#",
@@ -28,6 +29,7 @@
"@type": "@id"
},
"quoteUrl": "as:quoteUrl",
+ "quoteUri": "fedibird:quoteUri",
"_misskey_quote": "misskey:_misskey_quote",
"oauthRegistrationEndpoint": {
"@id": "litepub:oauthRegistrationEndpoint",
diff --git a/test/fixtures/quote_post/fedibird_quote_uri.json b/test/fixtures/quote_post/fedibird_quote_uri.json
new file mode 100644
index 0000000000..7c328fdb92
--- /dev/null
+++ b/test/fixtures/quote_post/fedibird_quote_uri.json
@@ -0,0 +1,54 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ {
+ "ostatus": "http://ostatus.org#",
+ "atomUri": "ostatus:atomUri",
+ "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+ "conversation": "ostatus:conversation",
+ "sensitive": "as:sensitive",
+ "toot": "http://joinmastodon.org/ns#",
+ "votersCount": "toot:votersCount",
+ "fedibird": "http://fedibird.com/ns#",
+ "quoteUri": "fedibird:quoteUri",
+ "expiry": "fedibird:expiry"
+ }
+ ],
+ "id": "https://fedibird.com/users/noellabo/statuses/107699335988346142",
+ "type": "Note",
+ "summary": null,
+ "inReplyTo": null,
+ "published": "2022-01-28T09:17:30Z",
+ "url": "https://fedibird.com/@noellabo/107699335988346142",
+ "attributedTo": "https://fedibird.com/users/noellabo",
+ "to": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "cc": [
+ "https://fedibird.com/users/noellabo/followers"
+ ],
+ "sensitive": false,
+ "atomUri": "https://fedibird.com/users/noellabo/statuses/107699335988346142",
+ "inReplyToAtomUri": null,
+ "conversation": "tag:fedibird.com,2022-01-28:objectId=107699335988345290:objectType=Conversation",
+ "context": "https://fedibird.com/contexts/107699335988345290",
+ "quoteUri": "https://fedibird.com/users/yamako/statuses/107699333438289729",
+ "_misskey_quote": "https://fedibird.com/users/yamako/statuses/107699333438289729",
+ "_misskey_content": "美味しそう",
+ "content": "美味しそう
QT: https://fedibird.com/@yamako/107699333438289729
",
+ "contentMap": {
+ "ja": "美味しそう
QT: https://fedibird.com/@yamako/107699333438289729
"
+ },
+ "attachment": [],
+ "tag": [],
+ "replies": {
+ "id": "https://fedibird.com/users/noellabo/statuses/107699335988346142/replies",
+ "type": "Collection",
+ "first": {
+ "type": "CollectionPage",
+ "next": "https://fedibird.com/users/noellabo/statuses/107699335988346142/replies?only_other_accounts=true&page=true",
+ "partOf": "https://fedibird.com/users/noellabo/statuses/107699335988346142/replies",
+ "items": []
+ }
+ }
+}
diff --git a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
index 1abf546adc..949b1339a6 100644
--- a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
+++ b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
@@ -43,6 +43,16 @@ test "Fedibird quote post" do
assert cng.changes.quoteUrl == "https://misskey.io/notes/8vsn2izjwh"
end
+ test "Fedibird quote post with quoteUri field" do
+ insert(:user, ap_id: "https://fedibird.com/users/noellabo")
+
+ data = File.read!("test/fixtures/quote_post/fedibird_quote_uri.json") |> Jason.decode!()
+ cng = ArticleNotePageValidator.cast_and_validate(data)
+
+ assert cng.valid?
+ assert cng.changes.quoteUrl == "https://fedibird.com/users/yamako/statuses/107699333438289729"
+ end
+
test "Misskey quote post" do
insert(:user, ap_id: "https://misskey.io/users/7rkrarq81i")
diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs
index 21dd86f732..e63a05d527 100644
--- a/test/pleroma/web/activity_pub/transmogrifier_test.exs
+++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs
@@ -332,12 +332,11 @@ test "it prepares a quote post" do
{:ok, modified} = Transmogrifier.prepare_outgoing(quote_post.data)
- quoted_post = Object.normalize(quoted_post)
+ %{data: %{"id" => quote_id}} = Object.normalize(quoted_post)
- assert modified["object"]["quoteUrl"] == quoted_post.data["id"]
-
- # Add Misskey's quote as a fallback
- assert modified["object"]["_misskey_quote"] == quoted_post.data["id"]
+ assert modified["object"]["quoteUrl"] == quote_id
+ assert modified["object"]["quoteUri"] == quote_id
+ assert modified["object"]["_misskey_quote"] == quote_id
end
end
From 108997b7644b400e7a3c7bd3f8f3f7e2bd42ecb2 Mon Sep 17 00:00:00 2001
From: Alex Gleason
Date: Fri, 28 Jan 2022 16:07:17 -0600
Subject: [PATCH 3/3] InlineQuotePolicy: improve the way Markdown quotes are
displayed by other software
---
.../web/activity_pub/mrf/inline_quote_policy.ex | 13 +++++++------
.../activity_pub/mrf/inline_quote_policy_test.exs | 4 ++--
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
index 46013fc5e9..7de4935f21 100644
--- a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
@@ -6,8 +6,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
@moduledoc "Force a quote line into the message content."
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
- defp build_inline_quote(prefix, url, br) do
- "#{String.duplicate("
", br)}#{prefix}: #{url}"
+ defp build_inline_quote(prefix, url) do
+ "
#{prefix}: #{url}"
end
defp filter_object(%{"quoteUrl" => quote_url} = object) do
@@ -18,12 +18,13 @@ defp filter_object(%{"quoteUrl" => quote_url} = object) do
else
prefix = Pleroma.Config.get([:mrf_inline_quote, :prefix])
- inline_quote =
+ content =
if String.ends_with?(content, "
"),
- do: build_inline_quote(prefix, quote_url, 0),
- else: build_inline_quote(prefix, quote_url, 2)
+ do:
+ String.trim_trailing(content, "") <>
+ build_inline_quote(prefix, quote_url) <> "",
+ else: content <> build_inline_quote(prefix, quote_url)
- content = content <> inline_quote
Map.put(object, "content", content)
end
end
diff --git a/test/pleroma/web/activity_pub/mrf/inline_quote_policy_test.exs b/test/pleroma/web/activity_pub/mrf/inline_quote_policy_test.exs
index 8e75aaaab2..2291c1dacd 100644
--- a/test/pleroma/web/activity_pub/mrf/inline_quote_policy_test.exs
+++ b/test/pleroma/web/activity_pub/mrf/inline_quote_policy_test.exs
@@ -22,7 +22,7 @@ test "adds quote URL to post content" do
{:ok, %{"object" => %{"content" => filtered}}} = InlineQuotePolicy.filter(activity)
assert filtered ==
- "Nice post
RT: https://gleasonator.com/objects/1234"
+ "Nice post
RT: https://gleasonator.com/objects/1234"
end
test "doesn't add line breaks to markdown posts" do
@@ -41,7 +41,7 @@ test "doesn't add line breaks to markdown posts" do
{:ok, %{"object" => %{"content" => filtered}}} = InlineQuotePolicy.filter(activity)
assert filtered ==
- "Nice post
RT: https://gleasonator.com/objects/1234"
+ "Nice post
RT: https://gleasonator.com/objects/1234
"
end
test "ignores Misskey quote posts" do