Support OpenGraph video embeds (#4897)
* Support OpenGraph video embeds It's not really OpenGraph, it's twitter:player property, but it's not OEmbed so that fits. For example, this allows Twitch clips to be displayed as embeds. Also, fixes glitch-soc/mastodon#135 * Fix invalid OpenGraph cards being saved through attaching and revisit URLs after 14 days
This commit is contained in:
parent
4f0597d579
commit
596dab06e9
|
@ -1,6 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class FetchLinkCardService < BaseService
|
class FetchLinkCardService < BaseService
|
||||||
|
include ActionView::Helpers::TagHelper
|
||||||
|
|
||||||
URL_PATTERN = %r{https?://\S+}
|
URL_PATTERN = %r{https?://\S+}
|
||||||
|
|
||||||
def call(status)
|
def call(status)
|
||||||
|
@ -14,11 +16,11 @@ class FetchLinkCardService < BaseService
|
||||||
RedisLock.acquire(lock_options) do |lock|
|
RedisLock.acquire(lock_options) do |lock|
|
||||||
if lock.acquired?
|
if lock.acquired?
|
||||||
@card = PreviewCard.find_by(url: @url)
|
@card = PreviewCard.find_by(url: @url)
|
||||||
process_url if @card.nil?
|
process_url if @card.nil? || @card.updated_at <= 2.weeks.ago
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attach_card unless @card.nil?
|
attach_card if @card&.persisted?
|
||||||
rescue HTTP::ConnectionError, OpenSSL::SSL::SSLError
|
rescue HTTP::ConnectionError, OpenSSL::SSL::SSLError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
@ -26,8 +28,8 @@ class FetchLinkCardService < BaseService
|
||||||
private
|
private
|
||||||
|
|
||||||
def process_url
|
def process_url
|
||||||
@card = PreviewCard.new(url: @url)
|
@card ||= PreviewCard.new(url: @url)
|
||||||
res = Request.new(:head, @url).perform
|
res = Request.new(:head, @url).perform
|
||||||
|
|
||||||
return if res.code != 200 || res.mime_type != 'text/html'
|
return if res.code != 200 || res.mime_type != 'text/html'
|
||||||
|
|
||||||
|
@ -106,12 +108,25 @@ class FetchLinkCardService < BaseService
|
||||||
guess = detector.detect(html, response.charset)
|
guess = detector.detect(html, response.charset)
|
||||||
page = Nokogiri::HTML(html, nil, guess&.fetch(:encoding))
|
page = Nokogiri::HTML(html, nil, guess&.fetch(:encoding))
|
||||||
|
|
||||||
@card.type = :link
|
if meta_property(page, 'twitter:player')
|
||||||
@card.title = meta_property(page, 'og:title') || page.at_xpath('//title')&.content || ''
|
@card.type = :video
|
||||||
@card.description = meta_property(page, 'og:description') || meta_property(page, 'description') || ''
|
@card.width = meta_property(page, 'twitter:player:width') || 0
|
||||||
@card.image_remote_url = meta_property(page, 'og:image') if meta_property(page, 'og:image')
|
@card.height = meta_property(page, 'twitter:player:height') || 0
|
||||||
|
@card.html = content_tag(:iframe, nil, src: meta_property(page, 'twitter:player'),
|
||||||
|
width: @card.width,
|
||||||
|
height: @card.height,
|
||||||
|
allowtransparency: 'true',
|
||||||
|
scrolling: 'no',
|
||||||
|
frameborder: '0')
|
||||||
|
else
|
||||||
|
@card.type = :link
|
||||||
|
@card.image_remote_url = meta_property(page, 'og:image') if meta_property(page, 'og:image')
|
||||||
|
end
|
||||||
|
|
||||||
return if @card.title.blank?
|
@card.title = meta_property(page, 'og:title').presence || page.at_xpath('//title')&.content || ''
|
||||||
|
@card.description = meta_property(page, 'og:description').presence || meta_property(page, 'description') || ''
|
||||||
|
|
||||||
|
return if @card.title.blank? && @card.html.blank?
|
||||||
|
|
||||||
@card.save_with_optional_image!
|
@card.save_with_optional_image!
|
||||||
end
|
end
|
||||||
|
|
Reference in a new issue