Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85711975
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/pleroma/web/metadata.ex b/lib/pleroma/web/metadata.ex
index d859dfd8b..8793fc265 100644
--- a/lib/pleroma/web/metadata.ex
+++ b/lib/pleroma/web/metadata.ex
@@ -1,30 +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 do
alias Phoenix.HTML
@providers Pleroma.Config.get([__MODULE__, :providers], [])
def build_tags(params) do
Enum.reduce(@providers, "", fn parser, acc ->
rendered_html =
params
|> parser.build_tags()
|> Enum.map(&to_tag/1)
|> Enum.map(&HTML.safe_to_string/1)
|> Enum.join()
acc <> rendered_html
end)
end
def to_tag(data) do
with {name, attrs, _content = []} <- data do
HTML.Tag.tag(name, attrs)
else
{name, attrs, content} ->
HTML.Tag.content_tag(name, content, attrs)
_ ->
raise ArgumentError, message: "make_tag invalid args"
end
end
end
diff --git a/lib/pleroma/web/metadata/opengraph.ex b/lib/pleroma/web/metadata/opengraph.ex
index f6a1f3023..b7c5dc64e 100644
--- a/lib/pleroma/web/metadata/opengraph.ex
+++ b/lib/pleroma/web/metadata/opengraph.ex
@@ -1,106 +1,109 @@
+# 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.OpenGraph do
alias Pleroma.Web.Metadata.Providers.Provider
alias Pleroma.{HTML, Formatter, User}
alias Pleroma.Web.MediaProxy
@behaviour Provider
@impl Provider
def build_tags(%{activity: activity, user: user}) do
with truncated_content = scrub_html_and_truncate(activity) do
attachments = build_attachments(activity)
[
{:meta,
[
property: "og:title",
content: user_name_string(user)
], []},
{:meta, [property: "og:url", content: activity.data["id"]], []},
{:meta, [property: "og:description", content: truncated_content], []}
] ++
if attachments == [] or
Enum.any?(activity.data["object"]["tag"], fn tag -> tag == "nsfw" end) do
[
{:meta, [property: "og:image", content: attachment_url(User.avatar_url(user))], []},
{:meta, [property: "og:image:width", content: 120], []},
{:meta, [property: "og:image:height", content: 120], []}
]
else
attachments
end
end
end
@impl Provider
def build_tags(%{user: user}) do
with truncated_bio = scrub_html_and_truncate(user.bio || "") do
[
{:meta,
[
property: "og:title",
content: user_name_string(user)
], []},
{:meta, [property: "og:url", content: User.profile_url(user)], []},
{:meta, [property: "og:description", content: truncated_bio], []},
{:meta, [property: "og:image", content: attachment_url(User.avatar_url(user))], []},
{:meta, [property: "og:image:width", content: 120], []},
{:meta, [property: "og:image:height", content: 120], []}
]
end
end
defp build_attachments(%{data: %{"object" => %{"attachment" => attachments}}} = _activity) 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)
if media_type do
[
{:meta, [property: "og:" <> media_type, content: attachment_url(url["href"])], []}
| acc
]
else
acc
end
end)
acc ++ rendered_tags
end)
end
defp scrub_html_and_truncate(%{data: %{"object" => %{"content" => content}}} = activity) do
content
# html content comes from DB already encoded, decode first and scrub after
|> HtmlEntities.decode()
|> String.replace(~r/<br\s?\/?>/, " ")
|> HTML.get_cached_stripped_html_for_object(activity, __MODULE__)
|> Formatter.truncate()
end
defp scrub_html_and_truncate(content) when is_binary(content) do
content
# html content comes from DB already encoded, decode first and scrub after
|> HtmlEntities.decode()
|> String.replace(~r/<br\s?\/?>/, " ")
|> HTML.strip_tags()
|> Formatter.truncate()
end
defp attachment_url(url) do
MediaProxy.url(url)
end
defp user_name_string(user) do
"#{user.name} " <>
if user.local do
"(@#{user.nickname}@#{Pleroma.Web.Endpoint.host()})"
else
"(@#{user.nickname})"
end
end
end
diff --git a/lib/pleroma/web/metadata/provider.ex b/lib/pleroma/web/metadata/provider.ex
index f64810fad..a39008bcc 100644
--- a/lib/pleroma/web/metadata/provider.ex
+++ b/lib/pleroma/web/metadata/provider.ex
@@ -1,3 +1,6 @@
+# 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.Provider do
@callback build_tags(map()) :: list()
end
diff --git a/lib/pleroma/web/metadata/twitter_card.ex b/lib/pleroma/web/metadata/twitter_card.ex
index 3094e61fd..853776611 100644
--- a/lib/pleroma/web/metadata/twitter_card.ex
+++ b/lib/pleroma/web/metadata/twitter_card.ex
@@ -1,42 +1,45 @@
+# 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.TwitterCard do
alias Pleroma.Web.Metadata.Providers.Provider
@behaviour Provider
@impl Provider
def build_tags(%{activity: activity}) do
if Enum.any?(activity.data["object"]["tag"], fn tag -> tag == "nsfw" end) or
activity.data["object"]["attachment"] == [] do
build_tags(nil)
else
case find_first_acceptable_media_type(activity) do
"image" ->
[{:meta, [property: "twitter:card", content: "summary_large_image"], []}]
"audio" ->
[{:meta, [property: "twitter:card", content: "player"], []}]
"video" ->
[{:meta, [property: "twitter:card", content: "player"], []}]
_ ->
build_tags(nil)
end
end
end
@impl Provider
def build_tags(_) do
[{:meta, [property: "twitter:card", content: "summary"], []}]
end
def find_first_acceptable_media_type(%{data: %{"object" => %{"attachment" => attachment}}}) do
Enum.find_value(attachment, fn attachment ->
Enum.find_value(attachment["url"], fn url ->
Enum.find(["image", "audio", "video"], fn media_type ->
String.starts_with?(url["mediaType"], media_type)
end)
end)
end)
end
end
diff --git a/test/web/metadata/opengraph_test.exs b/test/web/metadata/opengraph_test.exs
new file mode 100644
index 000000000..be3f89364
--- /dev/null
+++ b/test/web/metadata/opengraph_test.exs
@@ -0,0 +1,113 @@
+# 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.OpenGraphTest do
+ use Pleroma.DataCase
+ import Pleroma.Factory
+ alias Pleroma.Web.Metadata.Providers.OpenGraph
+
+ test "it renders all supported types of attachments and skips unknown types" do
+ user = insert(:user)
+
+ note =
+ insert(:note, %{
+ data: %{
+ "actor" => user.ap_id,
+ "tag" => [],
+ "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"}
+ ]
+ },
+ %{
+ "url" => [
+ %{
+ "mediaType" => "audio/basic",
+ "href" => "http://www.gnu.org/music/free-software-song.au"
+ }
+ ]
+ }
+ ]
+ }
+ })
+
+ note_activity =
+ insert(:note_activity, %{
+ data: %{
+ "actor" => note.data["actor"],
+ "to" => note.data["to"],
+ "object" => note.data,
+ "context" => note.data["context"]
+ },
+ actor: note.data["actor"],
+ recipients: note.data["to"]
+ })
+
+ result = OpenGraph.build_tags(%{activity: note_activity, user: user})
+
+ assert Enum.all?(
+ [
+ {:meta, [property: "og:image", content: "https://pleroma.gov/tenshi.png"], []},
+ {:meta,
+ [property: "og:audio", content: "http://www.gnu.org/music/free-software-song.au"],
+ []},
+ {:meta, [property: "og:video", content: "https://pleroma.gov/about/juche.webm"],
+ []}
+ ],
+ fn element -> element in result end
+ )
+ end
+
+ test "it does not render attachments if post is nsfw" do
+ user = insert(:user, avatar: %{"url" => [%{"href" => "https://pleroma.gov/tenshi.png"}]})
+
+ note =
+ insert(:note, %{
+ data: %{
+ "actor" => user.ap_id,
+ "content" => "#cuteposting #nsfw #hambaga",
+ "tag" => ["cuteposting", "nsfw", "hambaga"],
+ "attachment" => [
+ %{
+ "url" => [
+ %{"mediaType" => "image/png", "href" => "https://misskey.microsoft/corndog.png"}
+ ]
+ }
+ ]
+ }
+ })
+
+ note_activity =
+ insert(:note_activity, %{
+ data: %{
+ "actor" => note.data["actor"],
+ "to" => note.data["to"],
+ "object" => note.data,
+ "context" => note.data["context"]
+ },
+ actor: note.data["actor"],
+ recipients: note.data["to"]
+ })
+
+ result = OpenGraph.build_tags(%{activity: note_activity, user: user})
+
+ assert {:meta, [property: "og:image", content: "https://pleroma.gov/tenshi.png"], []} in result
+
+ refute {:meta, [property: "og:image", content: "https://misskey.microsoft/corndog.png"], []} in result
+ end
+end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Sep 19, 8:25 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1769188
Default Alt Text
(10 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline
Log In to Comment