From 6f521fd9bfecd4a90328712187fc2f33a105d3b4 Mon Sep 17 00:00:00 2001 From: Erin Shepherd Date: Tue, 2 Apr 2024 23:57:27 +0200 Subject: [PATCH] MRF.InlineQuotePolicy: Add link to post URL, not ID "id" is used for the canonical link to the AS2 representation of an object. "url" is typically used for the canonical link to the HTTP representation. It is what we use, for example, when following the "external source" link in the frontend. However, it's not the link we include in the post contents for quote posts. Using URL instead means we include a more user-friendly URL for Mastodon, and a working (in the browser) URL for Threads --- .../activity_pub/mrf/inline_quote_policy.ex | 26 ++++++++++++++----- .../mrf/inline_quote_policy_test.exs | 10 +++++-- 2 files changed, 28 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 20432410b..8b4ffd1cf 100644 --- a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex @@ -6,14 +6,26 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do @moduledoc "Force a quote line into the message content." @behaviour Pleroma.Web.ActivityPub.MRF.Policy + alias Pleroma.Object + defp build_inline_quote(prefix, url) do "

#{prefix}: #{url}
" end - defp has_inline_quote?(content, quote_url) do + defp resolve_urls(quote_url) do + with %Object{} = obj <- Object.normalize(quote_url, fetch: true) do + id = obj.data["id"] + url = Map.get(obj.data, "url", id) + {id, url, [id, url, quote_url]} + else + _ -> {quote_url, quote_url, [quote_url]} + end + end + + defp has_inline_quote?(content, urls) do cond do # Does the quote URL exist in the content? - content =~ quote_url -> true + Enum.any?(urls, fn url -> content =~ url end) -> true # Does the content already have a .quote-inline span? content =~ "" -> true # No inline quote found @@ -22,18 +34,20 @@ defp has_inline_quote?(content, quote_url) do end defp filter_object(%{"quoteUri" => quote_url} = object) do - content = object["content"] || "" + {id, preferred_url, all_urls} = resolve_urls(quote_url) + object = Map.put(object, "quoteUri", id) - if has_inline_quote?(content, quote_url) do + content = object["content"] || "" + if has_inline_quote?(content, all_urls) do object else prefix = Pleroma.Config.get([:mrf_inline_quote, :prefix]) content = if String.ends_with?(content, "

") do - String.trim_trailing(content, "

") <> build_inline_quote(prefix, quote_url) <> "

" + String.trim_trailing(content, "

") <> build_inline_quote(prefix, preferred_url) <> "

" else - content <> build_inline_quote(prefix, quote_url) + content <> build_inline_quote(prefix, preferred_url) end Map.put(object, "content", content) 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 4e0910d3e..4419da158 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 @@ -6,8 +6,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicyTest do alias Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy use Pleroma.DataCase + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + :ok + end + + test "adds quote URL to post content" do - quote_url = "https://example.com/objects/1234" + quote_url = "https://mastodon.social/users/emelie/statuses/101849165031453009" activity = %{ "type" => "Create", @@ -22,7 +28,7 @@ test "adds quote URL to post content" do {:ok, %{"object" => %{"content" => filtered}}} = InlineQuotePolicy.filter(activity) assert filtered == - "

Nice post

RE: https://example.com/objects/1234

" + "

Nice post

RE: https://mastodon.social/@emelie/101849165031453009

" end test "ignores Misskey quote posts" do