defmodule Pleroma.Web.Metadata do
alias Phoenix.HTML
- alias Pleroma.{Formatter, User}
- alias Pleroma.Web.MediaProxy
- def build_tags(params) do
- if(meta_enabled?(:opengraph), do: opengraph_tags(params), else: [])
- |> Enum.map(&to_tag/1)
- |> Enum.map(&HTML.safe_to_string/1)
- |> Enum.join()
- end
+ @parsers Pleroma.Config.get([:metadata, :providers], [])
+ def get_cached_tags(%{activity: activity, user: user} = params) do
+ # We don't need to use the both activity and a user since the object can't change it's content
+ key = "#{:erlang.term_to_binary(user)}#{activity.data["id"]}"
- def meta_enabled?(type) do
- Pleroma.Config.get([:metadata, type], false)
+ Cachex.fetch!(:metadata_cache, key, fn _key ->
+ {:commit, build_tags(params)}
+ end)
end
- # opengraph for single status
- defp opengraph_tags(%{activity: activity, user: user}) do
- with truncated_content = scrub_html_and_truncate(activity.data["object"]["content"]) do
- [
- {:meta,
- [
- property: "og:title",
- content:
- "#{user.name}" <>
- if user.local do
- "(@#{user.nickname}@{pleroma_domain})"
- else
- "(@#{user.nickname})"
- end
- ], []},
- {:meta, [property: "og:url", content: activity.data["id"]], []},
- {:meta, [property: "og:description", content: truncated_content], []},
- {:meta, [property: "og:image", content: user_avatar_url(user)], []},
- {:meta, [property: "og:image:width", content: 120], []},
- {:meta, [property: "og:image:height", content: 120], []},
- {:meta, [property: "twitter:card", content: "summary"], []}
- ]
- end
+ def get_cached_tags(%{user: user} = params) do
+ # I am unsure how well ETS works with big keys
+ key = :erlang.term_to_binary(user)
+
+ Cachex.fetch!(:metadata_cache, key, fn _key ->
+ {:commit, build_tags(params)}
+ end)
end
- # opengraph for user card
- defp opengraph_tags(%{user: user}) do
- with truncated_bio = scrub_html_and_truncate(user.bio || "") do
- [
- {:meta,
- [
- property: "og:title",
- content: "#{user.name} (@#{user.nickname}@#{pleroma_domain()}) profile"
- ], []},
- {:meta, [property: "og:url", content: User.profile_url(user)], []},
- {:meta, [property: "og:description", content: truncated_bio], []},
- {:meta, [property: "og:image", content: user_avatar_url(user)], []},
- {:meta, [property: "og:image:width", content: 120], []},
- {:meta, [property: "og:image:height", content: 120], []},
- {:meta, [property: "twitter:card", content: "summary"], []}
- ]
- end
+ def get_cached_tags(params) do
+ key = :erlang.term_to_binary(params)
+
+ Cachex.fetch!(:metadata_cache, key, fn _key ->
+ {:commit, build_tags(params)}
+ end)
end
- defp opengraph_tags(_) do
- []
+ def build_tags(params) do
+ Enum.reduce(@parsers, "", 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
raise ArgumentError, message: "make_tag invalid args"
end
end
-
- defp scrub_html_and_truncate(content) do
- content
- # html content comes from DB already encoded, decode first and scrub after
- |> HtmlEntities.decode()
- |> Pleroma.HTML.strip_tags()
- |> Formatter.truncate()
- end
-
- defp user_avatar_url(user) do
- User.avatar_url(user) |> MediaProxy.url()
- end
-
- def pleroma_domain do
- Pleroma.Web.Endpoint.host()
- end
end