embedly 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,8 +27,8 @@ You can find rdocs at http://rubydoc.info/github/embedly/embedly-ruby/master/fra
27
27
 
28
28
  # single url
29
29
  obj = embedly_api.oembed :url => 'http://blog.embed.ly'
30
- puts obj.marshal_dump
31
- json_obj = JSON.pretty_generate(obj.marshal_dump)
30
+ puts obj[0].marshal_dump
31
+ json_obj = JSON.pretty_generate(obj[0].marshal_dump)
32
32
  puts json_obj
33
33
 
34
34
  # multiple urls with opts
@@ -45,7 +45,7 @@ You can find rdocs at http://rubydoc.info/github/embedly/embedly-ruby/master/fra
45
45
  embedly_pro = Embedly::API.new :key => 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
46
46
  url = 'http://www.guardian.co.uk/media/2011/jan/21/andy-coulson-phone-hacking-statement'
47
47
  obj = embedly_pro.preview :url => url
48
- puts JSON.pretty_generate(obj.marshal_dump)
48
+ puts JSON.pretty_generate(obj[0].marshal_dump)
49
49
 
50
50
  == Testing
51
51
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
@@ -4,7 +4,7 @@ $:.unshift(File.expand_path('../../lib', __FILE__))
4
4
 
5
5
  options = OpenStruct.new({
6
6
  :endpoint => nil,
7
- :key => nil,
7
+ :key => ENV['EMBEDLY_KEY'],
8
8
  :verbose => false,
9
9
  :args => {}
10
10
  })
@@ -26,11 +26,13 @@ Usage #{action} [OPTIONS] <url> [url] ..
26
26
  options.endpoint = e
27
27
  end
28
28
 
29
- opts.on("-k", "--key KEY", "Embedly PRO key") do |k|
29
+ opts.on("-k", "--key KEY", "Embedly PRO key [default: " +
30
+ "EMBEDLY_KEY environmental variable]") do |k|
30
31
  options.key = k
31
32
  end
32
33
 
33
- opts.on("-o", "--option NAME=VALUE", "Set option to be passed as query param.") do |o|
34
+ opts.on("-o", "--option NAME=VALUE", "Set option to be passed as " +
35
+ "query param.") do |o|
34
36
  k,v = o.split('=')
35
37
  options.args[k] = v
36
38
  end
@@ -4,7 +4,7 @@ $:.unshift(File.expand_path('../../lib', __FILE__))
4
4
 
5
5
  options = OpenStruct.new({
6
6
  :endpoint => nil,
7
- :key => nil,
7
+ :key => ENV['EMBEDLY_KEY'],
8
8
  :verbose => false,
9
9
  :args => {}
10
10
  })
@@ -26,11 +26,13 @@ Usage #{action} [OPTIONS] <url> [url] ..
26
26
  options.endpoint = e
27
27
  end
28
28
 
29
- opts.on("-k", "--key KEY", "Embedly PRO key") do |k|
29
+ opts.on("-k", "--key KEY", "Embedly PRO key [default: " +
30
+ "EMBEDLY_KEY environmental variable]") do |k|
30
31
  options.key = k
31
32
  end
32
33
 
33
- opts.on("-o", "--option NAME=VALUE", "Set option to be passed as query param.") do |o|
34
+ opts.on("-o", "--option NAME=VALUE", "Set option to be passed as " +
35
+ "query param.") do |o|
34
36
  k,v = o.split('=')
35
37
  options.args[k] = v
36
38
  end
@@ -4,7 +4,7 @@ $:.unshift(File.expand_path('../../lib', __FILE__))
4
4
 
5
5
  options = OpenStruct.new({
6
6
  :endpoint => nil,
7
- :key => nil,
7
+ :key => ENV['EMBEDLY_KEY'],
8
8
  :verbose => false,
9
9
  :args => {}
10
10
  })
@@ -26,11 +26,13 @@ Usage #{action} [OPTIONS] <url> [url] ..
26
26
  options.endpoint = e
27
27
  end
28
28
 
29
- opts.on("-k", "--key KEY", "Embedly PRO key") do |k|
29
+ opts.on("-k", "--key KEY", "Embedly PRO key [default: " +
30
+ "EMBEDLY_KEY environmental variable]") do |k|
30
31
  options.key = k
