asin 0.4.0 → 0.5.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.
- data/CHANGELOG.rdoc +7 -1
- data/Gemfile.lock +10 -7
- data/README.rdoc +18 -4
- data/asin.gemspec +1 -0
- data/lib/asin.rb +5 -330
- data/lib/asin/client.rb +341 -0
- data/lib/asin/configuration.rb +3 -2
- data/lib/asin/{cart.rb → simple_cart.rb} +0 -0
- data/lib/asin/{item.rb → simple_item.rb} +0 -0
- data/lib/asin/version.rb +1 -1
- data/rakefile.rb +1 -1
- data/spec/cart_spec.rb +1 -1
- data/spec/search_spec.rb +12 -2
- metadata +72 -67
data/CHANGELOG.rdoc
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
asin (0.
|
4
|
+
asin (0.5.0)
|
5
5
|
crack (~> 0.1.8)
|
6
6
|
hashie (~> 1.0.0)
|
7
7
|
httpi (~> 0.9.2)
|
@@ -9,29 +9,31 @@ PATH
|
|
9
9
|
GEM
|
10
10
|
remote: http://rubygems.org/
|
11
11
|
specs:
|
12
|
-
chalofa_ruby-progressbar (0.0.9.1)
|
13
12
|
crack (0.1.8)
|
14
13
|
diff-lcs (1.1.2)
|
15
|
-
fuubar (0.0.
|
16
|
-
chalofa_ruby-progressbar (~> 0.0.9)
|
14
|
+
fuubar (0.0.5)
|
17
15
|
rspec (~> 2.0)
|
18
16
|
rspec-instafail (~> 0.1.4)
|
17
|
+
ruby-progressbar (~> 0.0.10)
|
19
18
|
hashie (1.0.0)
|
20
19
|
httpclient (2.2.0.2)
|
21
20
|
httpi (0.9.4)
|
22
21
|
pyu-ntlm-http (>= 0.1.3.1)
|
23
22
|
rack
|
24
23
|
pyu-ntlm-http (0.1.3.1)
|
25
|
-
rack (1.
|
24
|
+
rack (1.3.0)
|
25
|
+
rash (0.3.0)
|
26
|
+
hashie (~> 1.0.0)
|
26
27
|
rspec (2.6.0)
|
27
28
|
rspec-core (~> 2.6.0)
|
28
29
|
rspec-expectations (~> 2.6.0)
|
29
30
|
rspec-mocks (~> 2.6.0)
|
30
|
-
rspec-core (2.6.
|
31
|
+
rspec-core (2.6.4)
|
31
32
|
rspec-expectations (2.6.0)
|
32
33
|
diff-lcs (~> 1.1.2)
|
33
|
-
rspec-instafail (0.1.
|
34
|
+
rspec-instafail (0.1.8)
|
34
35
|
rspec-mocks (2.6.0)
|
36
|
+
ruby-progressbar (0.0.10)
|
35
37
|
|
36
38
|
PLATFORMS
|
37
39
|
ruby
|
@@ -40,4 +42,5 @@ DEPENDENCIES
|
|
40
42
|
asin!
|
41
43
|
fuubar (~> 0.0.4)
|
42
44
|
httpclient (~> 2.2.0.2)
|
45
|
+
rash (~> 0.3.0)
|
43
46
|
rspec (~> 2.6.0)
|
data/README.rdoc
CHANGED
@@ -39,13 +39,13 @@ ASIN is designed as a module, so you can include it into any object you like:
|
|
39
39
|
# lookup an ASIN
|
40
40
|
lookup '1430218150'
|
41
41
|
|
42
|
-
But you can also use the +
|
42
|
+
But you can also use the +instance+ method to get a proxy-object:
|
43
43
|
|
44
44
|
# just require
|
45
45
|
require 'asin'
|
46
46
|
|
47
47
|
# create an ASIN client
|
48
|
-
client = ASIN.
|
48
|
+
client = ASIN::Client.instance
|
49
49
|
|
50
50
|
# lookup an item with the amazon standard identification number (asin)
|
51
51
|
item = client.lookup '1430218150'
|
@@ -74,7 +74,7 @@ There is an additional set of methods to support AWS cart operations:
|
|
74
74
|
require 'asin'
|
75
75
|
|
76
76
|
# create an ASIN client
|
77
|
-
client = ASIN.
|
77
|
+
client = ASIN::Client.instance
|
78
78
|
|
79
79
|
# create a cart with an item
|
80
80
|
cart = client.create_cart({:asin => '1430218150', :quantity => 1})
|
@@ -101,6 +101,20 @@ There is an additional set of methods to support AWS cart operations:
|
|
101
101
|
cart.saved_items
|
102
102
|
=> [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
|
103
103
|
|
104
|
+
== Item / Cart Response
|
105
|
+
|
106
|
+
ASIN is customizable in the way it returns Responses from Amazon.
|
107
|
+
By default it will return +SimpleItem+ or +SimpleCart+ instances,
|
108
|
+
but you can override this behavior for using your custom Classes:
|
109
|
+
|
110
|
+
client.configure :item_type => YourItemClass
|
111
|
+
client.configure :cart_type => YourCartClass
|
112
|
+
|
113
|
+
You can also use built-in +:raw+, +:mash+ or +:rash+ types.
|
114
|
+
Since +rash+ is an additional library, you need to add it to your gemfile if you want to use it:
|
115
|
+
|
116
|
+
gem 'rash'
|
117
|
+
|
104
118
|
== HTTPI
|
105
119
|
|
106
120
|
ASIN uses HTTPI[https://github.com/rubiii/httpi] as a HTTP-Client adapter.
|
@@ -113,4 +127,4 @@ As a default HTTPI uses _httpclient_ so you should add that dependency to your p
|
|
113
127
|
|
114
128
|
Have a look at the RDOC[http://rdoc.info/projects/phoet/asin] for this project, if you want further information.
|
115
129
|
|
116
|
-
For more information on the REST calls, have a look at the whole Amazon E-Commerce-API[http://docs.amazonwebservices.com/
|
130
|
+
For more information on the REST calls, have a look at the whole Amazon E-Commerce-API[http://docs.amazonwebservices.com/AWSECommerceService/2010-11-01/DG/].
|
data/asin.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_dependency('httpi', '~> 0.9.2')
|
25
25
|
|
26
26
|
s.add_development_dependency('httpclient', '~> 2.2.0.2')
|
27
|
+
s.add_development_dependency('rash', '~> 0.3.0')
|
27
28
|
s.add_development_dependency('rspec', '~> 2.6.0')
|
28
29
|
s.add_development_dependency('fuubar', '~> 0.0.4')
|
29
30
|
end
|
data/lib/asin.rb
CHANGED
@@ -1,332 +1,7 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
require 'httpi'
|
3
|
-
require 'crack/xml'
|
4
|
-
require 'cgi'
|
5
|
-
require 'base64'
|
6
|
-
require 'logger'
|
7
|
-
|
8
|
-
require 'asin/item'
|
9
|
-
require 'asin/cart'
|
10
|
-
require 'asin/version'
|
11
|
-
require 'asin/configuration'
|
12
|
-
|
13
|
-
# ASIN (Amazon Simple INterface) is a gem for easy access of the Amazon E-Commerce-API.
|
14
|
-
# It is simple to configure and use. Since it's very small and flexible, it is easy to extend it to your needs.
|
15
|
-
#
|
16
|
-
# Author:: Peter Schröder (mailto:phoetmail@googlemail.com)
|
17
|
-
#
|
18
|
-
# == Usage
|
19
|
-
#
|
20
|
-
# The ASIN module is designed as a mixin.
|
21
|
-
#
|
22
|
-
# require 'asin'
|
23
|
-
# include ASIN
|
24
|
-
#
|
25
|
-
# In order to use the Amazon API properly, you need to be a registered user (http://aws.amazon.com).
|
26
|
-
#
|
27
|
-
# The registration process will give you a +secret-key+ and an +access-key+ (AWSAccessKeyId).
|
28
|
-
#
|
29
|
-
# Both are needed to use ASIN (see Configuration for more details):
|
30
|
-
#
|
31
|
-
# configure :secret => 'your-secret', :key => 'your-key'
|
32
|
-
#
|
33
|
-
# == Search
|
34
|
-
#
|
35
|
-
# After configuring your environment you can call the +lookup+ method to retrieve an +SimpleItem+ via the
|
36
|
-
# Amazon Standard Identification Number (ASIN):
|
37
|
-
#
|
38
|
-
# item = lookup '1430218150'
|
39
|
-
# item.title
|
40
|
-
# => "Learn Objective-C on the Mac (Learn Series)"
|
41
|
-
#
|
42
|
-
# OR search with fulltext/ASIN/ISBN
|
43
|
-
#
|
44
|
-
# items = search 'Learn Objective-C'
|
45
|
-
# items.first.title
|
46
|
-
# => "Learn Objective-C on the Mac (Learn Series)"
|
47
|
-
#
|
48
|
-
# The +SimpleItem+ uses a Hashie::Mash as its internal data representation and you can get fetched data from it:
|
49
|
-
#
|
50
|
-
# item.raw.ItemAttributes.ListPrice.FormattedPrice
|
51
|
-
# => "$39.99"
|
52
|
-
#
|
53
|
-
# == Further Configuration
|
54
|
-
#
|
55
|
-
# If you need more controll over the request that is sent to the
|
56
|
-
# Amazon API (http://docs.amazonwebservices.com/AWSEcommerceService/4-0/),
|
57
|
-
# you can override some defaults or add additional query-parameters to the REST calls:
|
58
|
-
#
|
59
|
-
# configure :host => 'webservices.amazon.de'
|
60
|
-
# lookup(asin, :ResponseGroup => :Medium)
|
61
|
-
#
|
62
|
-
# == Cart
|
63
|
-
#
|
64
|
-
# ASIN helps with AWS cart-operations.
|
65
|
-
# It currently supports the CartCreate, CartGet, CartAdd, CartModify and CartClear operations:
|
66
|
-
#
|
67
|
-
# cart = create_cart({:asin => '1430218150', :quantity => 1})
|
68
|
-
# cart.valid?
|
69
|
-
# cart.items
|
70
|
-
# => true
|
71
|
-
# => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
|
72
|
-
#
|
73
|
-
# cart = get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
|
74
|
-
# cart.empty?
|
75
|
-
# => false
|
76
|
-
#
|
77
|
-
# cart = clear_cart(cart)
|
78
|
-
# cart.empty?
|
79
|
-
# => true
|
80
|
-
#
|
81
|
-
# cart = add_items(cart, {:asin => '1430216263', :quantity => 2})
|
82
|
-
# cart.empty?
|
83
|
-
# => false
|
84
|
-
#
|
85
|
-
# cart = update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :action => :SaveForLater}, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
|
86
|
-
# cart.valid?
|
87
|
-
# cart.saved_items
|
88
|
-
# => true
|
89
|
-
# => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
|
90
|
-
#
|
91
1
|
module ASIN
|
92
|
-
|
93
|
-
DIGEST = OpenSSL::Digest::Digest.new('sha256')
|
94
|
-
PATH = '/onca/xml'
|
95
|
-
|
96
|
-
# Convenience method to create an ASIN client.
|
97
|
-
#
|
98
|
-
# A client is not necessary though, you can simply include the ASIN module otherwise.
|
99
|
-
#
|
100
|
-
def self.client
|
101
|
-
client = Object.new
|
102
|
-
client.extend ASIN
|
103
|
-
client
|
104
|
-
end
|
105
|
-
|
106
|
-
# Configures the basic request parameters for ASIN.
|
107
|
-
#
|
108
|
-
# Expects at least +secret+ and +key+ for the API call:
|
109
|
-
#
|
110
|
-
# configure :secret => 'your-secret', :key => 'your-key'
|
111
|
-
#
|
112
|
-
# See ASIN::Configuration for more infos.
|
113
|
-
#
|
114
|
-
def configure(options={})
|
115
|
-
Configuration.configure(options)
|
116
|
-
end
|
117
|
-
|
118
|
-
# Performs an +ItemLookup+ REST call against the Amazon API.
|
119
|
-
#
|
120
|
-
# Expects an ASIN (Amazon Standard Identification Number) and returns an +SimpleItem+:
|
121
|
-
#
|
122
|
-
# item = lookup '1430218150'
|
123
|
-
# item.title
|
124
|
-
# => "Learn Objective-C on the Mac (Learn Series)"
|
125
|
-
#
|
126
|
-
# ==== Options:
|
127
|
-
#
|
128
|
-
# Additional parameters for the API call like this:
|
129
|
-
#
|
130
|
-
# lookup(asin, :ResponseGroup => :Medium)
|
131
|
-
#
|
132
|
-
def lookup(asin, params={:ResponseGroup => :Medium})
|
133
|
-
response = call(params.merge(:Operation => :ItemLookup, :ItemId => asin))
|
134
|
-
handle_item(response['ItemLookupResponse']['Items']['Item'])
|
135
|
-
end
|
136
|
-
|
137
|
-
# Performs an +ItemSearch+ REST call against the Amazon API.
|
138
|
-
#
|
139
|
-
# Expects a search-string which can be an arbitrary array of strings (ASINs f.e.) and returns a list of +SimpleItem+s:
|
140
|
-
#
|
141
|
-
# items = search_keywords 'Learn', 'Objective-C'
|
142
|
-
# items.first.title
|
143
|
-
# => "Learn Objective-C on the Mac (Learn Series)"
|
144
|
-
#
|
145
|
-
# ==== Options:
|
146
|
-
#
|
147
|
-
# Additional parameters for the API call like this:
|
148
|
-
#
|
149
|
-
# search_keywords('nirvana', 'never mind', :SearchIndex => :Music)
|
150
|
-
#
|
151
|
-
# Have a look at the different search index values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
152
|
-
#
|
153
|
-
def search_keywords(*keywords)
|
154
|
-
params = keywords.last.is_a?(Hash) ? keywords.pop : {:SearchIndex => :Books, :ResponseGroup => :Medium}
|
155
|
-
response = call(params.merge(:Operation => :ItemSearch, :Keywords => keywords.join(' ')))
|
156
|
-
(response['ItemSearchResponse']['Items']['Item'] || []).map {|item| handle_item(item)}
|
157
|
-
end
|
158
|
-
|
159
|
-
# Performs an +ItemSearch+ REST call against the Amazon API.
|
160
|
-
#
|
161
|
-
# Expects a Hash of search params where and returns a list of +SimpleItem+s:
|
162
|
-
#
|
163
|
-
# items = search :SearchIndex => :Music
|
164
|
-
#
|
165
|
-
# ==== Options:
|
166
|
-
#
|
167
|
-
# Additional parameters for the API call like this:
|
168
|
-
#
|
169
|
-
# search(:Keywords => 'nirvana', :SearchIndex => :Music)
|
170
|
-
#
|
171
|
-
# Have a look at the different search index values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
172
|
-
#
|
173
|
-
def search(params={:SearchIndex => :Books, :ResponseGroup => :Medium})
|
174
|
-
response = call(params.merge(:Operation => :ItemSearch))
|
175
|
-
(response['ItemSearchResponse']['Items']['Item'] || []).map {|item| handle_item(item)}
|
176
|
-
end
|
177
|
-
|
178
|
-
# Performs an +CartCreate+ REST call against the Amazon API.
|
179
|
-
#
|
180
|
-
# Expects one ore more item-hashes and returns a +SimpleCart+:
|
181
|
-
#
|
182
|
-
# cart = create_cart({:asin => '1430218150', :quantity => 1})
|
183
|
-
#
|
184
|
-
# ==== Options:
|
185
|
-
#
|
186
|
-
# Additional parameters for the API call like this:
|
187
|
-
#
|
188
|
-
# create_cart({:asin => '1430218150', :quantity => 1}, {:asin => '1430216263', :quantity => 1, :action => :SaveForLater})
|
189
|
-
#
|
190
|
-
# Have a look at the different cart item operation values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
191
|
-
#
|
192
|
-
def create_cart(*items)
|
193
|
-
cart(:CartCreate, create_item_params(items))
|
194
|
-
end
|
195
|
-
|
196
|
-
# Performs an +CartGet+ REST call against the Amazon API.
|
197
|
-
#
|
198
|
-
# Expects the CartId and the HMAC to identify the returning +SimpleCart+:
|
199
|
-
#
|
200
|
-
# cart = get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
|
201
|
-
#
|
202
|
-
def get_cart(cart_id, hmac)
|
203
|
-
cart(:CartGet, {:CartId => cart_id, :HMAC => hmac})
|
204
|
-
end
|
205
|
-
|
206
|
-
# Performs an +CartAdd+ REST call against the Amazon API.
|
207
|
-
#
|
208
|
-
# Expects a +SimpleCart+ created with +create_cart+ and one ore more Item-Hashes and returns an updated +SimpleCart+:
|
209
|
-
#
|
210
|
-
# cart = add_items(cart, {:asin => '1430216263', :quantity => 2})
|
211
|
-
#
|
212
|
-
# ==== Options:
|
213
|
-
#
|
214
|
-
# Additional parameters for the API call like this:
|
215
|
-
#
|
216
|
-
# add_items(cart, {:asin => '1430218150', :quantity => 1}, {:asin => '1430216263', :quantity => 1, :action => :SaveForLater})
|
217
|
-
#
|
218
|
-
# Have a look at the different cart item operation values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
219
|
-
#
|
220
|
-
def add_items(cart, *items)
|
221
|
-
cart(:CartAdd, create_item_params(items).merge({:CartId => cart.cart_id, :HMAC => cart.hmac}))
|
222
|
-
end
|
223
|
-
|
224
|
-
# Performs an +CartModify+ REST call against the Amazon API.
|
225
|
-
#
|
226
|
-
# Expects a +SimpleCart+ created with +create_cart+ and one ore more Item-Hashes to modify and returns an updated +SimpleCart+:
|
227
|
-
#
|
228
|
-
# cart = update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
|
229
|
-
#
|
230
|
-
# ==== Options:
|
231
|
-
#
|
232
|
-
# Additional parameters for the API call like this:
|
233
|
-
#
|
234
|
-
# update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :action => :SaveForLater}, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
|
235
|
-
#
|
236
|
-
# Have a look at the different cart item operation values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
237
|
-
#
|
238
|
-
def update_items(cart, *items)
|
239
|
-
cart(:CartModify, create_item_params(items).merge({:CartId => cart.cart_id, :HMAC => cart.hmac}))
|
240
|
-
end
|
241
|
-
|
242
|
-
# Performs an +CartClear+ REST call against the Amazon API.
|
243
|
-
#
|
244
|
-
# Expects a +SimpleCart+ created with +create_cart+ and returns an empty +SimpleCart+:
|
245
|
-
#
|
246
|
-
# cart = clear_cart(cart)
|
247
|
-
#
|
248
|
-
def clear_cart(cart)
|
249
|
-
cart(:CartClear, {:CartId => cart.cart_id, :HMAC => cart.hmac})
|
250
|
-
end
|
251
|
-
|
252
|
-
private
|
253
|
-
|
254
|
-
def handle_item(item)
|
255
|
-
Configuration.item_type.is_a?(Class) ? Configuration.item_type.new(item) : item
|
256
|
-
end
|
257
|
-
|
258
|
-
def create_item_params(items)
|
259
|
-
keyword_mappings = {
|
260
|
-
:asin => 'ASIN',
|
261
|
-
:quantity => 'Quantity',
|
262
|
-
:cart_item_id => 'CartItemId',
|
263
|
-
:offer_listing_id => 'OfferListingId',
|
264
|
-
:action => 'Action'
|
265
|
-
}
|
266
|
-
params = {}
|
267
|
-
items.each_with_index do |item, i|
|
268
|
-
item.each do |key, value|
|
269
|
-
next unless keyword = keyword_mappings[key]
|
270
|
-
params["Item.#{i}.#{keyword}"] = value.to_s
|
271
|
-
end
|
272
|
-
end
|
273
|
-
params
|
274
|
-
end
|
275
|
-
|
276
|
-
def cart(operation, params={})
|
277
|
-
response = call(params.merge(:Operation => operation))
|
278
|
-
cart = response["#{operation}Response"]['Cart']
|
279
|
-
Configuration.cart_type.is_a?(Class) ? Configuration.cart_type.new(cart) : cart
|
280
|
-
end
|
281
|
-
|
282
|
-
|
283
|
-
def credentials_valid?
|
284
|
-
Configuration.secret && Configuration.key
|
285
|
-
end
|
286
|
-
|
287
|
-
def call(params)
|
288
|
-
raise "you have to configure ASIN: 'configure :secret => 'your-secret', :key => 'your-key''" unless credentials_valid?
|
289
|
-
|
290
|
-
log(:debug, "calling with params=#{params}")
|
291
|
-
signed = create_signed_query_string(params)
|
292
|
-
|
293
|
-
url = "http://#{Configuration.host}#{PATH}?#{signed}"
|
294
|
-
log(:info, "performing rest call to url='#{url}'")
|
295
|
-
|
296
|
-
response = HTTPI.get(url)
|
297
|
-
if response.code == 200
|
298
|
-
# force utf-8 chars, works only on 1.9 string
|
299
|
-
resp = response.body
|
300
|
-
resp = resp.force_encoding('UTF-8') if resp.respond_to? :force_encoding
|
301
|
-
log(:debug, "got response='#{resp}'")
|
302
|
-
Crack::XML.parse(resp)
|
303
|
-
else
|
304
|
-
log(:error, "got response='#{response.body}'")
|
305
|
-
raise "request failed with response-code='#{response.code}'"
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
def create_signed_query_string(params)
|
310
|
-
# nice tutorial http://cloudcarpenters.com/blog/amazon_products_api_request_signing/
|
311
|
-
params[:Service] = :AWSECommerceService
|
312
|
-
params[:AWSAccessKeyId] = Configuration.key
|
313
|
-
# utc timestamp needed for signing
|
314
|
-
params[:Timestamp] = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
|
315
|
-
|
316
|
-
# signing needs to order the query alphabetically
|
317
|
-
query = params.map{|key, value| "#{key}=#{CGI.escape(value.to_s)}" }.sort.join('&').gsub('+','%20')
|
318
|
-
|
319
|
-
# yeah, you really need to sign the get-request not the query
|
320
|
-
request_to_sign = "GET\n#{Configuration.host}\n#{PATH}\n#{query}"
|
321
|
-
hmac = OpenSSL::HMAC.digest(DIGEST, Configuration.secret, request_to_sign)
|
322
|
-
|
323
|
-
# don't forget to remove the newline from base64
|
324
|
-
signature = CGI.escape(Base64.encode64(hmac).chomp)
|
325
|
-
"#{query}&Signature=#{signature}"
|
326
|
-
end
|
327
|
-
|
328
|
-
def log(severity, message)
|
329
|
-
Configuration.logger.send severity, message if Configuration.logger
|
330
|
-
end
|
331
|
-
|
332
2
|
end
|
3
|
+
ASIN.autoload :Client, 'asin/client'
|
4
|
+
ASIN.autoload :SimpleItem, 'asin/simple_item'
|
5
|
+
ASIN.autoload :SimpleCart, 'asin/simple_cart'
|
6
|
+
ASIN.autoload :Version, 'asin/version'
|
7
|
+
ASIN.autoload :Configuration, 'asin/configuration'
|
data/lib/asin/client.rb
ADDED
@@ -0,0 +1,341 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'httpi'
|
3
|
+
require 'crack/xml'
|
4
|
+
require 'cgi'
|
5
|
+
require 'base64'
|
6
|
+
|
7
|
+
# ASIN (Amazon Simple INterface) is a gem for easy access of the Amazon E-Commerce-API.
|
8
|
+
# It is simple to configure and use. Since it's very small and flexible, it is easy to extend it to your needs.
|
9
|
+
#
|
10
|
+
# Author:: Peter Schröder (mailto:phoetmail@googlemail.com)
|
11
|
+
#
|
12
|
+
# == Usage
|
13
|
+
#
|
14
|
+
# The ASIN module is designed as a mixin.
|
15
|
+
#
|
16
|
+
# require 'asin'
|
17
|
+
# include ASIN::Client
|
18
|
+
#
|
19
|
+
# In order to use the Amazon API properly, you need to be a registered user (http://aws.amazon.com).
|
20
|
+
#
|
21
|
+
# The registration process will give you a +secret-key+ and an +access-key+ (AWSAccessKeyId).
|
22
|
+
#
|
23
|
+
# Both are needed to use ASIN (see Configuration for more details):
|
24
|
+
#
|
25
|
+
# configure :secret => 'your-secret', :key => 'your-key'
|
26
|
+
#
|
27
|
+
# == Search
|
28
|
+
#
|
29
|
+
# After configuring your environment you can call the +lookup+ method to retrieve an +SimpleItem+ via the
|
30
|
+
# Amazon Standard Identification Number (ASIN):
|
31
|
+
#
|
32
|
+
# item = lookup '1430218150'
|
33
|
+
# item.title
|
34
|
+
# => "Learn Objective-C on the Mac (Learn Series)"
|
35
|
+
#
|
36
|
+
# OR search with fulltext/ASIN/ISBN
|
37
|
+
#
|
38
|
+
# items = search 'Learn Objective-C'
|
39
|
+
# items.first.title
|
40
|
+
# => "Learn Objective-C on the Mac (Learn Series)"
|
41
|
+
#
|
42
|
+
# The +SimpleItem+ uses a Hashie::Mash as its internal data representation and you can get fetched data from it:
|
43
|
+
#
|
44
|
+
# item.raw.ItemAttributes.ListPrice.FormattedPrice
|
45
|
+
# => "$39.99"
|
46
|
+
#
|
47
|
+
# == Further Configuration
|
48
|
+
#
|
49
|
+
# If you need more controll over the request that is sent to the
|
50
|
+
# Amazon API (http://docs.amazonwebservices.com/AWSEcommerceService/4-0/),
|
51
|
+
# you can override some defaults or add additional query-parameters to the REST calls:
|
52
|
+
#
|
53
|
+
# configure :host => 'webservices.amazon.de'
|
54
|
+
# lookup(asin, :ResponseGroup => :Medium)
|
55
|
+
#
|
56
|
+
# == Cart
|
57
|
+
#
|
58
|
+
# ASIN helps with AWS cart-operations.
|
59
|
+
# It currently supports the CartCreate, CartGet, CartAdd, CartModify and CartClear operations:
|
60
|
+
#
|
61
|
+
# cart = create_cart({:asin => '1430218150', :quantity => 1})
|
62
|
+
# cart.valid?
|
63
|
+
# cart.items
|
64
|
+
# => true
|
65
|
+
# => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
|
66
|
+
#
|
67
|
+
# cart = get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
|
68
|
+
# cart.empty?
|
69
|
+
# => false
|
70
|
+
#
|
71
|
+
# cart = clear_cart(cart)
|
72
|
+
# cart.empty?
|
73
|
+
# => true
|
74
|
+
#
|
75
|
+
# cart = add_items(cart, {:asin => '1430216263', :quantity => 2})
|
76
|
+
# cart.empty?
|
77
|
+
# => false
|
78
|
+
#
|
79
|
+
# cart = update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :action => :SaveForLater}, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
|
80
|
+
# cart.valid?
|
81
|
+
# cart.saved_items
|
82
|
+
# => true
|
83
|
+
# => [<#Hashie::Mash ASIN="1430218150" CartItemId="U3G241HVLLB8N6" ... >]
|
84
|
+
#
|
85
|
+
module ASIN
|
86
|
+
module Client
|
87
|
+
|
88
|
+
DIGEST = OpenSSL::Digest::Digest.new('sha256')
|
89
|
+
PATH = '/onca/xml'
|
90
|
+
|
91
|
+
# Convenience method to create an ASIN client.
|
92
|
+
#
|
93
|
+
# An instance is not necessary though, you can simply include the ASIN module otherwise.
|
94
|
+
#
|
95
|
+
def self.instance
|
96
|
+
ins = Object.new
|
97
|
+
ins.extend ASIN::Client
|
98
|
+
ins
|
99
|
+
end
|
100
|
+
|
101
|
+
# Configures the basic request parameters for ASIN.
|
102
|
+
#
|
103
|
+
# Expects at least +secret+ and +key+ for the API call:
|
104
|
+
#
|
105
|
+
# configure :secret => 'your-secret', :key => 'your-key'
|
106
|
+
#
|
107
|
+
# See ASIN::Configuration for more infos.
|
108
|
+
#
|
109
|
+
def configure(options={})
|
110
|
+
Configuration.configure(options)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Performs an +ItemLookup+ REST call against the Amazon API.
|
114
|
+
#
|
115
|
+
# Expects an ASIN (Amazon Standard Identification Number) and returns an +SimpleItem+:
|
116
|
+
#
|
117
|
+
# item = lookup '1430218150'
|
118
|
+
# item.title
|
119
|
+
# => "Learn Objective-C on the Mac (Learn Series)"
|
120
|
+
#
|
121
|
+
# ==== Options:
|
122
|
+
#
|
123
|
+
# Additional parameters for the API call like this:
|
124
|
+
#
|
125
|
+
# lookup(asin, :ResponseGroup => :Medium)
|
126
|
+
#
|
127
|
+
def lookup(asin, params={:ResponseGroup => :Medium})
|
128
|
+
response = call(params.merge(:Operation => :ItemLookup, :ItemId => asin))
|
129
|
+
handle_item(response['ItemLookupResponse']['Items']['Item'])
|
130
|
+
end
|
131
|
+
|
132
|
+
# Performs an +ItemSearch+ REST call against the Amazon API.
|
133
|
+
#
|
134
|
+
# Expects a search-string which can be an arbitrary array of strings (ASINs f.e.) and returns a list of +SimpleItem+s:
|
135
|
+
#
|
136
|
+
# items = search_keywords 'Learn', 'Objective-C'
|
137
|
+
# items.first.title
|
138
|
+
# => "Learn Objective-C on the Mac (Learn Series)"
|
139
|
+
#
|
140
|
+
# ==== Options:
|
141
|
+
#
|
142
|
+
# Additional parameters for the API call like this:
|
143
|
+
#
|
144
|
+
# search_keywords('nirvana', 'never mind', :SearchIndex => :Music)
|
145
|
+
#
|
146
|
+
# Have a look at the different search index values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
147
|
+
#
|
148
|
+
def search_keywords(*keywords)
|
149
|
+
params = keywords.last.is_a?(Hash) ? keywords.pop : {:SearchIndex => :Books, :ResponseGroup => :Medium}
|
150
|
+
response = call(params.merge(:Operation => :ItemSearch, :Keywords => keywords.join(' ')))
|
151
|
+
(response['ItemSearchResponse']['Items']['Item'] || []).map {|item| handle_item(item)}
|
152
|
+
end
|
153
|
+
|
154
|
+
# Performs an +ItemSearch+ REST call against the Amazon API.
|
155
|
+
#
|
156
|
+
# Expects a Hash of search params where and returns a list of +SimpleItem+s:
|
157
|
+
#
|
158
|
+
# items = search :SearchIndex => :Music
|
159
|
+
#
|
160
|
+
# ==== Options:
|
161
|
+
#
|
162
|
+
# Additional parameters for the API call like this:
|
163
|
+
#
|
164
|
+
# search(:Keywords => 'nirvana', :SearchIndex => :Music)
|
165
|
+
#
|
166
|
+
# Have a look at the different search index values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
167
|
+
#
|
168
|
+
def search(params={:SearchIndex => :Books, :ResponseGroup => :Medium})
|
169
|
+
response = call(params.merge(:Operation => :ItemSearch))
|
170
|
+
(response['ItemSearchResponse']['Items']['Item'] || []).map {|item| handle_item(item)}
|
171
|
+
end
|
172
|
+
|
173
|
+
# Performs an +CartCreate+ REST call against the Amazon API.
|
174
|
+
#
|
175
|
+
# Expects one ore more item-hashes and returns a +SimpleCart+:
|
176
|
+
#
|
177
|
+
# cart = create_cart({:asin => '1430218150', :quantity => 1})
|
178
|
+
#
|
179
|
+
# ==== Options:
|
180
|
+
#
|
181
|
+
# Additional parameters for the API call like this:
|
182
|
+
#
|
183
|
+
# create_cart({:asin => '1430218150', :quantity => 1}, {:asin => '1430216263', :quantity => 1, :action => :SaveForLater})
|
184
|
+
#
|
185
|
+
# Have a look at the different cart item operation values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
186
|
+
#
|
187
|
+
def create_cart(*items)
|
188
|
+
cart(:CartCreate, create_item_params(items))
|
189
|
+
end
|
190
|
+
|
191
|
+
# Performs an +CartGet+ REST call against the Amazon API.
|
192
|
+
#
|
193
|
+
# Expects the CartId and the HMAC to identify the returning +SimpleCart+:
|
194
|
+
#
|
195
|
+
# cart = get_cart('176-9182855-2326919', 'KgeVCA0YJTbuN/7Ibakrk/KnHWA=')
|
196
|
+
#
|
197
|
+
def get_cart(cart_id, hmac)
|
198
|
+
cart(:CartGet, {:CartId => cart_id, :HMAC => hmac})
|
199
|
+
end
|
200
|
+
|
201
|
+
# Performs an +CartAdd+ REST call against the Amazon API.
|
202
|
+
#
|
203
|
+
# Expects a +SimpleCart+ created with +create_cart+ and one ore more Item-Hashes and returns an updated +SimpleCart+:
|
204
|
+
#
|
205
|
+
# cart = add_items(cart, {:asin => '1430216263', :quantity => 2})
|
206
|
+
#
|
207
|
+
# ==== Options:
|
208
|
+
#
|
209
|
+
# Additional parameters for the API call like this:
|
210
|
+
#
|
211
|
+
# add_items(cart, {:asin => '1430218150', :quantity => 1}, {:asin => '1430216263', :quantity => 1, :action => :SaveForLater})
|
212
|
+
#
|
213
|
+
# Have a look at the different cart item operation values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
214
|
+
#
|
215
|
+
def add_items(cart, *items)
|
216
|
+
cart(:CartAdd, create_item_params(items).merge({:CartId => cart.cart_id, :HMAC => cart.hmac}))
|
217
|
+
end
|
218
|
+
|
219
|
+
# Performs an +CartModify+ REST call against the Amazon API.
|
220
|
+
#
|
221
|
+
# Expects a +SimpleCart+ created with +create_cart+ and one ore more Item-Hashes to modify and returns an updated +SimpleCart+:
|
222
|
+
#
|
223
|
+
# cart = update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
|
224
|
+
#
|
225
|
+
# ==== Options:
|
226
|
+
#
|
227
|
+
# Additional parameters for the API call like this:
|
228
|
+
#
|
229
|
+
# update_items(cart, {:cart_item_id => cart.items.first.CartItemId, :action => :SaveForLater}, {:cart_item_id => cart.items.first.CartItemId, :quantity => 7})
|
230
|
+
#
|
231
|
+
# Have a look at the different cart item operation values on the Amazon-Documentation[http://docs.amazonwebservices.com/AWSEcommerceService/4-0/]
|
232
|
+
#
|
233
|
+
def update_items(cart, *items)
|
234
|
+
cart(:CartModify, create_item_params(items).merge({:CartId => cart.cart_id, :HMAC => cart.hmac}))
|
235
|
+
end
|
236
|
+
|
237
|
+
# Performs an +CartClear+ REST call against the Amazon API.
|
238
|
+
#
|
239
|
+
# Expects a +SimpleCart+ created with +create_cart+ and returns an empty +SimpleCart+:
|
240
|
+
#
|
241
|
+
# cart = clear_cart(cart)
|
242
|
+
#
|
243
|
+
def clear_cart(cart)
|
244
|
+
cart(:CartClear, {:CartId => cart.cart_id, :HMAC => cart.hmac})
|
245
|
+
end
|
246
|
+
|
247
|
+
private()
|
248
|
+
|
249
|
+
def handle_item(item)
|
250
|
+
handle_type(item, Configuration.item_type)
|
251
|
+
end
|
252
|
+
|
253
|
+
def handle_type(data, type)
|
254
|
+
if type.is_a?(Class)
|
255
|
+
type.new(data)
|
256
|
+
elsif type == :mash
|
257
|
+
require 'hashie'
|
258
|
+
Hashie::Mash.new(data)
|
259
|
+
elsif type == :rash
|
260
|
+
require 'rash'
|
261
|
+
Hashie::Rash.new(data)
|
262
|
+
else
|
263
|
+
data
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def create_item_params(items)
|
268
|
+
keyword_mappings = {
|
269
|
+
:asin => 'ASIN',
|
270
|
+
:quantity => 'Quantity',
|
271
|
+
:cart_item_id => 'CartItemId',
|
272
|
+
:offer_listing_id => 'OfferListingId',
|
273
|
+
:action => 'Action'
|
274
|
+
}
|
275
|
+
params = {}
|
276
|
+
items.each_with_index do |item, i|
|
277
|
+
item.each do |key, value|
|
278
|
+
next unless keyword = keyword_mappings[key]
|
279
|
+
params["Item.#{i}.#{keyword}"] = value.to_s
|
280
|
+
end
|
281
|
+
end
|
282
|
+
params
|
283
|
+
end
|
284
|
+
|
285
|
+
def cart(operation, params={})
|
286
|
+
response = call(params.merge(:Operation => operation))
|
287
|
+
cart = response["#{operation}Response"]['Cart']
|
288
|
+
handle_type(cart, Configuration.cart_type)
|
289
|
+
end
|
290
|
+
|
291
|
+
|
292
|
+
def credentials_valid?
|
293
|
+
Configuration.secret && Configuration.key
|
294
|
+
end
|
295
|
+
|
296
|
+
def call(params)
|
297
|
+
raise "you have to configure ASIN: 'configure :secret => 'your-secret', :key => 'your-key''" unless credentials_valid?
|
298
|
+
|
299
|
+
log(:debug, "calling with params=#{params}")
|
300
|
+
signed = create_signed_query_string(params)
|
301
|
+
|
302
|
+
url = "http://#{Configuration.host}#{PATH}?#{signed}"
|
303
|
+
log(:info, "performing rest call to url='#{url}'")
|
304
|
+
|
305
|
+
response = HTTPI.get(url)
|
306
|
+
if response.code == 200
|
307
|
+
# force utf-8 chars, works only on 1.9 string
|
308
|
+
resp = response.body
|
309
|
+
resp = resp.force_encoding('UTF-8') if resp.respond_to? :force_encoding
|
310
|
+
log(:debug, "got response='#{resp}'")
|
311
|
+
Crack::XML.parse(resp)
|
312
|
+
else
|
313
|
+
log(:error, "got response='#{response.body}'")
|
314
|
+
raise "request failed with response-code='#{response.code}'"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def create_signed_query_string(params)
|
319
|
+
# nice tutorial http://cloudcarpenters.com/blog/amazon_products_api_request_signing/
|
320
|
+
params[:Service] = :AWSECommerceService
|
321
|
+
params[:AWSAccessKeyId] = Configuration.key
|
322
|
+
# utc timestamp needed for signing
|
323
|
+
params[:Timestamp] = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
|
324
|
+
|
325
|
+
# signing needs to order the query alphabetically
|
326
|
+
query = params.map{|key, value| "#{key}=#{CGI.escape(value.to_s)}" }.sort.join('&').gsub('+','%20')
|
327
|
+
|
328
|
+
# yeah, you really need to sign the get-request not the query
|
329
|
+
request_to_sign = "GET\n#{Configuration.host}\n#{PATH}\n#{query}"
|
330
|
+
hmac = OpenSSL::HMAC.digest(DIGEST, Configuration.secret, request_to_sign)
|
331
|
+
|
332
|
+
# don't forget to remove the newline from base64
|
333
|
+
signature = CGI.escape(Base64.encode64(hmac).chomp)
|
334
|
+
"#{query}&Signature=#{signature}"
|
335
|
+
end
|
336
|
+
|
337
|
+
def log(severity, message)
|
338
|
+
Configuration.logger.send severity, message if Configuration.logger
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
data/lib/asin/configuration.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "yaml"
|
2
|
+
require 'logger'
|
2
3
|
|
3
4
|
module ASIN
|
4
5
|
class Configuration
|
@@ -34,8 +35,8 @@ module ASIN
|
|
34
35
|
# [key] the API access key
|
35
36
|
# [host] the host, which defaults to 'webservices.amazon.com'
|
36
37
|
# [logger] a different logger than logging to STDERR (nil for no logging)
|
37
|
-
# [item_type] a different class for SimpleItem, use :raw for a plain
|
38
|
-
# [cart_type] a different class for SimpleCart, use :raw for a plain
|
38
|
+
# [item_type] a different class for SimpleItem, use :mash / :rash for Hashie::Mash / Hashie::Rash or :raw for a plain hash
|
39
|
+
# [cart_type] a different class for SimpleCart, use :mash / :rash for Hashie::Mash / Hashie::Rash or :raw for a plain hash
|
39
40
|
#
|
40
41
|
def configure(options={})
|
41
42
|
init_config
|
File without changes
|
File without changes
|
data/lib/asin/version.rb
CHANGED
data/rakefile.rb
CHANGED
@@ -11,7 +11,7 @@ end
|
|
11
11
|
|
12
12
|
Rake::RDocTask.new(:rdoc_dev) do |rd|
|
13
13
|
rd.rdoc_files.include(File.readlines('.document').map(&:strip))
|
14
|
-
rd.options + ['-a', '--
|
14
|
+
rd.options + ['-a', '--line-numbers', '--charset=UTF-8']
|
15
15
|
end
|
16
16
|
|
17
17
|
task :default=>:spec
|
data/spec/cart_spec.rb
CHANGED
data/spec/search_spec.rb
CHANGED
@@ -4,7 +4,7 @@ module ASIN
|
|
4
4
|
describe ASIN do
|
5
5
|
before do
|
6
6
|
ASIN::Configuration.reset
|
7
|
-
@helper = ASIN.
|
7
|
+
@helper = ASIN::Client.instance
|
8
8
|
@helper.configure :logger => nil
|
9
9
|
|
10
10
|
@secret = ENV['ASIN_SECRET']
|
@@ -93,6 +93,16 @@ module ASIN
|
|
93
93
|
@helper.lookup(ANY_ASIN)['ItemAttributes']['Title'].should_not be_nil
|
94
94
|
end
|
95
95
|
|
96
|
+
it "should return a mash value" do
|
97
|
+
@helper.configure :item_type => :mash
|
98
|
+
@helper.lookup(ANY_ASIN).ItemAttributes.Title.should_not be_nil
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should return a rash value" do
|
102
|
+
@helper.configure :item_type => :rash
|
103
|
+
@helper.lookup(ANY_ASIN).item_attributes.title.should_not be_nil
|
104
|
+
end
|
105
|
+
|
96
106
|
it "should search_keywords a book with fulltext" do
|
97
107
|
items = @helper.search_keywords 'Learn', 'Objective-C'
|
98
108
|
items.should have(10).things
|
@@ -102,7 +112,7 @@ module ASIN
|
|
102
112
|
|
103
113
|
it "should search_keywords never mind music" do
|
104
114
|
items = @helper.search_keywords 'nirvana', 'never mind', :SearchIndex => :Music
|
105
|
-
items.should have(
|
115
|
+
items.should have(9).things
|
106
116
|
|
107
117
|
items.first.title.should =~ /Nevermind/
|
108
118
|
end
|
metadata
CHANGED
@@ -1,94 +1,101 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: asin
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.4.0
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
-
|
7
|
+
authors:
|
8
|
+
- Peter Schröder
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2011-05-20 00:00:00 +02:00
|
12
|
+
date: 2011-07-07 00:00:00.000000000 +02:00
|
14
13
|
default_executable:
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
17
16
|
name: crack
|
18
|
-
|
19
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
17
|
+
requirement: &2153571760 !ruby/object:Gem::Requirement
|
20
18
|
none: false
|
21
|
-
requirements:
|
19
|
+
requirements:
|
22
20
|
- - ~>
|
23
|
-
- !ruby/object:Gem::Version
|
21
|
+
- !ruby/object:Gem::Version
|
24
22
|
version: 0.1.8
|
25
23
|
type: :runtime
|
26
|
-
version_requirements: *id001
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: hashie
|
29
24
|
prerelease: false
|
30
|
-
|
25
|
+
version_requirements: *2153571760
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: hashie
|
28
|
+
requirement: &2153571260 !ruby/object:Gem::Requirement
|
31
29
|
none: false
|
32
|
-
requirements:
|
30
|
+
requirements:
|
33
31
|
- - ~>
|
34
|
-
- !ruby/object:Gem::Version
|
32
|
+
- !ruby/object:Gem::Version
|
35
33
|
version: 1.0.0
|
36
34
|
type: :runtime
|
37
|
-
version_requirements: *id002
|
38
|
-
- !ruby/object:Gem::Dependency
|
39
|
-
name: httpi
|
40
35
|
prerelease: false
|
41
|
-
|
36
|
+
version_requirements: *2153571260
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: httpi
|
39
|
+
requirement: &2153570800 !ruby/object:Gem::Requirement
|
42
40
|
none: false
|
43
|
-
requirements:
|
41
|
+
requirements:
|
44
42
|
- - ~>
|
45
|
-
- !ruby/object:Gem::Version
|
43
|
+
- !ruby/object:Gem::Version
|
46
44
|
version: 0.9.2
|
47
45
|
type: :runtime
|
48
|
-
version_requirements: *id003
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: httpclient
|
51
46
|
prerelease: false
|
52
|
-
|
47
|
+
version_requirements: *2153570800
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: httpclient
|
50
|
+
requirement: &2153570340 !ruby/object:Gem::Requirement
|
53
51
|
none: false
|
54
|
-
requirements:
|
52
|
+
requirements:
|
55
53
|
- - ~>
|
56
|
-
- !ruby/object:Gem::Version
|
54
|
+
- !ruby/object:Gem::Version
|
57
55
|
version: 2.2.0.2
|
58
56
|
type: :development
|
59
|
-
version_requirements: *id004
|
60
|
-
- !ruby/object:Gem::Dependency
|
61
|
-
name: rspec
|
62
57
|
prerelease: false
|
63
|
-
|
58
|
+
version_requirements: *2153570340
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rash
|
61
|
+
requirement: &2168479800 !ruby/object:Gem::Requirement
|
64
62
|
none: false
|
65
|
-
requirements:
|
63
|
+
requirements:
|
66
64
|
- - ~>
|
67
|
-
- !ruby/object:Gem::Version
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 0.3.0
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *2168479800
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec
|
72
|
+
requirement: &2168479340 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
68
77
|
version: 2.6.0
|
69
78
|
type: :development
|
70
|
-
version_requirements: *id005
|
71
|
-
- !ruby/object:Gem::Dependency
|
72
|
-
name: fuubar
|
73
79
|
prerelease: false
|
74
|
-
|
80
|
+
version_requirements: *2168479340
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: fuubar
|
83
|
+
requirement: &2168478880 !ruby/object:Gem::Requirement
|
75
84
|
none: false
|
76
|
-
requirements:
|
85
|
+
requirements:
|
77
86
|
- - ~>
|
78
|
-
- !ruby/object:Gem::Version
|
87
|
+
- !ruby/object:Gem::Version
|
79
88
|
version: 0.0.4
|
80
89
|
type: :development
|
81
|
-
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: *2168478880
|
82
92
|
description: Amazon Simple INterface.
|
83
|
-
email:
|
93
|
+
email:
|
84
94
|
- phoetmail@googlemail.com
|
85
95
|
executables: []
|
86
|
-
|
87
96
|
extensions: []
|
88
|
-
|
89
97
|
extra_rdoc_files: []
|
90
|
-
|
91
|
-
files:
|
98
|
+
files:
|
92
99
|
- .document
|
93
100
|
- .gitignore
|
94
101
|
- .rvmrc
|
@@ -98,9 +105,10 @@ files:
|
|
98
105
|
- README.rdoc
|
99
106
|
- asin.gemspec
|
100
107
|
- lib/asin.rb
|
101
|
-
- lib/asin/
|
108
|
+
- lib/asin/client.rb
|
102
109
|
- lib/asin/configuration.rb
|
103
|
-
- lib/asin/
|
110
|
+
- lib/asin/simple_cart.rb
|
111
|
+
- lib/asin/simple_item.rb
|
104
112
|
- lib/asin/version.rb
|
105
113
|
- rakefile.rb
|
106
114
|
- spec/asin.yml
|
@@ -110,32 +118,29 @@ files:
|
|
110
118
|
has_rdoc: true
|
111
119
|
homepage: http://github.com/phoet/asin
|
112
120
|
licenses: []
|
113
|
-
|
114
121
|
post_install_message:
|
115
122
|
rdoc_options: []
|
116
|
-
|
117
|
-
require_paths:
|
123
|
+
require_paths:
|
118
124
|
- lib
|
119
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
126
|
none: false
|
121
|
-
requirements:
|
122
|
-
- -
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version:
|
125
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ! '>='
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
132
|
none: false
|
127
|
-
requirements:
|
128
|
-
- -
|
129
|
-
- !ruby/object:Gem::Version
|
130
|
-
version:
|
133
|
+
requirements:
|
134
|
+
- - ! '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
131
137
|
requirements: []
|
132
|
-
|
133
138
|
rubyforge_project: asin
|
134
|
-
rubygems_version: 1.
|
139
|
+
rubygems_version: 1.6.2
|
135
140
|
signing_key:
|
136
141
|
specification_version: 3
|
137
142
|
summary: Simple interface to AWS Lookup, Search and Cart operations.
|
138
|
-
test_files:
|
143
|
+
test_files:
|
139
144
|
- spec/asin.yml
|
140
145
|
- spec/cart_spec.rb
|
141
146
|
- spec/search_spec.rb
|