aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex32
-rw-r--r--lib/pleroma/web/plugs/http_security_plug.ex3
-rw-r--r--lib/pleroma/web/rich_media/helpers.ex22
-rw-r--r--lib/pleroma/web/rich_media/parser.ex32
-rw-r--r--lib/pleroma/web/rich_media/parser/card.ex75
5 files changed, 126 insertions, 38 deletions
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index bac897a57..5eb09f0a1 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -367,36 +367,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
nil
end
- def render("card.json", %{rich_media: rich_media, page_url: page_url}) do
- page_url_data = URI.parse(page_url)
-
- page_url_data =
- if is_binary(rich_media["url"]) do
- URI.merge(page_url_data, URI.parse(rich_media["url"]))
- else
- page_url_data
- end
-
- page_url = page_url_data |> to_string
-
- image_url =
- if is_binary(rich_media["image"]) do
- URI.merge(page_url_data, URI.parse(rich_media["image"]))
- |> to_string
- end
-
- %{
- type: "link",
- provider_name: page_url_data.host,
- provider_url: page_url_data.scheme <> "://" <> page_url_data.host,
- url: page_url,
- image: image_url |> MediaProxy.url(),
- title: rich_media["title"] || "",
- description: rich_media["description"] || "",
- pleroma: %{
- opengraph: rich_media
- }
- }
+ def render("card.json", %{rich_media: rich_media, page_url: _page_url}) do
+ rich_media
end
def render("card.json", _), do: nil
diff --git a/lib/pleroma/web/plugs/http_security_plug.ex b/lib/pleroma/web/plugs/http_security_plug.ex
index 0025b042a..7be45dce8 100644
--- a/lib/pleroma/web/plugs/http_security_plug.ex
+++ b/lib/pleroma/web/plugs/http_security_plug.ex
@@ -79,7 +79,8 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlug do
"frame-ancestors 'none'",
"style-src 'self' 'unsafe-inline'",
"font-src 'self'",
- "manifest-src 'self'"
+ "manifest-src 'self'",
+ "frame-src 'self' https:"
]
@csp_start [Enum.join(static_csp_rules, ";") <> ";"]
diff --git a/lib/pleroma/web/rich_media/helpers.ex b/lib/pleroma/web/rich_media/helpers.ex
index 566fc8c8a..249730aea 100644
--- a/lib/pleroma/web/rich_media/helpers.ex
+++ b/lib/pleroma/web/rich_media/helpers.ex
@@ -8,6 +8,7 @@ defmodule Pleroma.Web.RichMedia.Helpers do
alias Pleroma.HTML
alias Pleroma.Object
alias Pleroma.Web.RichMedia.Parser
+ alias Pleroma.Web.RichMedia.Parser.Card
@options [
pool: :media,
@@ -15,6 +16,8 @@ defmodule Pleroma.Web.RichMedia.Helpers do
recv_timeout: 2_000
]
+ @headers [{"user-agent", Pleroma.Application.user_agent() <> "; Bot"}]
+
@spec validate_page_url(URI.t() | binary()) :: :ok | :error
defp validate_page_url(page_url) when is_binary(page_url) do
validate_tld = Config.get([Pleroma.Formatter, :validate_tld])
@@ -55,12 +58,23 @@ defmodule Pleroma.Web.RichMedia.Helpers do
|> hd
end
+ defp strip_card(%Card{} = card) do
+ card
+ |> Map.from_struct()
+ |> Map.new(fn {k, v} -> {Atom.to_string(k), v} end)
+ end
+
+ defp strip_card(%{} = card) do
+ Map.new(card, fn {k, v} -> {Atom.to_string(k), v} end)
+ end
+
def fetch_data_for_object(object) do
with true <- Config.get([:rich_media, :enabled]),
{:ok, page_url} <-
HTML.extract_first_external_url_from_object(object),
:ok <- validate_page_url(page_url),
- {:ok, rich_media} <- Parser.parse(page_url) do
+ {:ok, rich_media} <- Parser.parse(page_url),
+ rich_media <- strip_card(rich_media) do
%{page_url: page_url, rich_media: rich_media}
else
_ -> %{}
@@ -78,8 +92,12 @@ defmodule Pleroma.Web.RichMedia.Helpers do
def fetch_data_for_activity(_), do: %{}
+ def oembed_get(url) do
+ Pleroma.HTTP.get(url, @headers, @options)
+ end
+
def rich_media_get(url) do
- headers = [{"user-agent", Pleroma.Application.user_agent() <> "; Bot"}]
+ headers = @headers
head_check =
case Pleroma.HTTP.head(url, headers, @options) do
diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex
index d6b54943b..d7b0cab6f 100644
--- a/lib/pleroma/web/rich_media/parser.ex
+++ b/lib/pleroma/web/rich_media/parser.ex
@@ -4,6 +4,7 @@
defmodule Pleroma.Web.RichMedia.Parser do
require Logger
+ alias Pleroma.Web.RichMedia.Parser.Card
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@@ -131,13 +132,34 @@ defmodule Pleroma.Web.RichMedia.Parser do
end
def parse_url(url) do
+ case maybe_fetch_oembed(url) do
+ {:ok, %Card{} = card} -> {:ok, card}
+ _ -> fetch_document(url)
+ end
+ end
+
+ defp maybe_fetch_oembed(url) do
+ with {:ok, oembed_url} <- OEmbedProviders.oembed_url(url),
+ {:ok, %Tesla.Env{body: json}} <-
+ Pleroma.Web.RichMedia.Helpers.oembed_get(oembed_url),
+ {:ok, data} <- Jason.decode(json),
+ %Card{} = card <- Card.from_oembed(data, url) do
+ {:ok, card}
+ else
+ {:error, error} -> {:error, error}
+ error -> {:error, error}
+ end
+ end
+
+ defp fetch_document(url) do
with {:ok, %Tesla.Env{body: html}} <- Pleroma.Web.RichMedia.Helpers.rich_media_get(url),
{:ok, html} <- Floki.parse_document(html) do
html
|> maybe_parse()
|> Map.put("url", url)
|> clean_parsed_data()
- |> check_parsed_data()
+ |> Card.from_meta_tags(url)
+ |> check_card()
end
end
@@ -150,13 +172,13 @@ defmodule Pleroma.Web.RichMedia.Parser do
end)
end
- defp check_parsed_data(%{"title" => title} = data)
+ defp check_card(%Card{title: title} = card)
when is_binary(title) and title != "" do
- {:ok, data}
+ {:ok, card}
end
- defp check_parsed_data(data) do
- {:error, {:invalid_metadata, data}}
+ defp check_card(card) do
+ {:error, {:invalid_metadata, card}}
end
defp clean_parsed_data(data) do
diff --git a/lib/pleroma/web/rich_media/parser/card.ex b/lib/pleroma/web/rich_media/parser/card.ex
new file mode 100644
index 000000000..5ea719485
--- /dev/null
+++ b/lib/pleroma/web/rich_media/parser/card.ex
@@ -0,0 +1,75 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.RichMedia.Parser.Card do
+ @types ["link", "photo", "video", "rich"]
+
+ # https://docs.joinmastodon.org/entities/card/
+ defstruct url: nil,
+ title: nil,
+ description: "",
+ type: "link",
+ author_name: "",
+ author_url: "",
+ provider_name: "",
+ provider_url: "",
+ html: "",
+ width: 0,
+ height: 0,
+ image: nil,
+ embed_url: "",
+ blurhash: nil
+
+ def from_oembed(%{"type" => type, "title" => title} = oembed, url) when type in @types do
+ %__MODULE__{
+ url: url,
+ title: title,
+ description: "",
+ type: type,
+ author_name: oembed["author_name"],
+ author_url: oembed["author_url"],
+ provider_name: oembed["provider_name"],
+ provider_url: oembed["provider_url"],
+ html: oembed["html"],
+ width: oembed["width"],
+ height: oembed["height"],
+ image: oembed["thumbnail_url"] |> proxy(),
+ embed_url: oembed["url"] |> proxy()
+ }
+ end
+
+ def from_oembed(_oembed, _url), do: nil
+
+ def from_meta_tags(rich_media, page_url) do
+ page_url_data = URI.parse(page_url)
+
+ page_url_data =
+ if is_binary(rich_media["url"]) do
+ URI.merge(page_url_data, URI.parse(rich_media["url"]))
+ else
+ page_url_data
+ end
+
+ page_url = page_url_data |> to_string
+
+ image_url =
+ if is_binary(rich_media["image"]) do
+ URI.merge(page_url_data, URI.parse(rich_media["image"]))
+ |> to_string
+ end
+
+ %__MODULE__{
+ type: "link",
+ provider_name: page_url_data.host,
+ provider_url: page_url_data.scheme <> "://" <> page_url_data.host,
+ url: page_url,
+ image: image_url |> proxy(),
+ title: rich_media["title"] || "",
+ description: rich_media["description"] || ""
+ }
+ end
+
+ defp proxy(url) when is_binary(url), do: Pleroma.Web.MediaProxy.url(url)
+ defp proxy(_), do: nil
+end