Fix OpenGraph/TwitterCard meta tag ordering for posts with multiple attachments

This commit is contained in:
Mark Felder 2025-02-28 13:17:44 -08:00
commit 7bdeb9a1e5
5 changed files with 150 additions and 40 deletions

View file

@ -0,0 +1 @@
Fix OpenGraph/TwitterCard meta tag ordering for posts with multiple attachments

View file

@ -78,10 +78,10 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
# object when a Video or GIF is attached it will display that in Whatsapp Rich Preview. # object when a Video or GIF is attached it will display that in Whatsapp Rich Preview.
case Utils.fetch_media_type(@media_types, url["mediaType"]) do case Utils.fetch_media_type(@media_types, url["mediaType"]) do
"audio" -> "audio" ->
[ acc ++
{:meta, [property: "og:audio", content: MediaProxy.url(url["href"])], []} [
| acc {:meta, [property: "og:audio", content: MediaProxy.url(url["href"])], []}
] ]
# Not using preview_url for this. It saves bandwidth, but the image dimensions will # Not using preview_url for this. It saves bandwidth, but the image dimensions will
# be wrong. We generate it on the fly and have no way to capture or analyze the # be wrong. We generate it on the fly and have no way to capture or analyze the
@ -89,18 +89,18 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
# in timelines too, but you can get clever with the aspect ratio metadata as a # in timelines too, but you can get clever with the aspect ratio metadata as a
# workaround. # workaround.
"image" -> "image" ->
[ (acc ++
{:meta, [property: "og:image", content: MediaProxy.url(url["href"])], []}, [
{:meta, [property: "og:image:alt", content: attachment["name"]], []} {:meta, [property: "og:image", content: MediaProxy.url(url["href"])], []},
| acc {:meta, [property: "og:image:alt", content: attachment["name"]], []}
] ])
|> maybe_add_dimensions(url) |> maybe_add_dimensions(url)
"video" -> "video" ->
[ (acc ++
{:meta, [property: "og:video", content: MediaProxy.url(url["href"])], []} [
| acc {:meta, [property: "og:video", content: MediaProxy.url(url["href"])], []}
] ])
|> maybe_add_dimensions(url) |> maybe_add_dimensions(url)
|> maybe_add_video_thumbnail(url) |> maybe_add_video_thumbnail(url)

View file