31
32
  end
32
33
 
33
- opts.on("-o", "--option NAME=VALUE", "Set option to be passed as query param.") do |o|
34
+ opts.on("-o", "--option NAME=VALUE", "Set option to be passed as " +
35
+ "query param.") do |o|
34
36
  k,v = o.split('=')
35
37
  options.args[k] = v
36
38
  end
@@ -72,8 +72,8 @@ Feature: OEmbed
72
72
 
73
73
  Examples:
74
74
  | url |
75
- | http://www.youtube.com/this/is/a/bad/url |
76
- | http://blog.embed.ly/lsbsdlfldsf/asdfkljlas/klajsdlfkasdf |
75
+ | http://www.youtube.com/watch/is/a/bad/url |
76
+ | http://www.scribd.com/doc/zfldsf/asdfkljlas/klajsdlfkasdf |
77
77
  | http://tweetphoto.com/alsdfldsf/asdfkljlas/klajsdlfkasdf |
78
78
 
79
79
 
@@ -85,8 +85,22 @@ Feature: OEmbed
85
85
 
86
86
  Examples:
87
87
  | urls | errcode | types |
88
- | http://www.youtube.com/this/is/a/bad/url,http://blog.embed.ly/alsd/slsdlf/asdlfj | 404,404 | error,error |
89
- | http://blog.embed.ly/lsbsdlfldsf/asdf/kl,http://tweetphoto.com/asdf/asdf/asdfl | 404,404 | error,error |
90
- | http://blog.embed.ly/lsbsdlfldsf/asdf/kl,http://tweetphoto.com/14784358 | 404, | error,photo |
91
- | http://tweetphoto.com/14784358,http://www.scribd.com/asdf/asdf/asdfasdf | ,404 | photo,error |
88
+ | http://www.youtube.com/watch/a/bassd/url,http://www.youtube.com/watch/ldf/asdlfj | 404,404 | error,error |
89
+ | http://www.scribd.com/doc/lsbsdlfldsf/kl,http://www.scribd.com/doc/zasdf/asdfl | 404,404 | error,error |
90
+ | http://www.youtube.com/watch/zzzzasdf/kl,http://tweetphoto.com/14784358 | 404, | error,photo |
91
+ | http://tweetphoto.com/14784358,http://www.scribd.com/doc/asdfasdfasdf | ,404 | photo,error |
92
92
 
93
+ Scenario Outline: Attempt at non-api service without key
94
+ Given an embedly endpoint
95
+ When oembed is called with the <url> URL
96
+ Then error_code should be 401
97
+ And error_message should be This service requires an Embedly Pro account
98
+ And type should be error
99
+
100
+ Examples:
101
+ | urls |
102
+ | http://hn.embed.ly/ |
103
+ | http://bit.ly/enZRxO |
104
+ | http://techcrunch.com/2011/02/03/linkedins-next-data-dive-professional-skills/ |
105
+ | http://teachertube.com/rssPhoto.php |
106
+ | http://goo.gl/y1i9p |
@@ -1,6 +1,9 @@
1
1
  $:.unshift(File.expand_path('../../../lib',__FILE__))
2
2
  require 'embedly'
3
3
 
4
+ # cache for endpoints
5
+ ENDPOINTS = {}
6
+
4
7
  Given /an embedly endpoint( [^\s]+)?( with key)?$/ do |endpoint, key_enabled|
5
8
  opts = {}
6
9
  opts[:endpoint] = endpoint
@@ -8,38 +11,47 @@ Given /an embedly endpoint( [^\s]+)?( with key)?$/ do |endpoint, key_enabled|
8
11
  raise 'Please set env variable $EMBEDLY_KEY' unless ENV['EMBEDLY_KEY']
9
12
  opts[:key] = ENV["EMBEDLY_KEY"]
10
13
  end
11
- @api = Embedly::API.new opts
14
+ if not ENDPOINTS[opts]
15
+ ENDPOINTS[opts] = Embedly::API.new opts
16
+ end
17
+ @api = ENDPOINTS[opts]
12
18
  end
13
19
 
14
20
  When /(\w+) is called with the (.*) URLs?( and ([^\s]+) flag)?$/ do |method, urls, _, flag|
