1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
#require 'rubygems'
require 'yaml'
module OEmbed
# Allows OEmbed to perform tasks across several, registered, Providers
# at once.
class Providers
class << self
@@urls = {}
@@fallback = []
@@to_register = {}
@@access_token_setters = {}
# A Hash of all url schemes, where the keys represent schemes supported by
# all registered Provider instances and values are an Array of Providers
# that support that scheme.
def urls
@@urls
end
# Given one ore more Provider instances, register their url schemes for
# future get calls.
def register(*providers)
providers.each do |provider|
provider.urls.each do |url|
@@urls[url] ||= []
@@urls[url] << provider
end
end
end
# Given one ore more Provider instances, un-register their url schemes.
# Future get calls will not use these Providers.
def unregister(*providers)
providers.each do |provider|
provider.urls.each do |url|
if @@urls[url].is_a?(Array)
@@urls[url].delete(provider)
@@urls.delete(url) if @@urls[url].empty?
end
end
end
end
# Register all Providers built into this gem.
# The including_sub_type parameter should be one of the following values:
# * :aggregators: also register provider aggregator endpoints, like Embedly
# The access_tokens keys can be one of the following:
# * :facebook: See https://developers.facebook.com/docs/instagram/oembed#access-tokens
def register_all(*including_sub_type, access_tokens: {})
register(*@@to_register[""])
including_sub_type.each do |sub_type|
register(*@@to_register[sub_type.to_s])
end
set_access_tokens(access_tokens)
end
# Unregister all currently-registered Provider instances.
def unregister_all
@@urls = {}
@@fallback = []
end
# Takes an array of Provider instances or ProviderDiscovery
# Use this method to register fallback providers.
# When the raw or get methods are called, if the URL doesn't match
# any of the registerd url patters the fallback providers
# will be called (in order) with the URL.
#
# A common example:
# OEmbed::Providers.register_fallback(OEmbed::ProviderDiscovery, OEmbed::Providers::Noembed)
def register_fallback(*providers)
@@fallback += providers
end
# Returns an array of all registerd fallback Provider instances.
def fallback
@@fallback
end
# Returns a Provider instance whose url scheme matches the given url.
# Skips any Provider with missing required_query_params.
def find(url)
@@urls.keys.each do |url_regexp|
next unless url_regexp.match?(url)
matching_provider = @@urls[url_regexp].detect { |p| p.include?(url) }
# If we've found a matching provider, return it right away!
return matching_provider if matching_provider
end
nil
end
# Finds the appropriate Provider for this url and return the raw response.
# @deprecated *Note*: This method will be made private in the future.
def raw(url, options = {})
provider = find(url)
if provider
provider.raw(url, options)
else
fallback.each do |p|
return p.raw(url, options) rescue OEmbed::Error
end
raise(OEmbed::NotFound)
end
end
# Finds the appropriate Provider for this url and returns an OEmbed::Response,
# using Provider#get.
def get(url, options = {})
provider = find(url)
if provider
provider.get(url, options)
else
fallback.each do |p|
return p.get(url, options) rescue OEmbed::Error
end
raise(OEmbed::NotFound)
end
end
private
# Takes an OEmbed::Provider instance and registers it so that when we call
# the register_all method, they all register.
# The sub_type can be be any value
# used to uniquely group providers. Official sub_types are:
# * nil: a normal provider
# * :aggregators: an endpoint for an OEmbed aggregator
# :access_token takes a Hash with the following required keys:
# * :name: A Symbol: the name of access token, to be used with `register_all`
# * :method: A Symbol: the name of the required_query_params for the access token.
def add_official_provider(provider_class, sub_type=nil, access_token: nil)
raise TypeError, "Expected OEmbed::Provider instance but was #{provider_class.class}" \
unless provider_class.is_a?(OEmbed::Provider)
@@to_register[sub_type.to_s] ||= []
@@to_register[sub_type.to_s] << provider_class
if access_token.is_a?(Hash) && access_token[:name] && access_token[:method]
setter_method = "#{access_token[:method]}="
raise TypeError, "Expected OEmbed::Provider instance to respond to the given access_token method #{setter_method}" \
unless provider_class.respond_to?(setter_method)
@@access_token_setters[access_token[:name]] ||= []
@@access_token_setters[access_token[:name]] << provider_class.method(setter_method)
end
end
# Takes a Hash of tokens, and calls the setter method
# for all providers that use the given tokens.
# Also supports "OEMBED_*_TOKEN" environment variables.
# Currently supported tokens:
# * facebook: See https://developers.facebook.com/docs/instagram/oembed#access-tokens
def set_access_tokens(access_tokens)
access_tokens.each do |token_name, token_value|
token_name = token_name.to_sym
next unless @@access_token_setters.has_key?(token_name)
@@access_token_setters[token_name].each do |token_setter_method|
token_setter_method.call(token_value)
end
end
end
end
end
end
|