@ -61,13 +61,13 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
Enum.reduce(attachment["url"], [], fn url, acc -> Enum.reduce(attachment["url"], [], fn url, acc ->
case Utils.fetch_media_type(@media_types, url["mediaType"]) do case Utils.fetch_media_type(@media_types, url["mediaType"]) do
"audio" -> "audio" ->
[ acc ++
{:meta, [name: "twitter:card", content: "player"], []}, [
{:meta, [name: "twitter:player:width", content: "480"], []}, {:meta, [name: "twitter:card", content: "player"], []},
{:meta, [name: "twitter:player:height", content: "80"], []}, {:meta, [name: "twitter:player:width", content: "480"], []},
{:meta, [name: "twitter:player", content: player_url(id)], []} {:meta, [name: "twitter:player:height", content: "80"], []},
| acc {:meta, [name: "twitter:player", content: player_url(id)], []}
] ]
# Not using preview_url for this. It saves bandwidth, but the image dimensions will # Not using preview_url for this. It saves bandwidth, but the image dimensions will
# be wrong. We generate it on the fly and have no way to capture or analyze the # be wrong. We generate it on the fly and have no way to capture or analyze the
@ -75,16 +75,16 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
# in timelines too, but you can get clever with the aspect ratio metadata as a # in timelines too, but you can get clever with the aspect ratio metadata as a
# workaround. # workaround.
"image" -> "image" ->
[ (acc ++
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
{:meta,
[ [
name: "twitter:image", {:meta, [name: "twitter:card", content: "summary_large_image"], []},
content: MediaProxy.url(url["href"]) {:meta,
], []}, [
{:meta, [name: "twitter:image:alt", content: truncate(attachment["name"])], []} name: "twitter:image",
| acc content: MediaProxy.url(url["href"])
] ], []},
{:meta, [name: "twitter:image:alt", content: truncate(attachment["name"])], []}
])
|> maybe_add_dimensions(url) |> maybe_add_dimensions(url)
"video" -> "video" ->
@ -92,17 +92,17 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
height = url["height"] || 480 height = url["height"] || 480
width = url["width"] || 480 width = url["width"] || 480
[ acc ++
{:meta, [name: "twitter:card", content: "player"], []}, [
{:meta, [name: "twitter:player", content: player_url(id)], []}, {:meta, [name: "twitter:card", content: "player"], []},
{:meta, [name: "twitter:player:width", content: "#{width}"], []}, {:meta, [name: "twitter:player", content: player_url(id)], []},
{:meta, [name: "twitter:player:height", content: "#{height}"], []}, {:meta, [name: "twitter:player:width", content: "#{width}"], []},
{:meta, [name: "twitter:player:stream", content: MediaProxy.url(url["href"])], {:meta, [name: "twitter:player:height", content: "#{height}"], []},
[]}, {:meta, [name: "twitter:player:stream", content: MediaProxy.url(url["href"])],
{:meta, [name: "twitter:player:stream:content_type", content: url["mediaType"]], []},
[]} {:meta, [name: "twitter:player:stream:content_type", content: url["mediaType"]],
| acc []}
] ]
_ -> _ ->
acc acc

View file

@ -9,6 +9,7 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraphTest do
alias Pleroma.UnstubbedConfigMock, as: ConfigMock alias Pleroma.UnstubbedConfigMock, as: ConfigMock
alias Pleroma.Web.Metadata.Providers.OpenGraph alias Pleroma.Web.Metadata.Providers.OpenGraph
alias Pleroma.Web.Metadata.Utils
setup do setup do
ConfigMock ConfigMock
@ -197,4 +198,58 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraphTest do
"http://localhost:4001/proxy/preview/LzAnlke-l5oZbNzWsrHfprX1rGw/aHR0cHM6Ly9wbGVyb21hLmdvdi9hYm91dC9qdWNoZS53ZWJt/juche.webm" "http://localhost:4001/proxy/preview/LzAnlke-l5oZbNzWsrHfprX1rGw/aHR0cHM6Ly9wbGVyb21hLmdvdi9hYm91dC9qdWNoZS53ZWJt/juche.webm"
], []} in result ], []} in result
end end
test "meta tag ordering matches attachment order" do
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
note =
insert(:note, %{
data: %{
"actor" => user.ap_id,
"tag" => [],
"id" => "https://pleroma.gov/objects/whatever",
"summary" => "",
"content" => "pleroma in a nutshell",
"attachment" => [
%{
"url" => [
%{
"mediaType" => "image/png",
"href" => "https://example.com/first.png",
"height" => 1024,
"width" => 1280
}
]
},
%{
"url" => [
%{
"mediaType" => "image/png",
"href" => "https://example.com/second.png",
"height" => 1024,
"width" => 1280
}
]
}
]
}
})
result = OpenGraph.build_tags(%{object: note, url: note.data["id"], user: user})
assert [
{:meta, [property: "og:title", content: Utils.user_name_string(user)], []},
{:meta, [property: "og:url", content: "https://pleroma.gov/objects/whatever"], []},
{:meta, [property: "og:description", content: "pleroma in a nutshell"], []},
{:meta, [property: "og:type", content: "article"], []},
{:meta, [property: "og:image", content: "https://example.com/first.png"], []},
{:meta, [property: "og:image:alt", content: nil], []},
{:meta, [property: "og:image:width", content: "1280"], []},
{:meta, [property: "og:image:height", content: "1024"], []},
{:meta, [property: "og:image", content: "https://example.com/second.png"], []},
{:meta, [property: "og:image:alt", content: nil], []},
{:meta, [property: "og:image:width", content: "1280"], []},
{:meta, [property: "og:image:height", content: "1024"], []}
] == result
end
end end

View file

@ -202,4 +202,58 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do
{:meta, [name: "twitter:player:stream:content_type", content: "video/webm"], []} {:meta, [name: "twitter:player:stream:content_type", content: "video/webm"], []}
] == result ] == result
end end
test "meta tag ordering matches attachment order" do
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994")
note =
insert(:note, %{
data: %{
"actor" => user.ap_id,
"tag" => [],
"id" => "https://pleroma.gov/objects/whatever",
"summary" => "",
"content" => "pleroma in a nutshell",
"attachment" => [
%{
"url" => [
%{
"mediaType" => "image/png",
"href" => "https://example.com/first.png",
"height" => 1024,
"width" => 1280
}
]
},
%{
"url" => [
%{
"mediaType" => "image/png",
"href" => "https://example.com/second.png",
"height" => 1024,
"width" => 1280
}
]
}
]
}
})
result = TwitterCard.build_tags(%{object: note, activity_id: note.data["id"], user: user})
assert [
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []},
{:meta, [name: "twitter:description", content: "pleroma in a nutshell"], []},
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
{:meta, [name: "twitter:image", content: "https://example.com/first.png"], []},
{:meta, [name: "twitter:image:alt", content: ""], []},
{:meta, [name: "twitter:player:width", content: "1280"], []},
{:meta, [name: "twitter:player:height", content: "1024"], []},
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
{:meta, [name: "twitter:image", content: "https://example.com/second.png"], []},
{:meta, [name: "twitter:image:alt", content: ""], []},
{:meta, [name: "twitter:player:width", content: "1280"], []},
{:meta, [name: "twitter:player:height", content: "1024"], []}
] == result
end
end end