grabz_it 0.0.1
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/grabz_it.gemspec +19 -0
- data/image +0 -0
- data/lib/grabz_it/client.rb +251 -0
- data/lib/grabz_it/cookie.rb +5 -0
- data/lib/grabz_it/cookie_jar.rb +35 -0
- data/lib/grabz_it/hash.rb +47 -0
- data/lib/grabz_it/image.rb +20 -0
- data/lib/grabz_it/response.rb +17 -0
- data/lib/grabz_it/status.rb +21 -0
- data/lib/grabz_it/version.rb +3 -0
- data/lib/grabz_it.rb +8 -0
- data/spec/client_spec.rb +223 -0
- data/spec/image_spec.rb +27 -0
- data/spec/response_spec.rb +39 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/test_data/test_image.png +0 -0
- metadata +88 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 TODO: Write your name
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# GrabzIt
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'grabz_it'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install grabz_it
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/grabz_it.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/grabz_it/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Eric Berry"]
|
6
|
+
gem.email = ["cavneb@gmail.com"]
|
7
|
+
gem.description = "Ruby interface to the GrabzIt (grabz.it) service"
|
8
|
+
gem.summary = "Ruby interface to the GrabzIt (grabz.it) service"
|
9
|
+
gem.homepage = "https://github.com/cavneb/grabz_it"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "grabz_it"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = GrabzIt::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency('rspec')
|
19
|
+
end
|
data/image
ADDED
Binary file
|
@@ -0,0 +1,251 @@
|
|
1
|
+
module GrabzIt
|
2
|
+
class Client
|
3
|
+
attr_accessor :app_key, :app_secret, :url, :callback_url, :browser_width, :browser_height,
|
4
|
+
:output_width, :output_height, :custom_id, :format, :delay
|
5
|
+
|
6
|
+
API_BASE_URL = "http://grabz.it/services/"
|
7
|
+
|
8
|
+
##
|
9
|
+
# Initialize the +GrabzIt::Client+ class
|
10
|
+
#
|
11
|
+
# @param [String] app_key Application Key provided by grabz.it
|
12
|
+
# @param [String] app_secret Application Secret provided by grabz.it
|
13
|
+
#
|
14
|
+
# @raise [ArgumentError] Exception raised if the app_key or app_secret is not provided
|
15
|
+
#
|
16
|
+
def initialize(app_key, app_secret)
|
17
|
+
@app_key = app_key
|
18
|
+
@app_secret = app_secret
|
19
|
+
raise(ArgumentError, "You must provide app_key and app_secret") unless @app_key && @app_secret
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Calls the GrabzIt web service to take the screenshot. Warning, this is a SYNCHONOUS method and can take up to
|
24
|
+
# 5 minutes before a response.
|
25
|
+
#
|
26
|
+
# @param [String] target_path File path that the file should be saved to (including file name and extension)
|
27
|
+
# @param [Hash] options Data that is to be passed to the web service
|
28
|
+
# @option options [String] :url The URL that the screenshot should be made of
|
29
|
+
# @option options [String] :callback_url The handler the GrabzIt web service should call after it has completed its work
|
30
|
+
# @option options [String] :custom_id A custom identifier that you can pass through to the screenshot webservice. This will be returned with the callback URL you have specified.
|
31
|
+
# @option options [Integer] :browser_width The width of the browser in pixels
|
32
|
+
# @option options [Integer] :browser_height The height of the browser in pixels
|
33
|
+
# @option options [Integer] :output_width The width of the resulting thumbnail in pixels
|
34
|
+
# @option options [Integer] :output_height The height of the resulting thumbnail in pixels
|
35
|
+
# @option options [String] :format The format the screenshot should be in: bmp8, bmp16, bmp24, bmp, gif, jpg, png
|
36
|
+
# @option options [Integer] :delay The number of milliseconds to wait before taking the screenshot
|
37
|
+
#
|
38
|
+
# @return [GrabzIt::Response] The parsed response.
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# client = GrabzIt::Client.new('TEST_KEY', 'TEST_SECRET')
|
42
|
+
# options = {
|
43
|
+
# :url => 'http://grabz.it',
|
44
|
+
# :callback_url => 'http://example.com/callback',
|
45
|
+
# :browser_width => 1024,
|
46
|
+
# :browser_height => 768,
|
47
|
+
# :output_width => 800,
|
48
|
+
# :output_height => 600,
|
49
|
+
# :custom_id => '12345',
|
50
|
+
# :format => 'png',
|
51
|
+
# :delay => 1000
|
52
|
+
# }
|
53
|
+
# response = client.take_picture(options)
|
54
|
+
#
|
55
|
+
def save_picture(target_path, options = {})
|
56
|
+
response = take_picture(options)
|
57
|
+
|
58
|
+
# Wait for the response to be ready
|
59
|
+
iterations = 0
|
60
|
+
while true do
|
61
|
+
status = get_status(response.screenshot_id)
|
62
|
+
|
63
|
+
if status.failed?
|
64
|
+
raise "The screenshot did not complete with errors: " + status.message
|
65
|
+
|
66
|
+
elsif status.available?
|
67
|
+
image = get_picture(response.screenshot_id)
|
68
|
+
image.save(target_path)
|
69
|
+
break
|
70
|
+
end
|
71
|
+
|
72
|
+
# Check again in 1 second with a max of 5 minutes
|
73
|
+
if iterations <= (5 * 60)
|
74
|
+
sleep(1)
|
75
|
+
else
|
76
|
+
raise Timeout::Error
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Calls the GrabzIt web service to take the screenshot.
|
85
|
+
#
|
86
|
+
# @param [Hash] options Data that is to be passed to the web service
|
87
|
+
# @option options [String] :url The URL that the screenshot should be made of
|
88
|
+
# @option options [String] :callback_url The handler the GrabzIt web service should call after it has completed its work
|
89
|
+
# @option options [String] :custom_id A custom identifier that you can pass through to the screenshot webservice. This will be returned with the callback URL you have specified.
|
90
|
+
# @option options [Integer] :browser_width The width of the browser in pixels
|
91
|
+
# @option options [Integer] :browser_height The height of the browser in pixels
|
92
|
+
# @option options [Integer] :output_width The width of the resulting thumbnail in pixels
|
93
|
+
# @option options [Integer] :output_height The height of the resulting thumbnail in pixels
|
94
|
+
# @option options [String] :format The format the screenshot should be in: bmp8, bmp16, bmp24, bmp, gif, jpg, png
|
95
|
+
# @option options [Integer] :delay The number of milliseconds to wait before taking the screenshot
|
96
|
+
#
|
97
|
+
# @return [GrabzIt::Response] The parsed response.
|
98
|
+
#
|
99
|
+
# @example
|
100
|
+
# client = GrabzIt::Client.new('TEST_KEY', 'TEST_SECRET')
|
101
|
+
# options = {
|
102
|
+
# :url => 'http://grabz.it',
|
103
|
+
# :callback_url => 'http://example.com/callback',
|
104
|
+
# :browser_width => 1024,
|
105
|
+
# :browser_height => 768,
|
106
|
+
# :output_width => 800,
|
107
|
+
# :output_height => 600,
|
108
|
+
# :custom_id => '12345',
|
109
|
+
# :format => 'png',
|
110
|
+
# :delay => 1000
|
111
|
+
# }
|
112
|
+
# response = client.take_picture(options)
|
113
|
+
#
|
114
|
+
def take_picture(options = {})
|
115
|
+
parse_options(options)
|
116
|
+
action = "takepicture.ashx"
|
117
|
+
response_body = query_api(action, generate_params)
|
118
|
+
response = Response.new(response_body)
|
119
|
+
raise response.message if response.message
|
120
|
+
response
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Get the current status of a GrabzIt screenshot.
|
125
|
+
#
|
126
|
+
# @param [String] screenshot_id The id of the screenshot provided by the GrabzIt api
|
127
|
+
#
|
128
|
+
# @return [GrabzIt::Status] The parsed status.
|
129
|
+
#
|
130
|
+
# @example
|
131
|
+
# client = GrabzIt::Client.new('TEST_KEY', 'TEST_SECRET')
|
132
|
+
# status = client.get_status('Y2F2bmViQGdtYWlsLmNvbQ==-20943258e37c4fc28c4977cd76c40f58')
|
133
|
+
#
|
134
|
+
def get_status(screenshot_id)
|
135
|
+
action = "getstatus.ashx"
|
136
|
+
response_body = query_api(action, { :id => screenshot_id })
|
137
|
+
status = Status.new(response_body)
|
138
|
+
raise status.message if status.message
|
139
|
+
status
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Get the current status of a GrabzIt screenshot.
|
144
|
+
#
|
145
|
+
# @param [String] screenshot_id The id of the screenshot provided by the GrabzIt api
|
146
|
+
#
|
147
|
+
# @return [GrabzIt::Status] The parsed status.
|
148
|
+
#
|
149
|
+
# @example
|
150
|
+
# client = GrabzIt::Client.new('TEST_KEY', 'TEST_SECRET')
|
151
|
+
# status = client.get_status('Y2F2bmViQGdtYWlsLmNvbQ==-20943258e37c4fc28c4977cd76c40f58')
|
152
|
+
#
|
153
|
+
def get_cookies(domain)
|
154
|
+
action = "getcookies.ashx"
|
155
|
+
sig = Digest::MD5.hexdigest(@app_secret + "|" + domain)
|
156
|
+
params = {
|
157
|
+
:key => URI.escape(@app_key),
|
158
|
+
:domain => URI.escape(domain),
|
159
|
+
:sig => sig
|
160
|
+
}
|
161
|
+
response_body = query_api(action, params)
|
162
|
+
cookie_jar = CookieJar.new(response_body)
|
163
|
+
raise cookie_jar.message if cookie_jar.message
|
164
|
+
cookie_jar
|
165
|
+
end
|
166
|
+
|
167
|
+
##
|
168
|
+
# Get the screenshot image
|
169
|
+
#
|
170
|
+
# @param [String] screenshot_id The id of the screenshot provided by the GrabzIt api
|
171
|
+
#
|
172
|
+
# @return [GrabzIt::Image] The image object
|
173
|
+
#
|
174
|
+
# @example
|
175
|
+
# client = GrabzIt::Client.new('TEST_KEY', 'TEST_SECRET')
|
176
|
+
# image = client.get_image('Y2F2bmViQGdtYWlsLmNvbQ==-20943258e37c4fc28c4977cd76c40f58')
|
177
|
+
# puts image.content_type
|
178
|
+
# => 'image/png'
|
179
|
+
# puts image.size
|
180
|
+
# => 129347
|
181
|
+
# image.save("/tmp/myimage.png")
|
182
|
+
# File.exist?("/tmp/myimage.png")
|
183
|
+
# => true
|
184
|
+
#
|
185
|
+
def get_picture(screenshot_id)
|
186
|
+
action = "getpicture.ashx"
|
187
|
+
response = query_api(action, { :id => screenshot_id })
|
188
|
+
image = Image.new(response)
|
189
|
+
image
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
|
194
|
+
# Helper method that performs the request
|
195
|
+
def query_api(action, params)
|
196
|
+
uri = URI("#{API_BASE_URL}#{action}")
|
197
|
+
uri.query = URI.encode_www_form(params)
|
198
|
+
res = Net::HTTP.get_response(uri)
|
199
|
+
res.body
|
200
|
+
end
|
201
|
+
|
202
|
+
# Convert the options into the instance variable values
|
203
|
+
def parse_options(options={})
|
204
|
+
options = options.symbolize_keys
|
205
|
+
@url = options[:url] || ''
|
206
|
+
@callback_url = options[:callback_url] || ''
|
207
|
+
@browser_width = options[:browser_width] || ''
|
208
|
+
@browser_height = options[:browser_height] || ''
|
209
|
+
@output_width = options[:output_width] || ''
|
210
|
+
@output_height = options[:output_height] || ''
|
211
|
+
@custom_id = options[:custom_id] || ''
|
212
|
+
@format = options[:format] || ''
|
213
|
+
@delay = options[:delay] || ''
|
214
|
+
end
|
215
|
+
|
216
|
+
# Generate the params that are to be used in the request
|
217
|
+
def generate_params
|
218
|
+
{
|
219
|
+
:key => URI.escape(@app_key),
|
220
|
+
:url => URI.escape(@url),
|
221
|
+
:width => @output_width,
|
222
|
+
:height => @output_height,
|
223
|
+
:format => @format,
|
224
|
+
:bwidth => @browser_width,
|
225
|
+
:bheight => @browser_height,
|
226
|
+
:callback => URI.escape(@callback_url),
|
227
|
+
:customid => URI.escape(@custom_id),
|
228
|
+
:delay => @delay,
|
229
|
+
:sig => generate_signature
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
# Generate the signature that is used in the request
|
234
|
+
def generate_signature
|
235
|
+
sig = []
|
236
|
+
sig << @app_secret
|
237
|
+
sig << @url
|
238
|
+
sig << @callback_url
|
239
|
+
sig << @format
|
240
|
+
sig << @output_height
|
241
|
+
sig << @output_width
|
242
|
+
sig << @browser_height
|
243
|
+
sig << @browser_width
|
244
|
+
sig << @custom_id
|
245
|
+
sig << @delay
|
246
|
+
|
247
|
+
Digest::MD5.hexdigest(sig.join('|'))
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module GrabzIt
|
2
|
+
class CookieJar
|
3
|
+
attr_accessor :cookies, :message
|
4
|
+
|
5
|
+
def initialize(xml)
|
6
|
+
@cookies = []
|
7
|
+
doc = REXML::Document.new(xml)
|
8
|
+
@message = doc.root.elements['Message'].text
|
9
|
+
begin
|
10
|
+
add_cookies(doc.root.elements.to_a("//WebResult/Cookies/Cookie"))
|
11
|
+
rescue => ex
|
12
|
+
raise "Invalid Response: #{xml}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def add_cookies(xml_cookies)
|
19
|
+
xml_cookies.each do |c|
|
20
|
+
cookie = Cookie.new
|
21
|
+
cookie.name = c.elements['Name'].text
|
22
|
+
cookie.value = c.elements['Value'].text
|
23
|
+
cookie.domain = c.elements['Domain'].text
|
24
|
+
cookie.path = c.elements['Path'].text
|
25
|
+
cookie.http_only = (c.elements['HttpOnly'].text == 'True')
|
26
|
+
cookie.type = c.elements["Type"].text
|
27
|
+
if c.elements['Expires']
|
28
|
+
cookie.expires = c.elements['Expires'].text
|
29
|
+
end
|
30
|
+
@cookies << cookie
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
# Return a new hash with all keys converted to symbols, as long as
|
4
|
+
# they respond to +to_sym+.
|
5
|
+
#
|
6
|
+
# { 'name' => 'Rob', 'years' => '28' }.symbolize_keys
|
7
|
+
# #=> { :name => "Rob", :years => "28" }
|
8
|
+
def symbolize_keys
|
9
|
+
dup.symbolize_keys!
|
10
|
+
end
|
11
|
+
|
12
|
+
# Destructively convert all keys to symbols, as long as they respond
|
13
|
+
# to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
|
14
|
+
def symbolize_keys!
|
15
|
+
keys.each do |key|
|
16
|
+
self[(key.to_sym rescue key) || key] = delete(key)
|
17
|
+
end
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_params
|
22
|
+
params = ''
|
23
|
+
stack = []
|
24
|
+
|
25
|
+
each do |k, v|
|
26
|
+
if v.is_a?(Hash)
|
27
|
+
stack << [k,v]
|
28
|
+
else
|
29
|
+
params << "#{k}=#{v}&"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
stack.each do |parent, hash|
|
34
|
+
hash.each do |k, v|
|
35
|
+
if v.is_a?(Hash)
|
36
|
+
stack << ["#{parent}[#{k}]", v]
|
37
|
+
else
|
38
|
+
params << "#{parent}[#{k}]=#{v}&"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
params.chop! # trailing &
|
44
|
+
params
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GrabzIt
|
2
|
+
class Image
|
3
|
+
attr_accessor :image_bytes, :content_type, :size
|
4
|
+
|
5
|
+
def initialize(response)
|
6
|
+
begin
|
7
|
+
@image_bytes = response.body
|
8
|
+
@size = @image_bytes ? @image_bytes.size : 0
|
9
|
+
@content_type = response.header['content-type']
|
10
|
+
rescue => ex
|
11
|
+
raise "Invalid Response"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def save(path)
|
16
|
+
File.open(path, 'wb') { |s| s.write(@image_bytes) }
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module GrabzIt
|
2
|
+
class Response
|
3
|
+
attr_accessor :result, :screenshot_id, :message
|
4
|
+
|
5
|
+
def initialize(xml)
|
6
|
+
doc = REXML::Document.new(xml)
|
7
|
+
@result = doc.root.elements['Result'].text
|
8
|
+
@screenshot_id = doc.root.elements['ID'].text
|
9
|
+
@message = doc.root.elements['Message'].text
|
10
|
+
end
|
11
|
+
|
12
|
+
def successful?
|
13
|
+
@result == 'True'
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module GrabzIt
|
2
|
+
class Status
|
3
|
+
attr_accessor :processing, :cached, :expired, :message
|
4
|
+
|
5
|
+
def initialize(xml)
|
6
|
+
doc = REXML::Document.new(xml)
|
7
|
+
@processing = (doc.root.elements['Processing'].text == 'True')
|
8
|
+
@cached = (doc.root.elements['Cached'].text == 'True')
|
9
|
+
@expired = (doc.root.elements['Expired'].text == 'True')
|
10
|
+
@message = doc.root.elements['Message'].text
|
11
|
+
end
|
12
|
+
|
13
|
+
def failed?
|
14
|
+
!@processing && !@cached
|
15
|
+
end
|
16
|
+
|
17
|
+
def available?
|
18
|
+
@cached
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/grabz_it.rb
ADDED
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe GrabzIt::Client do
|
4
|
+
|
5
|
+
it "should raise an error when instanciating without the api_key or api_secret" do
|
6
|
+
lambda { GrabzIt::Client.new }.should raise_error(ArgumentError)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "with a valid api_key and api_secret" do
|
10
|
+
before(:each) do
|
11
|
+
@client = GrabzIt::Client.new('TEST_KEY', 'TEST_SECRET')
|
12
|
+
@options = {
|
13
|
+
:url => 'http://grabz.it',
|
14
|
+
:callback_url => 'http://example.com/callback',
|
15
|
+
:browser_width => 1024,
|
16
|
+
:browser_height => 768,
|
17
|
+
:output_width => 800,
|
18
|
+
:output_height => 600,
|
19
|
+
:custom_id => '12345',
|
20
|
+
:format => 'png',
|
21
|
+
:delay => 1000
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
## ------------------------------------------------------------------------------------
|
26
|
+
# Take Picture
|
27
|
+
## ------------------------------------------------------------------------------------
|
28
|
+
it "#take_picture" do
|
29
|
+
pending "unable to test without valid app_key and app_secret"
|
30
|
+
end
|
31
|
+
|
32
|
+
## ------------------------------------------------------------------------------------
|
33
|
+
# Take Picture
|
34
|
+
## ------------------------------------------------------------------------------------
|
35
|
+
describe "#take_picture" do
|
36
|
+
it "with successful response" do
|
37
|
+
xml = <<-EOF
|
38
|
+
<?xml version="1.0"?>
|
39
|
+
<WebResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
40
|
+
<Result>True</Result>
|
41
|
+
<ID>Y2F2bmViQGdtYWlsLmNvbQ==-20943258e37c4fc28c4977cd76c40f58</ID>
|
42
|
+
<Message />
|
43
|
+
</WebResult>
|
44
|
+
EOF
|
45
|
+
@client.stub!(:query_api).and_return(xml)
|
46
|
+
response = @client.take_picture(@options)
|
47
|
+
|
48
|
+
response.screenshot_id.should eq('Y2F2bmViQGdtYWlsLmNvbQ==-20943258e37c4fc28c4977cd76c40f58')
|
49
|
+
response.successful?.should be_true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "with error response" do
|
53
|
+
xml = <<-EOF
|
54
|
+
<?xml version="1.0"?>
|
55
|
+
<WebResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
56
|
+
<Result>False</Result>
|
57
|
+
<ID />
|
58
|
+
<Message>Application Key not recognised.</Message>
|
59
|
+
</WebResult>
|
60
|
+
EOF
|
61
|
+
@client.stub!(:query_api).and_return(xml)
|
62
|
+
|
63
|
+
lambda{ @client.take_picture(@options) }.should raise_error(RuntimeError, "Application Key not recognised.")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
## ------------------------------------------------------------------------------------
|
68
|
+
# Get Status
|
69
|
+
## ------------------------------------------------------------------------------------
|
70
|
+
describe "#get_status" do
|
71
|
+
it "with valid screenshot id" do
|
72
|
+
xml = <<-EOF
|
73
|
+
<?xml version="1.0"?>
|
74
|
+
<WebResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
75
|
+
<Processing>False</Processing>
|
76
|
+
<Cached>True</Cached>
|
77
|
+
<Expired>False</Expired>
|
78
|
+
<Message />
|
79
|
+
</WebResult>
|
80
|
+
EOF
|
81
|
+
@client.stub!(:query_api).and_return(xml)
|
82
|
+
status = @client.get_status('abcde12345')
|
83
|
+
|
84
|
+
status.processing.should be_false
|
85
|
+
status.cached.should be_true
|
86
|
+
status.expired.should be_false
|
87
|
+
status.message.should be_nil
|
88
|
+
end
|
89
|
+
|
90
|
+
it "with invalid screenshot id" do
|
91
|
+
xml = <<-EOF
|
92
|
+
<?xml version="1.0"?>
|
93
|
+
<WebResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
94
|
+
<Processing>False</Processing>
|
95
|
+
<Cached>False</Cached>
|
96
|
+
<Expired>True</Expired>
|
97
|
+
<Message />
|
98
|
+
</WebResult>
|
99
|
+
EOF
|
100
|
+
@client.stub!(:query_api).and_return(xml)
|
101
|
+
status = @client.get_status('abcde12345')
|
102
|
+
|
103
|
+
status.processing.should be_false
|
104
|
+
status.cached.should be_false
|
105
|
+
status.expired.should be_true
|
106
|
+
status.message.should be_nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
## ------------------------------------------------------------------------------------
|
111
|
+
# Get Picture
|
112
|
+
## ------------------------------------------------------------------------------------
|
113
|
+
describe "#get_picture" do
|
114
|
+
before(:each) do
|
115
|
+
raw_image = File.read(File.join(File.dirname(__FILE__), 'test_data', 'test_image.png'))
|
116
|
+
@mocked_response = Struct::MockHTTPResponse.new(raw_image, { 'content-type' => 'image/png' })
|
117
|
+
end
|
118
|
+
|
119
|
+
it "with valid screenshot id" do
|
120
|
+
@client.stub!(:query_api).and_return(@mocked_response)
|
121
|
+
image = @client.get_picture('YXBAMW9uMS5jb20=-4d164e5166134c31b95cd7b9d23e8ed5')
|
122
|
+
image.content_type.should eq('image/png')
|
123
|
+
image.size.should eq(129347)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
## ------------------------------------------------------------------------------------
|
128
|
+
# Get Cookies
|
129
|
+
## ------------------------------------------------------------------------------------
|
130
|
+
describe "#get_cookies" do
|
131
|
+
it "with valid domain" do
|
132
|
+
xml = <<-EOF
|
133
|
+
<?xml version="1.0"?>
|
134
|
+
<WebResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
135
|
+
<Cookies>
|
136
|
+
<Cookie>
|
137
|
+
<Name>secure</Name>
|
138
|
+
<Value />
|
139
|
+
<Domain>accounts.google.com</Domain>
|
140
|
+
<Path>/</Path>
|
141
|
+
<HttpOnly>False</HttpOnly>
|
142
|
+
<Type>Global</Type>
|
143
|
+
</Cookie>
|
144
|
+
<Cookie>
|
145
|
+
<Name>PREF</Name>
|
146
|
+
<Value>ID=c8a1a3e41c52b4ed:TM=1346246013:LM=1346246013:S=_6o6Tap-5lKkES34</Value>
|
147
|
+
<Domain>.google.com</Domain>
|
148
|
+
<Path>/</Path>
|
149
|
+
<HttpOnly>False</HttpOnly>
|
150
|
+
<Expires>Sat, 30 Aug 2014 03:13:33 GMT</Expires>
|
151
|
+
<Type>Global</Type>
|
152
|
+
</Cookie>
|
153
|
+
<Cookie>
|
154
|
+
<Name>NID</Name>
|
155
|
+
<Value>63=zJWKTpnMjJjEhk_9wEEFWYccDWjY7hGrDUfe7csnveQGvD33jdtwOm5fcDh-eHLLwWMlNfzxrM9hwAeWhUkcFNCAjZitNIsewSHf4LCPbfqgaG8eSIMJ7X07p_Gx-bGz</Value>
|
156
|
+
<Domain>.google.com</Domain>
|
157
|
+
<Path>/</Path>
|
158
|
+
<HttpOnly>True</HttpOnly>
|
159
|
+
<Expires>Thu, 28 Feb 2013 14:32:20 GMT</Expires>
|
160
|
+
<Type>Global</Type>
|
161
|
+
</Cookie>
|
162
|
+
</Cookies>
|
163
|
+
<Message />
|
164
|
+
</WebResult>
|
165
|
+
EOF
|
166
|
+
@client.stub!(:query_api).and_return(xml)
|
167
|
+
cookie_jar = @client.get_cookies('google')
|
168
|
+
cookie_jar.cookies.size.should eq(3)
|
169
|
+
cookie_jar.cookies[0].name.should eq('secure')
|
170
|
+
cookie_jar.cookies[0].domain.should eq('accounts.google.com')
|
171
|
+
end
|
172
|
+
|
173
|
+
it "with invalid domain" do
|
174
|
+
xml = <<-EOF
|
175
|
+
<?xml version="1.0"?>
|
176
|
+
<WebResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
177
|
+
<Cookies />
|
178
|
+
<Message />
|
179
|
+
</WebResult>
|
180
|
+
EOF
|
181
|
+
@client.stub!(:query_api).and_return(xml)
|
182
|
+
cookie_jar = @client.get_cookies('fsoi')
|
183
|
+
cookie_jar.cookies.should be_empty
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
## ------------------------------------------------------------------------------------
|
188
|
+
# Other
|
189
|
+
## ------------------------------------------------------------------------------------
|
190
|
+
|
191
|
+
it "#parse_options" do
|
192
|
+
@client.send(:parse_options, @options)
|
193
|
+
@options.each do |k, val|
|
194
|
+
@client.send(k).should eq(val)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
it "#generate_params" do
|
199
|
+
@client.send(:parse_options, @options)
|
200
|
+
params = @client.send(:generate_params)
|
201
|
+
|
202
|
+
params[:key].should eq('TEST_KEY')
|
203
|
+
params[:url].should eq("http://grabz.it")
|
204
|
+
params[:width].should eq(800)
|
205
|
+
params[:height].should eq(600)
|
206
|
+
params[:format].should eq("png")
|
207
|
+
params[:bwidth].should eq(1024)
|
208
|
+
params[:bheight].should eq(768)
|
209
|
+
params[:callback].should eq("http://example.com/callback")
|
210
|
+
params[:customid].should eq("12345")
|
211
|
+
params[:delay].should eq(1000)
|
212
|
+
params[:sig].should eq("6419e21afbf4d178894bce8dafa91c6d")
|
213
|
+
end
|
214
|
+
|
215
|
+
it "#generate_signature" do
|
216
|
+
@client.send(:parse_options, @options)
|
217
|
+
signature = @client.send(:generate_signature)
|
218
|
+
signature.should eq('6419e21afbf4d178894bce8dafa91c6d')
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
data/spec/image_spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe GrabzIt::Image do
|
4
|
+
before(:each) do
|
5
|
+
raw_image = File.read(File.join(File.dirname(__FILE__), 'test_data', 'test_image.png'))
|
6
|
+
@mocked_response = Struct::MockHTTPResponse.new(raw_image, { 'content-type' => 'image/png' })
|
7
|
+
end
|
8
|
+
|
9
|
+
it "#initialize with successful response" do
|
10
|
+
image = GrabzIt::Image.new(@mocked_response)
|
11
|
+
image.content_type.should eq('image/png')
|
12
|
+
image.size.should eq(129347)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "#initialize with failed response" do
|
16
|
+
lambda { image = GrabzIt::Image.new(nil) }.should raise_error(RuntimeError, "Invalid Response")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "#save" do
|
20
|
+
image = GrabzIt::Image.new(@mocked_response)
|
21
|
+
target = "/tmp/grabz_it_text_image.png"
|
22
|
+
saved_image = image.save(target)
|
23
|
+
File.exist?(target).should be_true
|
24
|
+
File.delete(target) if File.exist?(target) # cleanup
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe GrabzIt::Response do
|
4
|
+
|
5
|
+
it "#initialize with successful response" do
|
6
|
+
xml = <<-EOF
|
7
|
+
<?xml version="1.0"?>
|
8
|
+
<WebResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
9
|
+
<Result>True</Result>
|
10
|
+
<ID>Y2F2bmViQGdtYWlsLmNvbQ==-20943258e37c4fc28c4977cd76c40f58</ID>
|
11
|
+
<Message />
|
12
|
+
</WebResult>
|
13
|
+
EOF
|
14
|
+
|
15
|
+
api_response = GrabzIt::Response.new(xml)
|
16
|
+
api_response.result.should eq('True')
|
17
|
+
api_response.screenshot_id.should eq('Y2F2bmViQGdtYWlsLmNvbQ==-20943258e37c4fc28c4977cd76c40f58')
|
18
|
+
api_response.message.should be_nil
|
19
|
+
api_response.successful?.should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "#initialize with invalid api key" do
|
23
|
+
xml = <<-EOF
|
24
|
+
<?xml version="1.0"?>
|
25
|
+
<WebResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
26
|
+
<Result>False</Result>
|
27
|
+
<ID />
|
28
|
+
<Message>Application Key not recognised.</Message>
|
29
|
+
</WebResult>
|
30
|
+
EOF
|
31
|
+
|
32
|
+
api_response = GrabzIt::Response.new(xml)
|
33
|
+
api_response.result.should eq('False')
|
34
|
+
api_response.screenshot_id.should be_nil
|
35
|
+
api_response.message.should eq('Application Key not recognised.')
|
36
|
+
api_response.successful?.should be_false
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/spec/spec_helper.rb
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: grabz_it
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eric Berry
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Ruby interface to the GrabzIt (grabz.it) service
|
31
|
+
email:
|
32
|
+
- cavneb@gmail.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- Gemfile
|
39
|
+
- LICENSE
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- grabz_it.gemspec
|
43
|
+
- image
|
44
|
+
- lib/grabz_it.rb
|
45
|
+
- lib/grabz_it/client.rb
|
46
|
+
- lib/grabz_it/cookie.rb
|
47
|
+
- lib/grabz_it/cookie_jar.rb
|
48
|
+
- lib/grabz_it/hash.rb
|
49
|
+
- lib/grabz_it/image.rb
|
50
|
+
- lib/grabz_it/response.rb
|
51
|
+
- lib/grabz_it/status.rb
|
52
|
+
- lib/grabz_it/version.rb
|
53
|
+
- spec/client_spec.rb
|
54
|
+
- spec/image_spec.rb
|
55
|
+
- spec/response_spec.rb
|
56
|
+
- spec/spec_helper.rb
|
57
|
+
- spec/test_data/test_image.png
|
58
|
+
homepage: https://github.com/cavneb/grabz_it
|
59
|
+
licenses: []
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 1.8.24
|
79
|
+
signing_key:
|
80
|
+
specification_version: 3
|
81
|
+
summary: Ruby interface to the GrabzIt (grabz.it) service
|
82
|
+
test_files:
|
83
|
+
- spec/client_spec.rb
|
84
|
+
- spec/image_spec.rb
|
85
|
+
- spec/response_spec.rb
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
- spec/test_data/test_image.png
|
88
|
+
has_rdoc:
|