amazonian 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/amazonian/version.rb +1 -1
- data/lib/amazonian.rb +37 -13
- metadata +3 -3
data/lib/amazonian/version.rb
CHANGED
data/lib/amazonian.rb
CHANGED
@@ -48,20 +48,33 @@ module Amazonian
|
|
48
48
|
def self.asin(asin, params={})
|
49
49
|
params = params.merge :Operation => :ItemLookup, :ItemId => asin
|
50
50
|
xml = self.call params
|
51
|
-
Item.new xml
|
51
|
+
Item.new xml['ItemLookupResponse']['Items']['Item']
|
52
52
|
end
|
53
53
|
|
54
|
-
|
54
|
+
def self.search(query, params={})
|
55
|
+
params = params.merge :Operation => :ItemSearch,
|
56
|
+
:Keywords => query
|
57
|
+
|
58
|
+
params[:SearchIndex] = :Music if params[:SearchIndex].nil?
|
59
|
+
|
60
|
+
xml = self.call params
|
61
|
+
Search.new xml['ItemSearchResponse']
|
62
|
+
end
|
63
|
+
|
64
|
+
#private
|
55
65
|
|
56
66
|
def self.call(params)
|
57
67
|
raise "Cannot call the Amazon API without key and secret key." if @@key.blank? || @@secret.blank?
|
58
68
|
|
59
69
|
#get the signed query, and assemble the querystring
|
60
|
-
log :debug, "
|
70
|
+
log :debug, "Started Amazonian request for params: #{params.map {|p| "#{p[0]}=>#{p[1]}" }.join ','}" if @@debug
|
61
71
|
|
62
72
|
#memoize the last request for faster API querying...
|
63
73
|
query = assemble_querystring params
|
64
|
-
|
74
|
+
if query == @@query
|
75
|
+
log :debug, "MEMO'D! Shortcutting API call for dup request."
|
76
|
+
return Crack::XML.parse @@response.body
|
77
|
+
end
|
65
78
|
@@query = query
|
66
79
|
|
67
80
|
#sign the query
|
@@ -76,7 +89,9 @@ module Amazonian
|
|
76
89
|
|
77
90
|
log :debug, "Response Code: #{@@response.status}" if @@debug
|
78
91
|
|
79
|
-
|
92
|
+
#todo, this memo logic is broken....an error code is not always without a body
|
93
|
+
log :error, "Amazon API Error: #{@@response.status}" if @@response.status >= 400
|
94
|
+
|
80
95
|
#parse the response and return it
|
81
96
|
Crack::XML.parse @@response.body
|
82
97
|
end
|
@@ -88,25 +103,28 @@ module Amazonian
|
|
88
103
|
|
89
104
|
# CGI escape each param
|
90
105
|
# signing needs to order the query alphabetically
|
91
|
-
params.map{|key, value| "#{key}=#{CGI.escape(value.to_s)}" }.sort.join('&')
|
106
|
+
params.map{|key, value| "#{key}=#{CGI.escape(value.to_s)}" }.sort.join('&').gsub('+','%20')
|
92
107
|
end
|
93
108
|
|
94
109
|
def self.sign_query(query)
|
110
|
+
#make a copy... fixme fixme I'm awkward
|
95
111
|
q = query.clone
|
96
112
|
# UTC timestamp needed for signing
|
97
113
|
q <<= '&Timestamp=' << CGI.escape(Time.now.utc.strftime '%Y-%m-%dT%H:%M:%SZ')
|
98
114
|
|
99
115
|
# Sign the entire get-request (not just the querystring)
|
100
116
|
# possible gotcha if Patron starts using more/different headers.
|
101
|
-
request_to_sign =
|
117
|
+
request_to_sign = "GET\n#{@@host}\n#{@@path}\n#{q}"
|
118
|
+
|
119
|
+
"#{q}&Signature=#{sign_request request_to_sign}"
|
120
|
+
end
|
102
121
|
|
122
|
+
def self.sign_request(request_to_sign)
|
103
123
|
# Sign it.
|
104
124
|
hmac = OpenSSL::HMAC.digest(@@digest, @@secret, request_to_sign)
|
105
125
|
|
106
126
|
# Don't forget to remove the newline from base64
|
107
|
-
|
108
|
-
|
109
|
-
"#{q}&Signature=#{signature}"
|
127
|
+
CGI.escape(Base64.encode64(hmac).chomp)
|
110
128
|
end
|
111
129
|
|
112
130
|
def self.log(severity, message)
|
@@ -121,17 +139,23 @@ module Amazonian
|
|
121
139
|
# A Hashie::Mash is used for the internal data representation and can be accessed over the +raw+ attribute.
|
122
140
|
#
|
123
141
|
class Item
|
124
|
-
|
125
142
|
attr_reader :raw
|
126
|
-
|
127
143
|
def initialize(hash)
|
128
|
-
@raw = Hashie::Mash.new(hash)
|
144
|
+
@raw = Hashie::Mash.new(hash)
|
129
145
|
end
|
130
146
|
|
131
147
|
def title
|
132
148
|
@raw.ItemAttributes.Title
|
133
149
|
end
|
150
|
+
end
|
134
151
|
|
152
|
+
class Search
|
153
|
+
attr_reader :items
|
154
|
+
def initialize(hash)
|
155
|
+
@raw = Hashie::Mash.new(hash)
|
156
|
+
@items = []
|
157
|
+
@raw.Items.Item.each {|i| @items.push Amazonian::Item.new(i) }
|
158
|
+
end
|
135
159
|
end
|
136
160
|
|
137
161
|
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.2
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Robert L. Carpenter
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-29 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|