@@ -9,6 +9,7 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do | |||
alias Pleroma.Web.Metadata.Utils | |||
@behaviour Provider | |||
@media_types ["image", "audio", "video"] | |||
@impl Provider | |||
def build_tags(%{ | |||
@@ -81,26 +82,19 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do | |||
Enum.reduce(attachments, [], fn attachment, acc -> | |||
rendered_tags = | |||
Enum.reduce(attachment["url"], [], fn url, acc -> | |||
media_type = | |||
Enum.find(["image", "audio", "video"], fn media_type -> | |||
String.starts_with?(url["mediaType"], media_type) | |||
end) | |||
# TODO: Add additional properties to objects when we have the data available. | |||
# Also, Whatsapp only wants JPEG or PNGs. It seems that if we add a second og:image | |||
# object when a Video or GIF is attached it will display that in Whatsapp Rich Preview. | |||
case media_type do | |||
case Utils.fetch_media_type(@media_types, url["mediaType"]) do | |||
"audio" -> | |||
[ | |||
{:meta, | |||
[property: "og:" <> media_type, content: Utils.attachment_url(url["href"])], []} | |||
{:meta, [property: "og:audio", content: Utils.attachment_url(url["href"])], []} | |||
| acc | |||
] | |||
"image" -> | |||
[ | |||
{:meta, | |||
[property: "og:" <> media_type, content: Utils.attachment_url(url["href"])], []}, | |||
{:meta, [property: "og:image", content: Utils.attachment_url(url["href"])], []}, | |||
{:meta, [property: "og:image:width", content: 150], []}, | |||
{:meta, [property: "og:image:height", content: 150], []} | |||
| acc | |||
@@ -108,8 +102,7 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do | |||
"video" -> | |||
[ | |||
{:meta, | |||
[property: "og:" <> media_type, content: Utils.attachment_url(url["href"])], []} | |||
{:meta, [property: "og:video", content: Utils.attachment_url(url["href"])], []} | |||
| acc | |||
] | |||
@@ -1,4 +1,5 @@ | |||
# Pleroma: A lightweight social networking server | |||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> | |||
# SPDX-License-Identifier: AGPL-3.0-only | |||
@@ -9,13 +10,10 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do | |||
alias Pleroma.Web.Metadata.Utils | |||
@behaviour Provider | |||
@media_types ["image", "audio", "video"] | |||
@impl Provider | |||
def build_tags(%{ | |||
activity_id: id, | |||
object: object, | |||
user: user | |||
}) do | |||
def build_tags(%{activity_id: id, object: object, user: user}) do | |||
attachments = build_attachments(id, object) | |||
scrubbed_content = Utils.scrub_html_and_truncate(object) | |||
# Zero width space | |||
@@ -27,21 +25,12 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do | |||
end | |||
[ | |||
{:meta, | |||
[ | |||
property: "twitter:title", | |||
content: Utils.user_name_string(user) | |||
], []}, | |||
{:meta, | |||
[ | |||
property: "twitter:description", | |||
content: content | |||
], []} | |||
title_tag(user), | |||
{:meta, [property: "twitter:description", content: content], []} | |||
] ++ | |||
if attachments == [] or Metadata.activity_nsfw?(object) do | |||
[ | |||
{:meta, | |||
[property: "twitter:image", content: Utils.attachment_url(User.avatar_url(user))], []}, | |||
image_tag(user), | |||
{:meta, [property: "twitter:card", content: "summary_large_image"], []} | |||
] | |||
else | |||
@@ -53,30 +42,28 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do | |||
def build_tags(%{user: user}) do | |||
with truncated_bio = Utils.scrub_html_and_truncate(user.bio || "") do | |||
[ | |||
{:meta, | |||
[ | |||
property: "twitter:title", | |||
content: Utils.user_name_string(user) | |||
], []}, | |||
title_tag(user), | |||
{:meta, [property: "twitter:description", content: truncated_bio], []}, | |||
{:meta, [property: "twitter:image", content: Utils.attachment_url(User.avatar_url(user))], | |||
[]}, | |||
image_tag(user), | |||
{:meta, [property: "twitter:card", content: "summary"], []} | |||
] | |||
end | |||
end | |||
defp title_tag(user) do | |||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []} | |||
end | |||
def image_tag(user) do | |||
{:meta, [property: "twitter:image", content: Utils.attachment_url(User.avatar_url(user))], []} | |||
end | |||
defp build_attachments(id, %{data: %{"attachment" => attachments}}) do | |||
Enum.reduce(attachments, [], fn attachment, acc -> | |||
rendered_tags = | |||
Enum.reduce(attachment["url"], [], fn url, acc -> | |||
media_type = | |||
Enum.find(["image", "audio", "video"], fn media_type -> | |||
String.starts_with?(url["mediaType"], media_type) | |||
end) | |||
# TODO: Add additional properties to objects when we have the data available. | |||
case media_type do | |||
case Utils.fetch_media_type(@media_types, url["mediaType"]) do | |||
"audio" -> | |||
[ | |||
{:meta, [property: "twitter:card", content: "player"], []}, | |||
@@ -39,4 +39,11 @@ defmodule Pleroma.Web.Metadata.Utils do | |||
"(@#{user.nickname})" | |||
end | |||
end | |||
@spec fetch_media_type(list(String.t()), String.t()) :: String.t() | nil | |||
def fetch_media_type(supported_types, media_type) do | |||
Enum.find(supported_types, fn support_type -> | |||
String.starts_with?(media_type, support_type) | |||
end) | |||
end | |||
end |
@@ -0,0 +1,33 @@ | |||
# Pleroma: A lightweight social networking server | |||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> | |||
# SPDX-License-Identifier: AGPL-3.0-only | |||
defmodule Pleroma.Web.Metadata.PlayerViewTest do | |||
use Pleroma.DataCase | |||
alias Pleroma.Web.Metadata.PlayerView | |||
test "it renders audio tag" do | |||
res = | |||
PlayerView.render( | |||
"player.html", | |||
%{"mediaType" => "audio", "href" => "test-href"} | |||
) | |||
|> Phoenix.HTML.safe_to_string() | |||
assert res == | |||
"<audio controls><source src=\"test-href\" type=\"audio\">Your browser does not support audio playback.</audio>" | |||
end | |||
test "it renders videos tag" do | |||
res = | |||
PlayerView.render( | |||
"player.html", | |||
%{"mediaType" => "video", "href" => "test-href"} | |||
) | |||
|> Phoenix.HTML.safe_to_string() | |||
assert res == | |||
"<video controls loop><source src=\"test-href\" type=\"video\">Your browser does not support video playback.</video>" | |||
end | |||
end |
@@ -0,0 +1,123 @@ | |||
# Pleroma: A lightweight social networking server | |||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> | |||
# SPDX-License-Identifier: AGPL-3.0-only | |||
defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do | |||
use Pleroma.DataCase | |||
import Pleroma.Factory | |||
alias Pleroma.User | |||
alias Pleroma.Web.CommonAPI | |||
alias Pleroma.Web.Endpoint | |||
alias Pleroma.Web.Metadata.Providers.TwitterCard | |||
alias Pleroma.Web.Metadata.Utils | |||
alias Pleroma.Web.Router | |||
test "it renders twitter card for user info" do | |||
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994") | |||
avatar_url = Utils.attachment_url(User.avatar_url(user)) | |||
res = TwitterCard.build_tags(%{user: user}) | |||
assert res == [ | |||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []}, | |||
{:meta, [property: "twitter:description", content: "born 19 March 1994"], []}, | |||
{:meta, [property: "twitter:image", content: avatar_url], []}, | |||
{:meta, [property: "twitter:card", content: "summary"], []} | |||
] | |||
end | |||
test "it does not render attachments if post is nsfw" do | |||
Pleroma.Config.put([Pleroma.Web.Metadata, :unfurl_nsfw], false) | |||
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994") | |||
{:ok, activity} = CommonAPI.post(user, %{"status" => "HI"}) | |||
note = | |||
insert(:note, %{ | |||
data: %{ | |||
"actor" => user.ap_id, | |||
"tag" => [], | |||
"id" => "https://pleroma.gov/objects/whatever", | |||
"content" => "pleroma in a nutshell", | |||
"sensitive" => true, | |||
"attachment" => [ | |||
%{ | |||
"url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/tenshi.png"}] | |||
}, | |||
%{ | |||
"url" => [ | |||
%{ | |||
"mediaType" => "application/octet-stream", | |||
"href" => "https://pleroma.gov/fqa/badapple.sfc" | |||
} | |||
] | |||
}, | |||
%{ | |||
"url" => [ | |||
%{"mediaType" => "video/webm", "href" => "https://pleroma.gov/about/juche.webm"} | |||
] | |||
} | |||
] | |||
} | |||
}) | |||
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id}) | |||
assert [ | |||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []}, | |||
{:meta, [property: "twitter:description", content: "“pleroma in a nutshell”"], []}, | |||
{:meta, [property: "twitter:image", content: "http://localhost:4001/images/avi.png"], | |||
[]}, | |||
{:meta, [property: "twitter:card", content: "summary_large_image"], []} | |||
] == result | |||
end | |||
test "it renders supported types of attachments and skips unknown types" do | |||
user = insert(:user, name: "Jimmy Hendriks", bio: "born 19 March 1994") | |||
{:ok, activity} = CommonAPI.post(user, %{"status" => "HI"}) | |||
note = | |||
insert(:note, %{ | |||
data: %{ | |||
"actor" => user.ap_id, | |||
"tag" => [], | |||
"id" => "https://pleroma.gov/objects/whatever", | |||
"content" => "pleroma in a nutshell", | |||
"attachment" => [ | |||
%{ | |||
"url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/tenshi.png"}] | |||
}, | |||
%{ | |||
"url" => [ | |||
%{ | |||
"mediaType" => "application/octet-stream", | |||
"href" => "https://pleroma.gov/fqa/badapple.sfc" | |||
} | |||
] | |||
}, | |||
%{ | |||
"url" => [ | |||
%{"mediaType" => "video/webm", "href" => "https://pleroma.gov/about/juche.webm"} | |||
] | |||
} | |||
] | |||
} | |||
}) | |||
result = TwitterCard.build_tags(%{object: note, user: user, activity_id: activity.id}) | |||
assert [ | |||
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []}, | |||
{:meta, [property: "twitter:description", content: "“pleroma in a nutshell”"], []}, | |||
{:meta, [property: "twitter:card", content: "summary_large_image"], []}, | |||
{:meta, [property: "twitter:player", content: "https://pleroma.gov/tenshi.png"], []}, | |||
{:meta, [property: "twitter:card", content: "player"], []}, | |||
{:meta, | |||
[ | |||
property: "twitter:player", | |||
content: Router.Helpers.o_status_url(Endpoint, :notice_player, activity.id) | |||
], []}, | |||
{:meta, [property: "twitter:player:width", content: "480"], []}, | |||
{:meta, [property: "twitter:player:height", content: "480"], []} | |||
] == result | |||
end | |||
end |