Fix #5360: Use OpenGraph's og:image metadata for posts.
* Add og:image:width, og:image:height, and og:image:type tags. * Use og:video tags for videos. * Use 720x720 instead of 150x150 preview images for videos. * Add duration tag to JSON-LD data for videos. * Add OpenGraph tags to media assets show page. * Respect Twitter max image size limits. * Don't include OpenGraph image tags when someone shares a plain https://danbooru.donmai.us link with no tag search. This caused random potentially NSFW images to be shown when someone shared a https://danbooru.donmai.us link on social media, which could be cached for long periods of time.
This commit is contained in:
68
app/components/open_graph_component.rb
Normal file
68
app/components/open_graph_component.rb
Normal file
@@ -0,0 +1,68 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Render Open Graph metatags for an image or video.
|
||||
#
|
||||
# @see https://ogp.me/
|
||||
# @see https://www.opengraph.xyz/
|
||||
# @see https://developers.facebook.com/docs/sharing/webmasters/
|
||||
# @see https://developers.facebook.com/tools/debug/
|
||||
# @see https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started
|
||||
# @see https://developers.google.com/search/docs/appearance/structured-data
|
||||
# @see https://search.google.com/test/rich-results
|
||||
# @see https://validator.schema.org/
|
||||
class OpenGraphComponent < ApplicationComponent
|
||||
extend Memoist
|
||||
|
||||
attr_reader :media_asset, :current_user
|
||||
|
||||
delegate :json_ld_tag, :page_title, :meta_description, to: :helpers
|
||||
delegate :is_image?, :is_video?, :is_ugoira?, :image_width, :image_height, :file_size, :mime_type, :variant, :has_variant?, to: :media_asset
|
||||
|
||||
def initialize(media_asset:, current_user:)
|
||||
@media_asset = media_asset
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
memoize def video_url
|
||||
if is_video?
|
||||
variant("original").file_url
|
||||
elsif is_ugoira?
|
||||
variant("sample").file_url
|
||||
end
|
||||
end
|
||||
|
||||
memoize def image_url
|
||||
if is_image?
|
||||
variant("original").file_url
|
||||
elsif is_video? || is_ugoira?
|
||||
variant("720x720").file_url
|
||||
end
|
||||
end
|
||||
|
||||
# https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/summary-card-with-large-image
|
||||
#
|
||||
# Images for this Card support an aspect ratio of 2:1 with minimum dimensions of 300x157 or maximum of 4096x4096
|
||||
# pixels. Images must be less than 5MB in size. JPG, PNG, WEBP and GIF formats are supported. Only the first frame of
|
||||
# an animated GIF will be used. SVG is not supported.
|
||||
memoize def twitter_image_url
|
||||
if is_image? && file_size < 5.megabytes && image_width <= 4096 && image_height <= 4096
|
||||
variant("original").file_url
|
||||
elsif has_variant?("720x720")
|
||||
variant("720x720").file_url
|
||||
end
|
||||
end
|
||||
|
||||
# https://developers.google.com/search/docs/data-types/video#video-object
|
||||
def json_ld_video_data
|
||||
json_ld_tag({
|
||||
"@context": "https://schema.org",
|
||||
"@type": "VideoObject",
|
||||
name: page_title,
|
||||
description: meta_description,
|
||||
uploadDate: (media_asset.post || media_asset).created_at.iso8601,
|
||||
duration: media_asset.duration.seconds.iso8601,
|
||||
thumbnailUrl: image_url,
|
||||
contentUrl: video_url,
|
||||
})
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user