diff --git a/changelog.d/card-skip-quote-link.fix b/changelog.d/card-skip-quote-link.fix new file mode 100644 index 000000000..27fe096fa --- /dev/null +++ b/changelog.d/card-skip-quote-link.fix @@ -0,0 +1 @@ +Link preview cards skip the fallback link of quote posts (`RE: `), which pointed at the quoted post and showed it twice. diff --git a/lib/pleroma/html.ex b/lib/pleroma/html.ex index 4de7cbb76..aeac8bd04 100644 --- a/lib/pleroma/html.ex +++ b/lib/pleroma/html.ex @@ -66,14 +66,16 @@ defmodule Pleroma.HTML do end @spec extract_first_external_url_from_object(Pleroma.Object.t()) :: String.t() | nil - def extract_first_external_url_from_object(%{data: %{"content" => content}}) + def extract_first_external_url_from_object(%{data: %{"content" => content} = data}) when is_binary(content) do + # A quote post's fallback link ("RE: ", in a .quote-inline element or + # bare) points at the quoted post, which is shown already. content |> Floki.parse_fragment!() + |> Floki.filter_out(".quote-inline") |> Floki.find("a:not(.mention,.hashtag,.attachment,[rel~=\"tag\"])") - |> Enum.take(1) |> Floki.attribute("href") - |> Enum.at(0) + |> Enum.find(&(&1 != data["quoteUrl"])) end def extract_first_external_url_from_object(_), do: nil diff --git a/test/pleroma/html_test.exs b/test/pleroma/html_test.exs index d17b07540..5e7ad4749 100644 --- a/test/pleroma/html_test.exs +++ b/test/pleroma/html_test.exs @@ -299,5 +299,42 @@ defmodule Pleroma.HTMLTest do assert nil == HTML.extract_first_external_url_from_object(object) end + + test "skips the link in a Mastodon quote fallback paragraph" do + object = %Object{ + data: %{ + "quoteUrl" => "https://raru.re/users/ocean/statuses/116235427788617987", + "content" => + "

RE: raru.re/@ocean/116235427788617987

" <> + "

Berapa lapis?

youtube.com/watch?v=S0dJMhWDRDE

" + } + } + + assert HTML.extract_first_external_url_from_object(object) == + "https://www.youtube.com/watch?v=S0dJMhWDRDE" + end + + test "skips the link in a quote fallback span (Misskey, InlineQuotePolicy)" do + object = %Object{ + data: %{ + "content" => + "hello

RE: https://misskey.example/notes/abc
" + } + } + + assert nil == HTML.extract_first_external_url_from_object(object) + end + + test "skips a link to the quoted post without fallback markup" do + object = %Object{ + data: %{ + "quoteUrl" => "https://remote.example/objects/1", + "content" => + "RE: https://remote.example/objects/1 cofe" + } + } + + assert HTML.extract_first_external_url_from_object(object) == "https://cofe.example/" + end end end