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
This commit is contained in:
Erin Shepherd 2024-04-02 23:57:27 +02:00
parent c70df5fb2a
commit 0596044717
2 changed files with 27 additions and 7 deletions

View file

@ -6,14 +6,26 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
@moduledoc "Force a quote line into the message content." @moduledoc "Force a quote line into the message content."
@behaviour Pleroma.Web.ActivityPub.MRF.Policy @behaviour Pleroma.Web.ActivityPub.MRF.Policy
alias Pleroma.Object
defp build_inline_quote(prefix, url) do defp build_inline_quote(prefix, url) do
"<span class=\"quote-inline\"><br/><br/>#{prefix}: <a href=\"#{url}\">#{url}</a></span>" "<span class=\"quote-inline\"><br/><br/>#{prefix}: <a href=\"#{url}\">#{url}</a></span>"
end 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 cond do
# Does the quote URL exist in the content? # 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? # Does the content already have a .quote-inline span?
content =~ "<span class=\"quote-inline\">" -> true content =~ "<span class=\"quote-inline\">" -> true
# No inline quote found # No inline quote found
@ -22,16 +34,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
end end
defp filter_object(%{"quoteUri" => quote_url} = object) do 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 object
else else
prefix = Pleroma.Config.get([:mrf_inline_quote, :prefix]) prefix = Pleroma.Config.get([:mrf_inline_quote, :prefix])
content = content =
if String.ends_with?(content, "</p>") do if String.ends_with?(content, "</p>") do
String.trim_trailing(content, "</p>") <> build_inline_quote(prefix, quote_url) <> "</p>" String.trim_trailing(content, "</p>") <> build_inline_quote(prefix, preferred_url) <> "</p>"
else else
content <> build_inline_quote(prefix, quote_url) content <> build_inline_quote(prefix, quote_url)
end end

View file

@ -6,8 +6,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicyTest do
alias Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy alias Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy
use Pleroma.DataCase 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 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 = %{ activity = %{
"type" => "Create", "type" => "Create",
@ -22,7 +28,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicyTest do
{:ok, %{"object" => %{"content" => filtered}}} = InlineQuotePolicy.filter(activity) {:ok, %{"object" => %{"content" => filtered}}} = InlineQuotePolicy.filter(activity)
assert filtered == assert filtered ==
"<p>Nice post<span class=\"quote-inline\"><br/><br/>RE: <a href=\"https://example.com/objects/1234\">https://example.com/objects/1234</a></span></p>" "<p>Nice post<span class=\"quote-inline\"><br/><br/>RE: <a href=\"https://mastodon.social/@emelie/101849165031453009\">https://mastodon.social/@emelie/101849165031453009</a></span></p>"
end end
test "ignores Misskey quote posts" do test "ignores Misskey quote posts" do