app/embedders/oembed_embedder.rb
class OembedEmbedder < Embedder
def to_h
{
url: url,
kind: kind,
site: site,
title: oembed_data['title'],
image: image || thumbnail,
video: video
}.reject { |_k, v| v.blank? }
end
def match?
oembed_data.present?
end
private
# Get providers from the ProvidersList class
delegate :providers, to: :ProvidersList
# @return [String] the URL to get the oEmbed data
def oembed_url
# First try for json+oembed
html.at_css('link[rel=alternate][type$="json+oembed"]')&.[]('href') ||
# Look for anything ending with oembed
html.at_css('link[rel=alternate][type$=oembed]')&.[]('href') ||
# Check the global providers list
providers.for_url(url)
end
# @return [String] the oEmbed type converted to OpenGraph type
def kind
case oembed_data['type']
when 'photo' then 'image'
else oembed_data['type']
end
end
# @return [Hash] the information about the site
def site
{
name: oembed_data['provider_name'],
url: oembed_data['provider_url']
}.compact
end
# @return [Hash] the oEmbed thumbnail expressed as an opengraph image
def thumbnail
{
url: oembed_data['thumbnail_url'],
width: oembed_data['thumbnail_width'],
height: oembed_data['thumbnail_height']
}
end
# @return [Hash] the oEmbed image expressed as an opengraph image
def image
return unless kind == 'image'
{
url: oembed_data['url'],
width: oembed_data['width'],
height: oembed_data['height']
}
end
# @return [Hash, nil] the oEmbed video expressed as an opengraph video
def video
return unless kind == 'video'
video_frame = Nokogiri::HTML(oembed_data['html']).at_css('iframe')
return unless video_frame
{
url: video_frame['src'],
width: video_frame['width'],
height: video_frame['height'],
type: 'text/html'
}
end
def oembed_data
data = get(oembed_url)
return unless data
JSON.parse(data)
rescue JSON::ParserError
nil
end
end