logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

opengraph.ex (4098B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 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. # Zero width space
  20. content =
  21. if scrubbed_content != "" and scrubbed_content != "\u200B" do
  22. ": “" <> scrubbed_content <> "”"
  23. else
  24. ""
  25. end
  26. # Most previews only show og:title which is inconvenient. Instagram
  27. # hacks this by putting the description in the title and making the
  28. # description longer prefixed by how many likes and shares the post
  29. # has. Here we use the descriptive nickname in the title, and expand
  30. # the full account & nickname in the description. We also use the cute^Wevil
  31. # smart quotes around the status text like Instagram, too.
  32. [
  33. {:meta,
  34. [
  35. property: "og:title",
  36. content: "#{user.name}" <> content
  37. ], []},
  38. {:meta, [property: "og:url", content: url], []},
  39. {:meta,
  40. [
  41. property: "og:description",
  42. content: "#{Utils.user_name_string(user)}" <> content
  43. ], []},
  44. {:meta, [property: "og:type", content: "website"], []}
  45. ] ++
  46. if attachments == [] or Metadata.activity_nsfw?(object) do
  47. [
  48. {:meta, [property: "og:image", content: Utils.attachment_url(User.avatar_url(user))],
  49. []},
  50. {:meta, [property: "og:image:width", content: 150], []},
  51. {:meta, [property: "og:image:height", content: 150], []}
  52. ]
  53. else
  54. attachments
  55. end
  56. end
  57. @impl Provider
  58. def build_tags(%{user: user}) do
  59. with truncated_bio = Utils.scrub_html_and_truncate(user.bio) do
  60. [
  61. {:meta,
  62. [
  63. property: "og:title",
  64. content: Utils.user_name_string(user)
  65. ], []},
  66. {:meta, [property: "og:url", content: user.uri || user.ap_id], []},
  67. {:meta, [property: "og:description", content: truncated_bio], []},
  68. {:meta, [property: "og:type", content: "website"], []},
  69. {:meta, [property: "og:image", content: Utils.attachment_url(User.avatar_url(user))], []},
  70. {:meta, [property: "og:image:width", content: 150], []},
  71. {:meta, [property: "og:image:height", content: 150], []}
  72. ]
  73. end
  74. end
  75. defp build_attachments(%{data: %{"attachment" => attachments}}) do
  76. Enum.reduce(attachments, [], fn attachment, acc ->
  77. rendered_tags =
  78. Enum.reduce(attachment["url"], [], fn url, acc ->
  79. # TODO: Add additional properties to objects when we have the data available.
  80. # Also, Whatsapp only wants JPEG or PNGs. It seems that if we add a second og:image
  81. # object when a Video or GIF is attached it will display that in Whatsapp Rich Preview.
  82. case Utils.fetch_media_type(@media_types, url["mediaType"]) do
  83. "audio" ->
  84. [
  85. {:meta, [property: "og:audio", content: Utils.attachment_url(url["href"])], []}
  86. | acc
  87. ]
  88. "image" ->
  89. [
  90. {:meta, [property: "og:image", content: Utils.attachment_url(url["href"])], []},
  91. {:meta, [property: "og:image:width", content: 150], []},
  92. {:meta, [property: "og:image:height", content: 150], []}
  93. | acc
  94. ]
  95. "video" ->
  96. [
  97. {:meta, [property: "og:video", content: Utils.attachment_url(url["href"])], []}
  98. | acc
  99. ]
  100. _ ->
  101. acc
  102. end
  103. end)
  104. acc ++ rendered_tags
  105. end)
  106. end
  107. defp build_attachments(_), do: []
  108. end