netshade-oembed_links 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,68 @@
1
+ This is the oembed_links gem. It allows you to easily parse text and
2
+ query configured providers for embedding information on the links
3
+ inside the text. A sample configuration file for configuring the
4
+ library has been included (oembed_links_example.yml), though you
5
+ may also configure the library programmatically (see rdocs).
6
+
7
+
8
+
9
+ To get started quickly (in irb):
10
+
11
+ require 'oembed_links'
12
+ OEmbed.register({:method => "NetHTTP"},
13
+ {:flickr => "http://www.flickr.com/services/oembed/",
14
+ :vimeo => "http://www.vimeo.com/api/oembed.{format}"},
15
+ {:flickr => { :format => "xml", :schemes => ["http://www.flickr.com/photos/*"]},
16
+ :vimeo => { :format => "json", :schemes => ["http://www.vimeo.com/*"]}})
17
+
18
+ # Simple transformation
19
+ OEmbed.transform("This is my flickr URL http://www.flickr.com/photos/bees/2341623661/ and all I did was show the URL straight to the picture")
20
+
21
+ # More complex transformation
22
+ OEmbed.transform("This is my flickr URL http://www.flickr.com/photos/bees/2341623661/ and this is a vimeo URL http://www.vimeo.com/757219 wow neat") do |r, url|
23
+ r.audio? { |a| "It's unlikely flickr or vimeo will give me audio" }
24
+ r.photo? { |p| "<img src='#{p["url"]}' alt='Sweet, a photo named #{p["title"]}' />" }
25
+ r.from?(:vimeo) { |v| "<div class='vimeo'>#{v['html']}</div>" }
26
+ end
27
+
28
+ # Transformation to drive affiliate links to Amazon to our department and help us buy some laptops (hint)
29
+ OEmbed.register_provider(:oohembed,
30
+ "http://oohembed.com/oohembed/",
31
+ "json",
32
+ "http://*.amazon.(com|co.uk|de|ca|jp)/*/(gp/product|o/ASIN|obidos/ASIN|dp)/*",
33
+ "http://*.amazon.(com|co.uk|de|ca|jp)/(gp/product|o/ASIN|obidos/ASIN|dp)/*")
34
+ OEmbed.transform("Here is a link to amazon http://www.amazon.com/Complete-Aubrey-Maturin-Novels/dp/039306011X/ref=pd_bbs_sr_2 wow") do |res, url|
35
+ res.matches?(/amazon/) { |d|
36
+ unless url =~ /(&|\?)tag=[^&]+/i
37
+ url += ((url.index("?")) ? "&" : "?")
38
+ url += "tag=wwwindystarco-20"
39
+ end
40
+ <<-EOHTML
41
+ <div style="text-align:center;">
42
+ <a href='#{url}' target='_blank'>
43
+ <img src='#{d['thumbnail_url']}' border='0' /><br />
44
+ #{d['title']} #{"<br />by #{d['author']}" if d['author']}
45
+ </a>
46
+ </div>
47
+ EOHTML
48
+ }
49
+ end
50
+
51
+
52
+ To get started quickly in Rails:
53
+
54
+ Copy the included oembed_links_example.yml file to RAILS_ROOT/config/oembed_links.yml,
55
+ add a dependency to the gem in your environment.rb ( config.gem "oembed_links" )
56
+ and start your server. That's it.
57
+
58
+
59
+
60
+
61
+ See the rdocs for much more complete examples. The specs directory has some examples of programmatic
62
+ use, but the test to code ratio is slim atm.
63
+
64
+ Thanks to the Indianapolis Star I&D department for open sourcing this; most notably Chris Vannoy for giving the okay.
65
+
66
+
67
+ CZ - chris.zelenak!at!!indystar.com
68
+
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ Gem::manage_gems
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ CLEAN.include("pkg")
6
+
7
+ spec = eval(File.read("oembed_links.gemspec")) # I'm going to hell, etc. etc.
8
+
9
+ task :default => [:clean, :repackage]
10
+
11
+ Rake::GemPackageTask.new(spec) do |pkg|
12
+ pkg.need_tar = true
13
+ end
14
+
@@ -0,0 +1,19 @@
1
+ require 'net/http'
2
+
3
+ class OEmbed
4
+ module Fetchers
5
+ class NetHTTP
6
+
7
+ def name
8
+ "NetHTTP"
9
+ end
10
+
11
+ def fetch(url)
12
+ Net::HTTP.get(URI.parse(url))
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+
19
+ OEmbed.register_fetcher(OEmbed::Fetchers::NetHTTP)
@@ -0,0 +1,18 @@
1
+ require 'json'
2
+
3
+ class OEmbed
4
+ module Formatters
5
+ class JSON
6
+
7
+ def name
8
+ "json"
9
+ end
10
+
11
+ def format(txt)
12
+ ::JSON.parse(txt)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ OEmbed.register_formatter(OEmbed::Formatters::JSON)
@@ -0,0 +1,36 @@
1
+ require 'libxml'
2
+
3
+ class OEmbed
4
+ module Formatters
5
+ class LibXML
6
+
7
+ def name
8
+ "xml"
9
+ end
10
+
11
+ # This is an extremely naive XML doc to hash
12
+ # formatter. Cases like arrays represented in
13
+ # XML will not work; only strings, ints and
14
+ # floats will be converted.
15
+ def format(txt)
16
+ parser = LibXML::XML::Parser.string(txt)
17
+ doc = parser.parse
18
+ h = { }
19
+ doc.root.children.each do |node|
20
+ unless node.name.strip.empty?
21
+ c = node.content
22
+ if c =~ /^[0-9]+$/
23
+ c = c.to_i
24
+ elsif c=~ /^[0-9]+\.[0-9]+$/
25
+ c = c.to_f
26
+ end
27
+ h[node.name.strip] = c
28
+ end
29
+ end
30
+ return h
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ OEmbed.register_formatter(OEmbed::Formatters::LibXML)
@@ -0,0 +1,102 @@
1
+ # The class used to represent data returned by the server.
2
+ #
3
+ class OEmbed
4
+ class Response
5
+
6
+ def initialize(provider, url, response_object)
7
+ @provider = provider
8
+ @url = url
9
+ @response = response_object
10
+ @rendered_via_provider = @rendered_via_regex = @rendered_via_type = false
11
+ @rendered = nil
12
+ end
13
+
14
+ def to_s
15
+ @response["html"] || @response["url"]
16
+ end
17
+
18
+ # If no content has been explicitly rendered for this Response,
19
+ # the default representation of the data will be returned.
20
+ def rendered_content
21
+ @rendered || self.to_s
22
+ end
23
+
24
+ # Test if this response has been returned from
25
+ # the given provider_name.
26
+ def from?(provider_name, &block)
27
+ if @provider.to_s === provider_name.to_s
28
+ if can_render_type?(:provider)
29
+ @rendered_via_provider = true
30
+ return render_content(&block)
31
+ end
32
+ end
33
+ end
34
+
35
+ # Test if this response came from a URL
36
+ # that matches the given regex.
37
+ def matches?(regex, &block)
38
+ if @url =~ regex
39
+ if can_render_type?(:regex)
40
+ @rendered_via_regex = true
41
+ render_content(&block)
42
+ end
43
+ end
44
+ end
45
+
46
+ # Lowest priority renderer, which will execute
47
+ # a block regardless of conditions so long as
48
+ # no content has yet been rendered for this response.
49
+ def any?(&block)
50
+ if can_render_type?
51
+ return render_content(&block)
52
+ end
53
+ end
54
+
55
+ # Provides the mechanism to allow .audio?, .video?
56
+ # and other .type? checking methods. The value of the
57
+ # method name will be compared against the "type" field
58
+ # from the returned server data.
59
+ def method_missing(msym, *args, &block)
60
+ mname = msym.to_s
61
+ if mname[mname.size - 1, mname.size] == "?"
62
+ ts = mname[0..mname.size - 2]
63
+ if @response["type"] == ts
64
+ if can_render_type?(:type)
65
+ @rendered_via_type = true
66
+ return render_content(&block)
67
+ end
68
+ end
69
+ else
70
+ raise NoMethodError.new("No such method #{msym.to_s}", msym, *args)
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ # Needlessly stupid priority for rendering.
77
+ def can_render_type?(type = nil)
78
+ if type == :provider
79
+ !@rendered_via_provider
80
+ elsif type == :regex
81
+ !@rendered_via_provider && !@rendered_via_regex
82
+ elsif type == :type
83
+ !@rendered_via_provider && !@rendered_via_regex && !@rendered_via_type
84
+ else
85
+ !has_rendered?
86
+ end
87
+ end
88
+
89
+ def has_rendered?
90
+ !@rendered.nil?
91
+ end
92
+
93
+ def render_content(&block)
94
+ if block_given?
95
+ @rendered = yield(@response)
96
+ else
97
+ @rendered = self.to_s
98
+ end
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,307 @@
1
+ require 'cgi'
2
+ require 'uri'
3
+ require 'yaml'
4
+ require 'oembed_links/response'
5
+
6
+ # The OEmbed class is the interface to class registration functions
7
+ # such as register_provider, register_formatter, etc., as well as
8
+ # the seat of the main .transform() function. If you are using OEmbed
9
+ # inside a Rails application, the process of initialization will be
10
+ # handled for you by the init.rb file. Create a file called
11
+ # oembed_links.yml inside your RAILS_ROOT/config directory, giving it
12
+ # a format like:
13
+ #
14
+ # :config:
15
+ # :method: "NetHTTP"
16
+ #
17
+ # :providers:
18
+ # :provider_1: "http://provider1.com/oembed.{format}"
19
+ # :provider_2: "http://provider2.com/oembed.{format}"
20
+ #
21
+ # :provider_1:
22
+ # :format: "json"
23
+ # :schemes:
24
+ # - "http://provider1.com/links/*/user/*"
25
+ # - "http://provider1.com/photos/*/user/*"
26
+ #
27
+ # :provider_2:
28
+ # :format: "xml"
29
+ # :schemes:
30
+ # - "http://provider2.com/videos/*"
31
+ #
32
+ #
33
+ # If you are not using the library in a Rails app, you can still create
34
+ # a YAML file like above and register it using OEmbed.register_yaml_file("/path/to/file.yml")
35
+ #
36
+ # You may also programmatically register information into the app using the
37
+ # register function, which takes a hash of configuration options, a
38
+ # provider hash, and the provider scheme hash.
39
+ #
40
+ # You may also register providers ad hoc using the OEmbed.register_provider
41
+ # function.
42
+ #
43
+ # To transform text, use the OEmbed.transform function, like:
44
+ #
45
+ # OEmbed.transform("This is my text and here's a picture http://www.flickr.com/path/to/a/photo")
46
+ #
47
+ # OEmbed.transform("Same text http://youtube.com/videos/somevideo") do |r, url|
48
+ # r.from?(:youtube) { |vid| vid["html"] }
49
+ # end
50
+ #
51
+ # See the OEmbed.transform function for more details.
52
+ #
53
+ #
54
+ # The OEmbed library by default uses net/http, libxml and json libraries for
55
+ # fetching network data, parsing xml and parsing json, respectively. These
56
+ # libraries are loaded by default.
57
+ #
58
+ # If you want to write your own mechanism for fetching HTTP data, parsing XML
59
+ # data, JSON data, or some other format, see the OEmbed::Fetchers::NetHTTP and
60
+ # OEmbed::Formatters::JSON for simple examples in terms of API. Once your new
61
+ # class mirrors these classes, you can register it with OEmbed by using
62
+ # OEmbed.register_formatter(class) or OEmbed.register_fetcher(class).
63
+ #
64
+ # NOTE that the default formatters and fetcher are EXTREMELY naive. There is no
65
+ # attempt at error handling, connection timeouts, or the like. If you need richer
66
+ # functionality you should subclass the existing formatters / fetchers and register them.
67
+ #
68
+ class OEmbed
69
+
70
+ # Configure OEmbed with all necessary information - library configuration,
71
+ # oembed provider urls, and the supported schemes and formats of said providers.
72
+ #
73
+ # The configuration hash should follow the form:
74
+ # { :method => "NameOfFetcher" }
75
+ # Note that the name of the fetcher is NOT the classname, but the arbitrarily
76
+ # chosen name provided by that class' .name() method. By default, it will
77
+ # be NetHTTP.
78
+ #
79
+ # The provider hash will be a hash where the keys are the symbolic names of the
80
+ # providers, eg. :vimeo, and the values are the URL strings used to query those providers.
81
+ # You may use the substring {format} inside these URLs to indicate that the
82
+ # given provider URL requires the format desired to be inserted at that point.
83
+ # Whatever format you have configured that provider for in the provider_scheme_hash
84
+ # will be inserted when they are queried.
85
+ #
86
+ # The provider_scheme_hash is a hash with two keys - the first key is the format
87
+ # key, which will either be the string "json" or the string "xml". The other
88
+ # key will be the schemes key, which contains an array of supported URL schemes
89
+ # by the provider.
90
+ #
91
+ # It is assumed that all hashes passed in use symbols for keys. Do not use string
92
+ # keys. This decision is totally arbitrary and without any technical merit.
93
+ #
94
+ # It is assumed that all provider names are symbols. Same rules as above.
95
+ #
96
+ def self.register(config_hash = { }, provider_hash = { }, provider_scheme_hash = { })
97
+ @fetch_method = (config_hash[:method] || "NetHTTP")
98
+ @config = config_hash
99
+ provider_hash.each do |provider, url|
100
+ config = provider_scheme_hash[provider]
101
+ raise "No Schemes were provided for #{provider.to_s}" if config.nil? ||
102
+ config[:schemes].nil? ||
103
+ config[:schemes].empty?
104
+ self.register_provider(provider, url, config[:format] || "json", *config[:schemes])
105
+ end
106
+ end
107
+
108
+ # The configuration hash passed into register() or parsed from the YAML file
109
+ def self.config
110
+ @config
111
+ end
112
+
113
+ # Register a provider with OEmbed. The provider name should be a symbol,
114
+ # like :flickr. The URL should be a string representing the endpoint
115
+ # for that provider, and may include the {format} substring to indicate
116
+ # how that provider should be notified of the desired format.
117
+ # format is either the string "json", or the string "xml".
118
+ # The list of schemes is an array of strings representing the different
119
+ # URL schemes supported by the provider. These strings follow the form:
120
+ #
121
+ # http://*.somedomain.*/*/*
122
+ #
123
+ # All schemes should use * to indicate variable text matched until the
124
+ # next non-* character or end of line.
125
+ def self.register_provider(provider, url, format = "json", *schemes)
126
+ @schemes ||= [ ]
127
+ @urls ||= { }
128
+ @formats ||= { }
129
+
130
+ @formats[provider] = format
131
+ @urls[provider] = url.gsub(/\{format\}/i, format)
132
+ schemes.each do |scheme|
133
+ sanitized_scheme = scheme.gsub(/([\.\?])/) { |str| "\\#{$1}" }.gsub(/\*/, '.+?')
134
+ @schemes << [Regexp.new("^" + sanitized_scheme + "$"), provider]
135
+ end
136
+ end
137
+
138
+ # Loads the YAML file at the specified path and registers
139
+ # its information with OEmbed.
140
+ def self.register_yaml_file(file)
141
+ y = YAML.load(File.read(file))
142
+ self.register(y.delete(:config),
143
+ y.delete(:providers),
144
+ y)
145
+ end
146
+
147
+ # Clear all registration information; really only valuable in testing
148
+ def self.clear_registrations
149
+ @schemes = []
150
+ @urls = { }
151
+ @formats = { }
152
+ @formatters = { }
153
+ @fetchers = { }
154
+ self.register_formatter(OEmbed::Formatters::LibXML)
155
+ self.register_formatter(OEmbed::Formatters::JSON)
156
+ self.register_fetcher(OEmbed::Fetchers::NetHTTP)
157
+ end
158
+
159
+ # Register a new formatter. klass is the class object of the desired formatter.
160
+ # A new instance of klass will be created and stored. This instance MUST
161
+ # respond to the methods "name" and "format".
162
+ def self.register_formatter(klass)
163
+ @formatters ||= { }
164
+ inst = klass.new
165
+ @formatters[inst.name] = inst
166
+ end
167
+
168
+ # Register a new fetcher. klass is the class object of the desired fetcher.
169
+ # A new instance of klass will be created and stored. This instance MUST
170
+ # respond to the methods "name" and "fetch".
171
+ def self.register_fetcher(klass)
172
+ @fetchers ||= { }
173
+ inst = klass.new
174
+ @fetchers[inst.name] = inst
175
+ end
176
+
177
+ # Get the OEmbed::Response object for a given URL and provider. If you wish
178
+ # to pass extra attributes to the provider, provide a hash as the last attribute
179
+ # with keys and values representing the keys and values of the added querystring
180
+ # parameters.
181
+ def self.get_url_for_provider(url, provider, *attribs)
182
+ purl = @urls[provider]
183
+ eurl = CGI.escape(url)
184
+ purl += (purl.index("?")) ? "&" : "?"
185
+ purl += "url=#{eurl}"
186
+ attrib_hash = (attribs.last.is_a?(Hash)) ? attribs.last : { }
187
+ attrib_hash.each do |k, v|
188
+ purl += "&#{CGI.escape(k)}=#{CGI.escape(v)}"
189
+ end
190
+ fetcher = @fetchers[@fetch_method] || @fetchers[@fetchers.keys.first]
191
+ formatter = @formatters[@formats[provider]]
192
+ response = fetcher.fetch(purl)
193
+ formatter.format(response)
194
+ end
195
+
196
+ # Transform all URLs supported by configured providers by the passed-in
197
+ # block or by outputting their "html" attributes ( or "url" attributes
198
+ # if no "html" attribute exists ). You may pass in a hash to specify
199
+ # extra parameters that should be appended to the querystrings to any
200
+ # matching providers (see OEmbed.get_url_for_provider). If you pass a
201
+ # block to this method, that block will be executed for each URL
202
+ # found in txt that has a matching provider. This block will be passed
203
+ # the OEmbed::Response object representing the embedding information for that
204
+ # url.
205
+ #
206
+ # OEmbed.transform supports two additional parameters:
207
+ #
208
+ # use_strict: Optionally use Ruby's stricter URI detection regex. While
209
+ # this will be technically correct regex, not all URLs
210
+ # use correct syntax. If this is false, URLs will be detected
211
+ # by the incredibly naive approach of finding any instance of
212
+ # http:// or https://, and finding anything that is not whitespace
213
+ # after that.
214
+ #
215
+ # Example:
216
+ # OEmbed.transform("all my urls are correctly formed", true)
217
+ #
218
+ # (options hash): This hash is used to append extra querystring parameters
219
+ # to the oembed provider. For example:
220
+ # OEmbed.transform("blah", false, :max_width => 320, :max_height => 200)
221
+ #
222
+ # You may fine tune the appearance of the embedding information by using the
223
+ # following forms:
224
+ #
225
+ # OEmbed.transform(some_string) do |r, url|
226
+ # r.from?(:provider_name) { |content| content["html"] }
227
+ # r.matches?(/some_regex_against_the_url/) { |content| content["title"] }
228
+ # r.video? { |video| content["html"] }
229
+ # r.audio? { |audio| content["html"] }
230
+ # r.hedgehog? { |hog| content["title"] }
231
+ # r.photo? { |photo| "<img src='#{photo["url"]}' title='#{photo['title']} />" }
232
+ # r.any? { |anythingelse| content["title"] }
233
+ # end
234
+ #
235
+ # The priority of these conditions is as follows:
236
+ # The first matching block for provider (.from?(:provider_name)) takes precendence OVER
237
+ # The first matching block for a URL regex (.matches?(/some_regex_against_the_url/)) takes precedence OVER
238
+ # The first matching block for a type equivalent (.video?, .audio?, .hedgehog?, .photo?) takes precendence OVER
239
+ # The match anything block (.any?)
240
+ #
241
+ #
242
+ #
243
+ #
244
+ # You do not need to specify an .any? block if you do not intend to perform any special
245
+ # transformations upon its data; the OEmbed::Response object will output either its html attribute
246
+ # (if it exists) or its url attribute.
247
+ #
248
+ # The value passed to these conditional blocks is a hash representing the data returned
249
+ # by the server. The keys of all the attributes will be strings.
250
+ #
251
+ # NOTE: The type equivalent blocks (.video?, .audio?, .hedgehog?, .photo?, etc.) perform
252
+ # an equality test between the method name and the type returned by the OEmbed provider.
253
+ # You may specify any type name you wish as the method name, and its type will be checked
254
+ # appropriately (as shown by the obviously trivial .hedgehog? method name).
255
+ #
256
+ def self.transform(txt, use_strict = false, *attribs, &block)
257
+ ret = txt.dup
258
+
259
+ if use_strict
260
+ URI.extract(txt, "http") do |u|
261
+ transform_url_for_text!(u, ret, *attribs, &block)
262
+ end
263
+ else
264
+ simple_extract(txt) do |u|
265
+ transform_url_for_text!(u, ret, *attribs, &block)
266
+ end
267
+ end
268
+
269
+ return ret
270
+ end
271
+
272
+ private
273
+
274
+ # stupid simple copy of URI.extract to allow for looser URI detection
275
+ def self.simple_extract(str, &block)
276
+ reg = /(https?:\/\/[^\s]+)/i
277
+ if block_given?
278
+ str.scan(reg) { yield $& }
279
+ nil
280
+ else
281
+ result = []
282
+ str.scan(reg) { result.push $& }
283
+ result
284
+ end
285
+ end
286
+
287
+ # extraction of inner loop of .transform(), to allow for easier
288
+ # parameterization of OEmbed
289
+ def self.transform_url_for_text!(u, txt, *attribs, &block)
290
+ unless (vschemes = @schemes.select { |a| u =~ a[0] }).empty?
291
+ regex, provider = vschemes.first
292
+ data = get_url_for_provider(u, provider, *attribs)
293
+ response = OEmbed::Response.new(provider, u, data)
294
+ if block.nil?
295
+ txt.gsub!(u, response.to_s)
296
+ else
297
+ yield(response, u)
298
+ txt.gsub!(u, response.rendered_content)
299
+ end
300
+ end
301
+ end
302
+
303
+
304
+ end
305
+ require 'oembed_links/formatters/json'
306
+ require 'oembed_links/formatters/xml'
307
+ require 'oembed_links/fetchers/net_http'
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "oembed_links"
3
+ s.version = "0.0.3"
4
+ s.author = "Indianapolis Star"
5
+ s.email = "bugs at indystar dot com"
6
+ s.homepage = "http://www.indystar.com"
7
+ s.platform = Gem::Platform::RUBY
8
+ s.summary = "a library for using the OEmbed format (http://oembed.com/) to acquire embedding information for freetext"
9
+ s.files = ["Rakefile", "README", "oembed_links_example.yml", "oembed_links.gemspec", "lib", "lib/oembed_links.rb", "lib/oembed_links", "lib/oembed_links/formatters", "lib/oembed_links/fetchers", "lib/oembed_links/response.rb", "lib/oembed_links/formatters/json.rb", "lib/oembed_links/formatters/xml.rb", "lib/oembed_links/fetchers/net_http.rb", "rails", "rails/init.rb", "spec", "spec/spec_helper.rb", "spec/oembed_links_spec.rb", "spec/oembed_links_test.yml" ]
10
+ s.require_path = "lib"
11
+ s.has_rdoc = true
12
+ s.extra_rdoc_files = ['README']
13
+ s.add_dependency(%q<json>)
14
+ s.add_dependency(%q<libxml-ruby>)
15
+ end
@@ -0,0 +1,40 @@
1
+ :config:
2
+ :method: "NetHTTP"
3
+
4
+ :providers:
5
+ :oohembed: "http://oohembed.com/oohembed/"
6
+ :vimeo: "http://www.vimeo.com/api/oembed.{format}"
7
+ :hulu: "http://www.hulu.com/api/oembed.{format}"
8
+ :flickr: "http://www.flickr.com/services/oembed"
9
+
10
+ :oohembed:
11
+ :format: "json"
12
+ :schemes:
13
+ - "http://*.amazon.(com|co.uk|de|ca|jp)/*/(gp/product|o/ASIN|obidos/ASIN|dp)/*"
14
+ - "http://*.amazon.(com|co.uk|de|ca|jp)/(gp/product|o/ASIN|obidos/ASIN|dp)/*"
15
+ - "http://*.collegehumor.com/video:*"
16
+ - "http://*.funnyordie.com/videos/*"
17
+ - "http://video.google.com/videoplay?*"
18
+ - "http://*.imdb.com/title/tt*/"
19
+ - "http://*.metacafe.com/watch/*"
20
+ - "http://*.slideshare.net/*"
21
+ - "http://twitter.com/*/statuses/*"
22
+ - "http://*.wikipedia.org/wiki/*"
23
+ - "http://*.wordpress.com/yyyy/mm/dd/*"
24
+ - "http://*.youtube.com/watch*"
25
+
26
+ :vimeo:
27
+ :format: "json"
28
+ :schemes:
29
+ - "http://www.vimeo.com/groups/*/*"
30
+ - "http://www.vimeo.com/*"
31
+
32
+ :hulu:
33
+ :format: "xml"
34
+ :schemes:
35
+ - "http://www.hulu.com/watch/*"
36
+
37
+ :flickr:
38
+ :format: "xml"
39
+ :schemes:
40
+ - "http://*.flickr.com/*"
data/rails/init.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'oembed_links'
2
+
3
+ yaml_file = File.join(RAILS_ROOT, "config", "oembed_links.yml")
4
+ if File.exists?(yaml_file)
5
+ OEmbed::register_yaml_file(yaml_file)
6
+ end
7
+
@@ -0,0 +1,128 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe OEmbed, "registration tasks" do
4
+ include SpecHelper
5
+
6
+ before(:each) do
7
+ OEmbed.clear_registrations
8
+ clear_urls
9
+ end
10
+
11
+ it "should default to NetHTTP if no method is specified in configuration" do
12
+ OEmbed.register()
13
+ OEmbed.instance_variable_get("@fetch_method").should == "NetHTTP"
14
+ end
15
+
16
+ it "should throw an error if you provide provider URLs but no scheme or format information" do
17
+ lambda { OEmbed.register({ }, { :fake => "http://fake" })}.should raise_error
18
+ end
19
+
20
+ it "should throw an error if you don't provide any scheme urls for registration" do
21
+ lambda { OEmbed.register({ }, { :fake => "http://fake" }, { :fake => { :format => "json", :schemes => []}})}.should raise_error
22
+ end
23
+
24
+ it "should default to json format if none is specified" do
25
+ OEmbed.register({ }, { :fake => "http://fake" }, { :fake => { :schemes => ["http://fake/*"]}})
26
+ OEmbed.instance_variable_get("@formats")[:fake].should == "json"
27
+ end
28
+
29
+ it "should support loading a configuration via YAML" do
30
+ OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
31
+ OEmbed.instance_variable_get("@urls").size.should == 3
32
+ end
33
+
34
+ it "should support ad hoc addition of providers" do
35
+ OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
36
+ OEmbed.instance_variable_get("@urls").size.should == 3
37
+ OEmbed.register_provider(:test4, "http://test4/oembed.{format}", "xml", "http://test4.*/*", "http://test4.*/foo/*")
38
+ OEmbed.instance_variable_get("@urls").size.should == 4
39
+ end
40
+
41
+ it "should support adding new fetchers" do
42
+
43
+ OEmbed.register_fetcher(FakeFetcher)
44
+ OEmbed.register({ :method => "fake_fetcher"},
45
+ { :fake => "http://fake" },
46
+ { :fake => {
47
+ :format => "json",
48
+ :schemes => "http://fake/*"
49
+ }})
50
+ OEmbed.transform("http://fake/bar/baz").should == "fakecontent"
51
+ end
52
+
53
+ it "should support adding new formatters" do
54
+ OEmbed.register_formatter(FakeFormatter)
55
+ OEmbed.register({ :method => "fake_fetcher"},
56
+ { :fake => "http://fake" },
57
+ { :fake => {
58
+ :format => "fake_formatter",
59
+ :schemes => "http://fake/*"
60
+ }})
61
+ url_provides("")
62
+ OEmbed.transform("http://fake/bar/baz").should == "http://fakesville"
63
+ end
64
+
65
+ end
66
+
67
+ describe OEmbed, "transforming functions" do
68
+ include SpecHelper
69
+ before(:each) do
70
+ OEmbed.clear_registrations
71
+ clear_urls
72
+ url_provides({
73
+ "html" => "foo",
74
+ "type" => "video"
75
+ }.to_json)
76
+ OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
77
+ end
78
+
79
+ it "should always give priority to provider conditional blocks" do
80
+ OEmbed.transform("http://test1.net/foo") do |r, url|
81
+ r.any? { |a| "any" }
82
+ r.video? { |v| "video" }
83
+ r.from?(:test1) { |t| "test1" }
84
+ r.matches?(/./) { |m| "regex" }
85
+ end.should == "test1"
86
+ end
87
+
88
+ it "should always give priority regex conditional blocks over all others except provider" do
89
+ OEmbed.transform("http://test1.net/foo") do |r, url|
90
+ r.any? { |a| "any" }
91
+ r.video? { |v| "video" }
92
+ r.matches?(/./) { |m| "regex" }
93
+ end.should == "regex"
94
+ OEmbed.transform("http://test1.net/foo") do |r, url|
95
+ r.matches?(/./) { |m| "regex" }
96
+ r.any? { |a| "any" }
97
+ r.video? { |v| "video" }
98
+ end.should == "regex"
99
+ end
100
+
101
+ it "should recognize the type of content and handle the conditional block appropriately" do
102
+ OEmbed.transform("http://test1.net/foo") do |r, url|
103
+ r.any? { |a| "any" }
104
+ r.video? { |v| "video" }
105
+ end.should == "video"
106
+ url_provides({
107
+ "html" => "bar",
108
+ "type" => "hedgehog"
109
+ }.to_json)
110
+ OEmbed.transform("http://test1.net/foo") do |r, url|
111
+ r.video? { |v| "video" }
112
+ r.hedgehog? { |v| "hedgey"}
113
+ end.should == "hedgey"
114
+ end
115
+
116
+ it "should still output the content of a url if no transforming blocks match it" do
117
+ OEmbed.transform("http://test1.net/foo") do |r, url|
118
+ r.audio? { |a| "audio" }
119
+ r.hedgehog? { |v| "hedgey"}
120
+ r.from?(:test2) { |t| "test2" }
121
+ r.matches?(/baz/) { |m| "regex" }
122
+ end.should == "foo"
123
+ end
124
+
125
+
126
+ end
127
+
128
+
@@ -0,0 +1,26 @@
1
+ :config:
2
+ :method: "NetHTTP"
3
+
4
+ :providers:
5
+ :test1: "http://test1/dude/{format}/"
6
+ :test2: "http://test2.{format}"
7
+ :test3: "http://test3"
8
+
9
+
10
+ :test1:
11
+ :format: "json"
12
+ :schemes:
13
+ - "http://test1.*/*"
14
+ - "http://test1/*/test/*"
15
+
16
+ :test2:
17
+ :format: "xml"
18
+ :schemes:
19
+ - "http://test2.*/*/stuff/*"
20
+ - "http://test2/foo/bar/*"
21
+
22
+ :test3:
23
+ :format: "json"
24
+ :schemes:
25
+ - "http://test3/foo/*"
26
+
@@ -0,0 +1,62 @@
1
+ $: << File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'oembed_links'
3
+
4
+ module SpecHelper
5
+
6
+ def url_provides(content)
7
+ Net::HTTP.fake_content(content)
8
+ end
9
+
10
+ def clear_urls
11
+ Net::HTTP.clear_fakes
12
+ end
13
+
14
+ end
15
+
16
+ require 'net/http'
17
+ module Net
18
+ class HTTP
19
+
20
+ def self.fake_content(content)
21
+ @content = content
22
+ end
23
+
24
+
25
+ def self.clear_fakes
26
+ @content = nil
27
+ end
28
+
29
+ def self.get(uri)
30
+ return @content
31
+ end
32
+
33
+ end
34
+ end
35
+
36
+
37
+ require 'json'
38
+ class FakeFetcher
39
+ def name
40
+ "fake_fetcher"
41
+ end
42
+
43
+ def fetch(url)
44
+ {
45
+ "url" => "fakecontent"
46
+ }.to_json
47
+ end
48
+ end
49
+
50
+ class FakeFormatter
51
+ def name
52
+ "fake_formatter"
53
+ end
54
+
55
+ def format(txt)
56
+ {
57
+ "url" => "http://fakesville"
58
+ }
59
+ end
60
+ end
61
+
62
+
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: netshade-oembed_links
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Indianapolis Star
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-07-08 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: libxml-ruby
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ description:
34
+ email: bugs at indystar dot com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - README
41
+ files:
42
+ - Rakefile
43
+ - README
44
+ - oembed_links_example.yml
45
+ - oembed_links.gemspec
46
+ - lib
47
+ - lib/oembed_links.rb
48
+ - lib/oembed_links
49
+ - lib/oembed_links/formatters
50
+ - lib/oembed_links/fetchers
51
+ - lib/oembed_links/response.rb
52
+ - lib/oembed_links/formatters/json.rb
53
+ - lib/oembed_links/formatters/xml.rb
54
+ - lib/oembed_links/fetchers/net_http.rb
55
+ - rails
56
+ - rails/init.rb
57
+ - spec
58
+ - spec/spec_helper.rb
59
+ - spec/oembed_links_spec.rb
60
+ - spec/oembed_links_test.yml
61
+ has_rdoc: true
62
+ homepage: http://www.indystar.com
63
+ post_install_message:
64
+ rdoc_options: []
65
+
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.2.0
84
+ signing_key:
85
+ specification_version: 2
86
+ summary: a library for using the OEmbed format (http://oembed.com/) to acquire embedding information for freetext
87
+ test_files: []
88
+