require 'hashie'
require 'nokogiri'
require 'restclient'
module OpenGraph
# Fetch Open Graph data from the specified URI. Makes an
# HTTP GET request and returns an OpenGraph::Object if there
# is data to be found or false if there isn't.
def self.fetch(uri)
parse(RestClient.get(uri).body)
rescue RestClient::Exception, SocketError
false
end
def self.parse(html)
doc = Nokogiri::HTML.parse(html)
page = OpenGraph::Object.new
doc.css('meta').each do |m|
if m.attribute('property') && m.attribute('property').to_s.match(/^og:(.+)$/i)
page[$1.gsub('-','_')] = m.attribute('content').to_s
end
end
return false unless page.valid?
page
end
TYPES = {
'activity' => %w(activity sport),
'business' => %w(bar company cafe hotel restaurant),
'group' => %w(cause sports_league sports_team),
'organization' => %w(band government non_profit school university),
'person' => %w(actor athlete author director musician politician public_figure),
'place' => %w(city country landmark state_province),
'product' => %w(album book drink food game movie product song tv_show),
'website' => %w(blog website)
}
# The OpenGraph::Object is a Hash with method accessors for
# all detected Open Graph attributes.
class Object < Hashie::Mash
MANDATORY_ATTRIBUTES = %w(title type image url)
# The object type.
def type
self['type']
end
# The schema under which this particular object lies. May be any of
# the keys of the TYPES constant.
def schema
OpenGraph::TYPES.each_pair do |schema, types|
return schema if types.include?(self.type)
end
nil
end
OpenGraph::TYPES.values.flatten.each do |type|
define_method "#{type}?" do
self.type == type
end
end
OpenGraph::TYPES.keys.each do |scheme|
define_method "#{scheme}?" do
self.type == scheme || OpenGraph::TYPES[scheme].include?(self.type)
end
end
# If the Open Graph information for this object doesn't contain
# the mandatory attributes, this will be false.
def valid?
MANDATORY_ATTRIBUTES.each{|a| return false unless self[a]}
true
end
end
end