embedly 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -3
- data/VERSION +1 -1
- data/bin/embedly_objectify +5 -3
- data/bin/embedly_oembed +5 -3
- data/bin/embedly_preview +5 -3
- data/features/oembed.feature +20 -6
- data/features/steps/api_steps.rb +33 -21
- data/lib/embedly/api.rb +73 -33
- metadata +3 -3
data/README.rdoc
CHANGED
@@ -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.
|
1
|
+
0.3.0
|
data/bin/embedly_objectify
CHANGED
@@ -4,7 +4,7 @@ $:.unshift(File.expand_path('../../lib', __FILE__))
|
|
4
4
|
|
5
5
|
options = OpenStruct.new({
|
6
6
|
:endpoint => nil,
|
7
|
-
:key =>
|
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"
|
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
|
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
|
data/bin/embedly_oembed
CHANGED
@@ -4,7 +4,7 @@ $:.unshift(File.expand_path('../../lib', __FILE__))
|
|
4
4
|
|
5
5
|
options = OpenStruct.new({
|
6
6
|
:endpoint => nil,
|
7
|
-
:key =>
|
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"
|
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
|
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
|
data/bin/embedly_preview
CHANGED
@@ -4,7 +4,7 @@ $:.unshift(File.expand_path('../../lib', __FILE__))
|
|
4
4
|
|
5
5
|
options = OpenStruct.new({
|
6
6
|
:endpoint => nil,
|
7
|
-
:key =>
|
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"
|
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
|
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
|
data/features/oembed.feature
CHANGED
@@ -72,8 +72,8 @@ Feature: OEmbed
|
|
72
72
|
|
73
73
|
Examples:
|
74
74
|
| url |
|
75
|
-
| http://www.youtube.com/
|
76
|
-
| http://
|
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/
|
89
|
-
| http://
|
90
|
-
| http://
|
91
|
-
| http://tweetphoto.com/14784358,http://www.scribd.com/
|
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 |
|
data/features/steps/api_steps.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
opts
|
19
|
-
|
20
|
-
|
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 /(
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
|
data/lib/embedly/api.rb
CHANGED
@@ -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
|
-
@
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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[:
|
81
|
-
|
82
|
-
|
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
|
-
|
98
|
+
path = "/#{opts[:version]}/#{opts[:action]}?#{q params}"
|
86
99
|
|
87
|
-
|
88
|
-
ep = "http://#{ep}" if endpoint !~ %r{^https?://.*}
|
89
|
-
logger.debug { "calling #{ep}#{path}" }
|
100
|
+
logger.debug { "calling #{endpoint}#{path}" }
|
90
101
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
123
|
+
# we only have rejects, return them without calling embedly
|
124
|
+
rejects.collect{|i, obj| obj}
|
107
125
|
end
|
126
|
+
end
|
108
127
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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] = @
|
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
|
-
-
|
7
|
+
- 3
|
8
8
|
- 0
|
9
|
-
version: 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-
|
17
|
+
date: 2011-02-04 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|