aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorkaniini <nenolod@gmail.com>2019-01-04 20:50:18 +0000
committerkaniini <nenolod@gmail.com>2019-01-04 20:50:18 +0000
commit4258dd8633407587ca1f3dfe275afa6a91be9197 (patch)
tree44dde15a2d2237297ce0a21f64bd3313836a3b7d /lib
parentffea81b84f73c75853518f7e0c28b8429f752a36 (diff)
parent48e81d3d40d334bccb8438c61ab6b307ddb1392f (diff)
downloadpleroma-4258dd8633407587ca1f3dfe275afa6a91be9197.tar.gz
Merge branch 'feature/rich-media' into 'develop'
URL previews in posts Closes #402 See merge request pleroma/pleroma!617
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/web/rich_media/controllers/rich_media_controller.ex17
-rw-r--r--lib/pleroma/web/rich_media/parser.ex26
-rw-r--r--lib/pleroma/web/rich_media/parsers/ogp.ex30
-rw-r--r--lib/pleroma/web/router.ex6
4 files changed, 79 insertions, 0 deletions
diff --git a/lib/pleroma/web/rich_media/controllers/rich_media_controller.ex b/lib/pleroma/web/rich_media/controllers/rich_media_controller.ex
new file mode 100644
index 000000000..91019961d
--- /dev/null
+++ b/lib/pleroma/web/rich_media/controllers/rich_media_controller.ex
@@ -0,0 +1,17 @@
+defmodule Pleroma.Web.RichMedia.RichMediaController do
+ use Pleroma.Web, :controller
+
+ import Pleroma.Web.ControllerHelper, only: [json_response: 3]
+
+ def parse(conn, %{"url" => url}) do
+ case Pleroma.Web.RichMedia.Parser.parse(url) do
+ {:ok, data} ->
+ conn
+ |> json_response(200, data)
+
+ {:error, msg} ->
+ conn
+ |> json_response(404, msg)
+ end
+ end
+end
diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex
new file mode 100644
index 000000000..477a38196
--- /dev/null
+++ b/lib/pleroma/web/rich_media/parser.ex
@@ -0,0 +1,26 @@
+defmodule Pleroma.Web.RichMedia.Parser do
+ @parsers [Pleroma.Web.RichMedia.Parsers.OGP]
+
+ def parse(url) do
+ {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url)
+
+ html |> maybe_parse() |> get_parsed_data()
+ end
+
+ defp maybe_parse(html) do
+ Enum.reduce_while(@parsers, %{}, fn parser, acc ->
+ case parser.parse(html, acc) do
+ {:ok, data} -> {:halt, data}
+ {:error, _msg} -> {:cont, acc}
+ end
+ end)
+ end
+
+ defp get_parsed_data(data) when data == %{} do
+ {:error, "No metadata found"}
+ end
+
+ defp get_parsed_data(data) do
+ {:ok, data}
+ end
+end
diff --git a/lib/pleroma/web/rich_media/parsers/ogp.ex b/lib/pleroma/web/rich_media/parsers/ogp.ex
new file mode 100644
index 000000000..5773a5263
--- /dev/null
+++ b/lib/pleroma/web/rich_media/parsers/ogp.ex
@@ -0,0 +1,30 @@
+defmodule Pleroma.Web.RichMedia.Parsers.OGP do
+ def parse(html, data) do
+ with elements = [_ | _] <- get_elements(html),
+ ogp_data =
+ Enum.reduce(elements, data, fn el, acc ->
+ attributes = normalize_attributes(el)
+
+ Map.merge(acc, attributes)
+ end) do
+ {:ok, ogp_data}
+ else
+ _e -> {:error, "No OGP metadata found"}
+ end
+ end
+
+ defp get_elements(html) do
+ html |> Floki.find("meta[property^='og:']")
+ end
+
+ defp normalize_attributes(html_node) do
+ {_tag, attributes, _children} = html_node
+
+ data =
+ Enum.into(attributes, %{}, fn {name, value} ->
+ {name, String.trim_leading(value, "og:")}
+ end)
+
+ %{String.to_atom(data["property"]) => data["content"]}
+ end
+end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 1f929ee21..8df45bf4d 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -232,6 +232,12 @@ defmodule Pleroma.Web.Router do
put("/settings", MastodonAPIController, :put_settings)
end
+ scope "/api", Pleroma.Web.RichMedia do
+ pipe_through(:authenticated_api)
+
+ get("/rich_media/parse", RichMediaController, :parse)
+ end
+
scope "/api/v1", Pleroma.Web.MastodonAPI do
pipe_through(:api)
get("/instance", MastodonAPIController, :masto_instance)