Introduce group basic federation, event new page and notifications
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
41
lib/service/rich_media/parsers/fallback.ex
Normal file
41
lib/service/rich_media/parsers/fallback.ex
Normal file
@@ -0,0 +1,41 @@
|
||||
# Portions of this file are derived from Pleroma:
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mobilizon.Service.RichMedia.Parsers.Fallback do
|
||||
@moduledoc """
|
||||
Module to parse fallback data in HTML pages (plain old title and meta description)
|
||||
"""
|
||||
@spec parse(String.t(), map()) :: {:ok, map()} | {:error, String.t()}
|
||||
def parse(html, data) do
|
||||
data =
|
||||
data
|
||||
|> maybe_put(html, :title)
|
||||
|> maybe_put(html, :description)
|
||||
|
||||
if Enum.empty?(data) do
|
||||
{:error, "Not even a title"}
|
||||
else
|
||||
{:ok, data}
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_put(meta, html, attr) do
|
||||
case get_page(html, attr) do
|
||||
"" -> meta
|
||||
content -> Map.put_new(meta, attr, content)
|
||||
end
|
||||
end
|
||||
|
||||
defp get_page(html, :title) do
|
||||
html |> Floki.find("html head title") |> List.first() |> Floki.text() |> String.trim()
|
||||
end
|
||||
|
||||
defp get_page(html, :description) do
|
||||
case html |> Floki.find("html head meta[name='description']") |> List.first() do
|
||||
nil -> ""
|
||||
elem -> elem |> Floki.attribute("content") |> List.first() |> String.trim()
|
||||
end
|
||||
end
|
||||
end
|
||||
76
lib/service/rich_media/parsers/meta_tags_parser.ex
Normal file
76
lib/service/rich_media/parsers/meta_tags_parser.ex
Normal file
@@ -0,0 +1,76 @@
|
||||
# Portions of this file are derived from Pleroma:
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mobilizon.Service.RichMedia.Parsers.MetaTagsParser do
|
||||
@moduledoc """
|
||||
Module to parse meta tags data in HTML pages
|
||||
"""
|
||||
def parse(html, data, prefix, error_message, key_name, value_name \\ "content") do
|
||||
meta_data =
|
||||
html
|
||||
|> get_elements(key_name, prefix)
|
||||
|> Enum.reduce(data, fn el, acc ->
|
||||
attributes = normalize_attributes(el, prefix, key_name, value_name)
|
||||
|
||||
Map.merge(acc, attributes)
|
||||
end)
|
||||
|> maybe_put_title(html)
|
||||
|> maybe_put_description(html)
|
||||
|
||||
if Enum.empty?(meta_data) do
|
||||
{:error, error_message}
|
||||
else
|
||||
{:ok, meta_data}
|
||||
end
|
||||
end
|
||||
|
||||
defp get_elements(html, key_name, prefix) do
|
||||
html |> Floki.find("meta[#{key_name}^='#{prefix}:']")
|
||||
end
|
||||
|
||||
defp normalize_attributes(html_node, prefix, key_name, value_name) do
|
||||
{_tag, attributes, _children} = html_node
|
||||
|
||||
data =
|
||||
Enum.into(attributes, %{}, fn {name, value} ->
|
||||
{name, String.trim_leading(value, "#{prefix}:")}
|
||||
end)
|
||||
|
||||
%{String.to_atom(data[key_name]) => data[value_name]}
|
||||
end
|
||||
|
||||
defp maybe_put_title(%{title: _} = meta, _), do: meta
|
||||
|
||||
defp maybe_put_title(meta, html) when meta != %{} do
|
||||
case get_page_title(html) do
|
||||
"" -> meta
|
||||
title -> Map.put_new(meta, :title, title)
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_put_title(meta, _), do: meta
|
||||
|
||||
defp maybe_put_description(%{description: _} = meta, _), do: meta
|
||||
|
||||
defp maybe_put_description(meta, html) when meta != %{} do
|
||||
case get_page_description(html) do
|
||||
"" -> meta
|
||||
description -> Map.put_new(meta, :description, description)
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_put_description(meta, _), do: meta
|
||||
|
||||
defp get_page_title(html) do
|
||||
html |> Floki.find("html head title") |> List.first() |> Floki.text()
|
||||
end
|
||||
|
||||
defp get_page_description(html) do
|
||||
case html |> Floki.find("html head meta[name='description']") |> List.first() do
|
||||
nil -> ""
|
||||
elem -> Floki.attribute(elem, "content")
|
||||
end
|
||||
end
|
||||
end
|
||||
83
lib/service/rich_media/parsers/oembed_parser.ex
Normal file
83
lib/service/rich_media/parsers/oembed_parser.ex
Normal file
@@ -0,0 +1,83 @@
|
||||
# Portions of this file are derived from Pleroma:
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mobilizon.Service.RichMedia.Parsers.OEmbed do
|
||||
@moduledoc """
|
||||
Module to parse OEmbed data in HTML pages
|
||||
"""
|
||||
alias Mobilizon.Service.Formatter.HTML
|
||||
require Logger
|
||||
|
||||
@http_options [
|
||||
follow_redirect: true,
|
||||
ssl: [{:versions, [:"tlsv1.2"]}]
|
||||
]
|
||||
|
||||
def parse(html, _data) do
|
||||
Logger.debug("Using OEmbed parser")
|
||||
|
||||
with elements = [_ | _] <- get_discovery_data(html),
|
||||
{:ok, oembed_url} <- get_oembed_url(elements),
|
||||
{:ok, oembed_data} <- get_oembed_data(oembed_url),
|
||||
oembed_data <- filter_oembed_data(oembed_data) do
|
||||
Logger.debug("Data found with OEmbed parser")
|
||||
Logger.debug(inspect(oembed_data))
|
||||
{:ok, oembed_data}
|
||||
else
|
||||
_e ->
|
||||
{:error, "No OEmbed data found"}
|
||||
end
|
||||
end
|
||||
|
||||
defp get_discovery_data(html) do
|
||||
html |> Floki.find("link[type='application/json+oembed']")
|
||||
end
|
||||
|
||||
defp get_oembed_url(nodes) do
|
||||
{"link", attributes, _children} = nodes |> hd()
|
||||
|
||||
{:ok, Enum.into(attributes, %{})["href"]}
|
||||
end
|
||||
|
||||
defp get_oembed_data(url) do
|
||||
with {:ok, %HTTPoison.Response{body: json}} <- HTTPoison.get(url, [], @http_options),
|
||||
{:ok, data} <- Jason.decode(json),
|
||||
data <- data |> Map.new(fn {k, v} -> {String.to_atom(k), v} end) do
|
||||
{:ok, data}
|
||||
end
|
||||
end
|
||||
|
||||
defp filter_oembed_data(data) do
|
||||
case Map.get(data, :type) do
|
||||
nil ->
|
||||
{:error, "No type declared for OEmbed data"}
|
||||
|
||||
"link" ->
|
||||
Map.put(data, :image_remote_url, Map.get(data, :thumbnail_url))
|
||||
|
||||
"photo" ->
|
||||
if Map.get(data, :url, "") == "" do
|
||||
{:error, "No URL for photo OEmbed data"}
|
||||
else
|
||||
data
|
||||
|> Map.put(:image_remote_url, Map.get(data, :url))
|
||||
|> Map.put(:width, Map.get(data, :width, 0))
|
||||
|> Map.put(:height, Map.get(data, :height, 0))
|
||||
end
|
||||
|
||||
"video" ->
|
||||
{:ok, html} = data |> Map.get(:html, "") |> HTML.filter_tags_for_oembed()
|
||||
|
||||
data
|
||||
|> Map.put(:html, html)
|
||||
|> Map.put(:width, Map.get(data, :width, 0))
|
||||
|> Map.put(:height, Map.get(data, :height, 0))
|
||||
|> Map.put(:image_remote_url, Map.get(data, :thumbnail_url))
|
||||
|
||||
"rich" ->
|
||||
{:error, "OEmbed data has rich type, which we don't support"}
|
||||
end
|
||||
end
|
||||
end
|
||||
36
lib/service/rich_media/parsers/ogp.ex
Normal file
36
lib/service/rich_media/parsers/ogp.ex
Normal file
@@ -0,0 +1,36 @@
|
||||
# Portions of this file are derived from Pleroma:
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mobilizon.Service.RichMedia.Parsers.OGP do
|
||||
@moduledoc """
|
||||
Module to parse OpenGraph data in HTML pages
|
||||
"""
|
||||
require Logger
|
||||
alias Mobilizon.Service.RichMedia.Parsers.MetaTagsParser
|
||||
|
||||
def parse(html, data) do
|
||||
Logger.debug("Using OpenGraph card parser")
|
||||
|
||||
with {:ok, data} <-
|
||||
MetaTagsParser.parse(
|
||||
html,
|
||||
data,
|
||||
"og",
|
||||
"No OGP metadata found",
|
||||
"property"
|
||||
) do
|
||||
data = transform_tags(data)
|
||||
Logger.debug("Data found with OpenGraph card parser")
|
||||
{:ok, data}
|
||||
end
|
||||
end
|
||||
|
||||
defp transform_tags(data) do
|
||||
data
|
||||
|> Map.put(:image_remote_url, Map.get(data, :image))
|
||||
|> Map.put(:width, Map.get(data, :"image:width"))
|
||||
|> Map.put(:height, Map.get(data, :"image:height"))
|
||||
end
|
||||
end
|
||||
34
lib/service/rich_media/parsers/twitter_card.ex
Normal file
34
lib/service/rich_media/parsers/twitter_card.ex
Normal file
@@ -0,0 +1,34 @@
|
||||
# Portions of this file are derived from Pleroma:
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mobilizon.Service.RichMedia.Parsers.TwitterCard do
|
||||
@moduledoc """
|
||||
Module to parse Twitter tags data in HTML pages
|
||||
"""
|
||||
alias Mobilizon.Service.RichMedia.Parsers.MetaTagsParser
|
||||
require Logger
|
||||
|
||||
@spec parse(String.t(), map()) :: {:ok, map()} | {:error, String.t()}
|
||||
def parse(html, data) do
|
||||
Logger.debug("Using Twitter card parser")
|
||||
|
||||
res =
|
||||
data
|
||||
|> parse_name_attrs(html)
|
||||
|> parse_property_attrs(html)
|
||||
|
||||
Logger.debug("Data found with Twitter card parser")
|
||||
Logger.debug(inspect(res))
|
||||
res
|
||||
end
|
||||
|
||||
defp parse_name_attrs(data, html) do
|
||||
MetaTagsParser.parse(html, data, "twitter", %{}, "name")
|
||||
end
|
||||
|
||||
defp parse_property_attrs({_, data}, html) do
|
||||
MetaTagsParser.parse(html, data, "twitter", "No twitter card metadata found", "property")
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user