15
- urls = urls.split(',')
16
- opts = {}
17
- if urls.size == 1
18
- opts[:url] = urls.first
19
- else
20
- opts[:urls] = urls
21
+ @result = nil
22
+ begin
23
+ urls = urls.split(',')
24
+ opts = {}
25
+ if urls.size == 1
26
+ opts[:url] = urls.first
27
+ else
28
+ opts[:urls] = urls
29
+ end
30
+ opts[flag.to_sym] = true if flag
31
+ @result = @api.send(method, opts)
32
+ rescue
33
+ @error = $!
21
34
  end
22
- opts[flag.to_sym] = true if flag
23
- @result = @api.send(method, opts)
24
35
  end
25
36
 
26
- Then /([^\s]+) should be ([^\s]+)/ do |key, value|
37
+ Then /an? (\w+) error should get thrown/ do |error|
38
+ @error.class.to_s.should == error
39
+ end
40
+
41
+ Then /([^\s]+) should be (.+)$/ do |key, value|
42
+ raise @error if @error
27
43
  logger = Embedly.logger('api_steps')
28
- if @result.is_a?Array
29
- @result.collect do |o|
30
- logger.debug { "result: #{o.marshal_dump}"}
31
- o.send(key).to_s
32
- end.join(',').should == value
33
- else
34
- logger.debug { "result: #{@result.marshal_dump}"}
35
- @result.send(key).to_s.should == value
36
- end
44
+ @result.collect do |o|
45
+ logger.debug { "result: #{o.marshal_dump}"}
46
+ o.send(key).to_s
47
+ end.join(',').should == value
37
48
  end
38
49
 
39
50
  Then /([^\s]+) should start with ([^\s]+)/ do |key, value|
51
+ raise @error if @error
40
52
  logger = Embedly.logger('api_steps')
