Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
3.8KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
  5. alias Pleroma.User
  6. alias Pleroma.Web.Metadata
  7. alias Pleroma.Web.Metadata.Providers.Provider
  8. alias Pleroma.Web.Metadata.Utils
  9. @behaviour Provider
  10. @media_types ["image", "audio", "video"]
  11. @impl Provider
  12. def build_tags(%{
  13. object: object,
  14. url: url,
  15. user: user
  16. }) do
  17. attachments = build_attachments(object)
  18. scrubbed_content = Utils.scrub_html_and_truncate(object)
  19. [
  20. {:meta,
  21. [
  22. property: "og:title",
  23. content: Utils.user_name_string(user)
  24. ], []},
  25. {:meta, [property: "og:url", content: url], []},
  26. {:meta,
  27. [
  28. property: "og:description",
  29. content: scrubbed_content
  30. ], []},
  31. {:meta, [property: "og:type", content: "article"], []}
  32. ] ++
  33. if attachments == [] or Metadata.activity_nsfw?(object) do
  34. [
  35. {:meta, [property: "og:image", content: Utils.attachment_url(User.avatar_url(user))],
  36. []},
  37. {:meta, [property: "og:image:width", content: 150], []},
  38. {:meta, [property: "og:image:height", content: 150], []}
  39. ]
  40. else
  41. attachments
  42. end
  43. end
  44. @impl Provider
  45. def build_tags(%{user: user}) do
  46. with truncated_bio = Utils.scrub_html_and_truncate(user.bio) do
  47. [
  48. {:meta,
  49. [
  50. property: "og:title",
  51. content: Utils.user_name_string(user)
  52. ], []},
  53. {:meta, [property: "og:url", content: user.uri || user.ap_id], []},
  54. {:meta, [property: "og:description", content: truncated_bio], []},
  55. {:meta, [property: "og:type", content: "article"], []},
  56. {:meta, [property: "og:image", content: Utils.attachment_url(User.avatar_url(user))], []},
  57. {:meta, [property: "og:image:width", content: 150], []},
  58. {:meta, [property: "og:image:height", content: 150], []}
  59. ]
  60. end
  61. end
  62. defp build_attachments(%{data: %{"attachment" => attachments}}) do
  63. Enum.reduce(attachments, [], fn attachment, acc ->
  64. rendered_tags =
  65. Enum.reduce(attachment["url"], [], fn url, acc ->
  66. # TODO: Whatsapp only wants JPEG or PNGs. It seems that if we add a second og:image
  67. # object when a Video or GIF is attached it will display that in Whatsapp Rich Preview.
  68. case Utils.fetch_media_type(@media_types, url["mediaType"]) do
  69. "audio" ->
  70. [
  71. {:meta, [property: "og:audio", content: Utils.attachment_url(url["href"])], []}
  72. | acc
  73. ]
  74. "image" ->
  75. [
  76. {:meta, [property: "og:image", content: Utils.attachment_url(url["href"])], []},
  77. {:meta, [property: "og:image:alt", content: attachment["name"]], []}
  78. | acc
  79. ]
  80. |> maybe_add_dimensions(url)
  81. "video" ->
  82. [
  83. {:meta, [property: "og:video", content: Utils.attachment_url(url["href"])], []}
  84. | acc
  85. ]
  86. |> maybe_add_dimensions(url)
  87. _ ->
  88. acc
  89. end
  90. end)
  91. acc ++ rendered_tags
  92. end)
  93. end
  94. defp build_attachments(_), do: []
  95. # We can use url["mediaType"] to dynamically fill the metadata
  96. defp maybe_add_dimensions(metadata, url) do
  97. type = url["mediaType"] |> String.split("/") |> List.first()
  98. cond do
  99. !is_nil(url["height"]) && !is_nil(url["width"]) ->
  100. metadata ++
  101. [
  102. {:meta, [property: "og:#{type}:width", content: "#{url["width"]}"], []},
  103. {:meta, [property: "og:#{type}:height", content: "#{url["height"]}"], []}
  104. ]
  105. true ->
  106. metadata
  107. end
  108. end
  109. end