* Send user agent in open graph fetch * Update app/services/open_graph.rb Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Change user agent and test --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
100 lines
2.5 KiB
Ruby
100 lines
2.5 KiB
Ruby
# This class provides methods for getting structured metadata properties for
|
|
# Open Graph usage
|
|
|
|
# @note A wrapper around the metainspector gem
|
|
class OpenGraph
|
|
delegate :meta, :meta_tags, :images, to: :page
|
|
delegate :favicon, to: :images
|
|
|
|
attr_reader :page, :tags
|
|
|
|
DEFAULT_METHODS = %i[description title url].freeze
|
|
CACHE_EXPIRY_IN_MINUTES = 15
|
|
|
|
def initialize(url)
|
|
html = fetch_html(url)
|
|
@page = MetaInspector.new(url, document: html)
|
|
@tags = meta_tags
|
|
end
|
|
|
|
# the optional "use_best" argument is used to determine if we should use the
|
|
# "best" option availabile for said method this works by picking the most
|
|
# available (first?) title, description, or author (respectively), if defined
|
|
# with the og:* or twitter:* metatags. example page.title(true) would look in
|
|
# said areas. the default only looks at the head or default metatag.
|
|
|
|
DEFAULT_METHODS.each do |method_name|
|
|
define_method(method_name) do |use_best = false|
|
|
if use_best
|
|
page.public_send("best_#{method_name}".to_sym)
|
|
else
|
|
page.public_send(method_name)
|
|
end
|
|
end
|
|
end
|
|
|
|
def meta_for(data)
|
|
page.meta[data]
|
|
end
|
|
|
|
def image
|
|
page.images.best
|
|
end
|
|
|
|
def properties
|
|
return {} if tags["property"].blank?
|
|
|
|
tags["property"]
|
|
end
|
|
|
|
def main_properties
|
|
# QUESTION: If we don't have `og:url` could we infer the url based on what was passed?
|
|
%w[og:title og:url]
|
|
end
|
|
|
|
def main_properties_present?
|
|
(main_properties - properties.keys).empty?
|
|
end
|
|
|
|
def preferred_desc
|
|
properties["og:description"].first || page.description
|
|
end
|
|
|
|
# this method groups like-properties, making it a little easier to determine
|
|
# the high level properties available for use. All "fb", "og", etc properties
|
|
# will be grouped by their respective key
|
|
def grouped_properties
|
|
return {} if properties.blank?
|
|
|
|
group(properties)
|
|
end
|
|
|
|
def grouped_meta
|
|
return {} if meta.blank?
|
|
|
|
group(meta)
|
|
end
|
|
|
|
def twitter
|
|
return {} unless grouped_meta.key?("twitter")
|
|
|
|
grouped_meta["twitter"]
|
|
end
|
|
|
|
private
|
|
|
|
def fetch_html(url)
|
|
Rails.cache.fetch("#{url}_open_graph_html", expires_in: CACHE_EXPIRY_IN_MINUTES.minutes) do
|
|
response = HTTParty.get(url, headers: { "User-Agent" => "#{Settings::Community.community_name} (#{URL.url})" })
|
|
response&.body
|
|
end
|
|
end
|
|
|
|
def group(data)
|
|
data.each_with_object({}) do |(key, value), hash|
|
|
group_key = key.split(":").first
|
|
hash[group_key] ||= {}
|
|
hash[group_key][key] = value
|
|
end
|
|
end
|
|
end
|