41
- logger.debug { "result: #{@result.marshal_dump}"}
42
- v = key.split('.').inject(@result){|o,c| o.send(c)}.to_s
53
+ logger.debug { "result: #{@result[0].marshal_dump}"}
54
+ v = key.split('.').inject(@result[0]){|o,c| o.send(c)}.to_s
43
55
  v.to_s.should match(/^#{value}/)
44
56
  end
45
57
 
@@ -20,7 +20,7 @@ include ::Embedly
20
20
  #
21
21
  # api = Embedly::API.new
22
22
  # obj = api.oembed :url => 'http://blog.doki-pen.org/'
23
- # puts obj.title, obj.description, obj.thumbnail_url
23
+ # puts obj[0].title, obj[0].description, obj[0].thumbnail_url
24
24
  #
25
25
  # Call parameters should be passed as the opts parameter. If set, key will
26
26
  # automatically be added to the query string of the call, so no need to set it.
@@ -49,7 +49,7 @@ class Embedly::API
49
49
  else
50
50
  @endpoint = opts[:endpoint] || 'api.embed.ly'
51
51
  end
52
- @api_versions = Hash.new('1').merge!({'objectify' => '2'})
52
+ @api_version = Hash.new('1').merge!({'objectify' => '2'})
53
53
  @user_agent = opts[:user_agent] || "Mozilla/5.0 (compatible; embedly-ruby/#{Embedly::VERSION};)"
54
54
  end
55
55
 
@@ -71,46 +71,82 @@ class Embedly::API
71
71
 
72
72
  raise 'must pass urls' if opts[:urls].size == 0
73
73
 
74
- if opts[:urls].size == 1
75
- params = {:url => opts[:urls].first}
76
- else
77
- params = {:urls => opts[:urls]}
74
+ params = {:urls => opts[:urls]}
75
+
76
+ # store unsupported services as errors and don't send them to embedly
77
+ rejects = []
78
+ if not key
79
+ params[:urls].reject!.with_index do |url, i|
80
+ if url !~ services_regex
81
+ rejects << [i,
82
+ EmbedlyObject.new(
83
+ :type => 'error',
84
+ :error_code => 401,
85
+ :error_message => 'This service requires an Embedly Pro account'
86
+ )
87
+ ]
88
+ end
89
+ end
78
90
  end
79
91
 
80
- params[:key] = key if key
81
- params.merge!Hash[
82
- opts.select{|k,_| not [:url, :urls, :action, :version].index k}
83
- ]
92
+ if params[:urls].size > 0
93
+ params[:key] = key if key
94
+ params.merge!Hash[
95
+ opts.select{|k,_| not [:url, :urls, :action, :version].index k}
96
+ ]
84
97
 
85
- path = "/#{opts[:version]}/#{opts[:action]}?#{q params}"
98
+ path = "/#{opts[:version]}/#{opts[:action]}?#{q params}"
86
99
 
87
- ep = endpoint
88
- ep = "http://#{ep}" if endpoint !~ %r{^https?://.*}
89
- logger.debug { "calling #{ep}#{path}" }
100
+ logger.debug { "calling #{endpoint}#{path}" }
90
101
 
91
- url = URI.parse(ep)
92
- response = Net::HTTP.start(url.host, url.port) do |http|
93
- http.get(path, {'User-Agent' => user_agent})
94
- end
102
+ url = URI.parse(absurl(endpoint))
103
+ response = Net::HTTP.start(url.host, url.port) do |http|
104
+ http.get(path, {'User-Agent' => user_agent})
105
+ end
106
+
107
+ if response.code.to_i == 200
108
+ logger.debug { response.body }
109
+ # [].flatten is to be sure we have an array
110
+ objs = [JSON.parse(response.body)].flatten.collect {|o| EmbedlyObject.new(o)}
111
+ else
112
+ logger.error { response.inspect }
113
+ raise 'An unexpected error occurred'
114
+ end
95
115
 
96
- # passing url vs. urls causes different things to happen on errors (like a
97
- # 404 for the URL). using the url parameter returns a non 200 error code
98
- # in the response. Using urls causes an error json object to be returned,
99
- # but the main call will still be status 200. Below, we try to canonize as
100
- # best we can but it should really be changed server side.
101
- if response.code.to_i == 200
102
- logger.debug { response.body }
103
- # [].flatten is to be sure we have an array
104
- objs = [JSON.parse(response.body)].flatten.collect {|o| EmbedlyObject.new(o)}
116
+ # re-insert rejects into response
117
+ rejects.each do |i, obj|
118
+ objs.insert i, obj
119
+ end
120
+
121
+ objs
105
122
  else
106
- objs = EmbedlyObject.new :type => 'error', :error_code => response.code.to_i
123
+ # we only have rejects, return them without calling embedly
124
+ rejects.collect{|i, obj| obj}
107
125
  end
126
+ end
108
127
 
109
- if objs.size == 1
110
- objs.first
111
- else
112
- objs
128
+ # Returns structured data from the services API method.
129
+ #
130
+ # Response is cached per API object.
131
+ #
132
+ # see http://api.embed.ly/docs/service for a description of the response.
133
+ def services
134
+ logger.warn { "services isn't availble on the pro endpoint" } if key
135
+ if not @services
136
+ url = URI.parse(absurl(endpoint))
137
+ response = Net::HTTP.start(url.host, url.port) do |http|
138
+ http.get('/1/services/ruby', {'User-Agent' => user_agent})
139
+ end
140
+ raise 'services call failed', response if response.code.to_i != 200
141
+ @services = JSON.parse(response.body)
113
142
  end
143
+ @services
144
+ end
145
+
146
+ # Returns a regex suitable for checking urls against for non-Pro usage
147
+ def services_regex
148
+ r = services.collect {|p| p["regex"].join("|")}.join("|")
149
+ Regexp.new r
114
150
  end
115
151
 
116
152
  # Performs api call based on method name
@@ -124,11 +160,15 @@ class Embedly::API
124
160
  def method_missing(name, *args, &block)
125
161
  opts = args[0]
126
162
  opts[:action] = name
127
- opts[:version] = @api_versions[name]
163
+ opts[:version] = @api_version[name]
128
164
  apicall opts
129
165
  end
130
166
 
131
167
  private
168
+ def absurl uri
169
+ uri !~ %r{^https?://.*} ? "http://#{uri}" : uri
170
+ end
171
+
132
172
  # Escapes url parameters
133
173
  # TODO: move to utils
134
174
  def escape s
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
7
+ - 3
8
8
  - 0
9
- version: 0.2.0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Bob Corsaro
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-26 00:00:00 -05:00
17
+ date: 2011-02-04 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency