peddler 0.12.7 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +80 -41
- data/lib/peddler/client.rb +39 -17
- data/lib/peddler/marketplace.rb +2 -2
- data/lib/peddler/parser.rb +1 -1
- data/lib/peddler/version.rb +1 -1
- data/test/unit/mws/test_fulfillment_inbound_shipment_client.rb +5 -3
- data/test/unit/peddler/test_client.rb +55 -2
- data/test/unit/peddler/test_marketplace.rb +8 -2
- data/test/unit/peddler/test_parser.rb +1 -1
- metadata +2 -5
- data/lib/peddler/flat_file_response.rb +0 -53
- data/lib/peddler/response.rb +0 -24
- data/lib/peddler/xml_response.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9dd9c5afba95ac1d338faf962febf957b9b0c379
|
4
|
+
data.tar.gz: adf4cd38b3f060d0eb6bd192a7a8b26ccfb975c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5340b8e65c5ed04ad39da45754a61666d3585b11a190779efbe39377903a3f3b8ef495fb39d56414caae34a1a2bf93226fa2d0b40130f3c245eca050b50ea95
|
7
|
+
data.tar.gz: e943781a460d6302bf567e1b2c68d73ef8e151205c42350bafd909bef9e2156219a0e8d1321d91ce5e248a6e86de91aca3434ebd2a3be95f8ada00127406a122
|
data/README.md
CHANGED
@@ -7,87 +7,126 @@
|
|
7
7
|
|
8
8
|
**Peddler** is a Ruby interface to the [Amazon MWS API](https://developer.amazonservices.com/), a collection of web services that help Amazon sellers programmatically exchange data on their listings, orders, payments, reports, and more.
|
9
9
|
|
10
|
-
To use Amazon MWS, you must have an eligible seller account.
|
10
|
+
To use Amazon MWS, you must have an eligible seller account and register for MWS. This applies to developers as well.
|
11
|
+
|
12
|
+
Some MWS API sections may require additional authorisation from Amazon.
|
11
13
|
|
12
14
|
![Peddler](http://f.cl.ly/items/231z2m0r1Q2o2q1n0w1N/peddler.jpg)
|
13
15
|
|
14
|
-
##
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
Require the library.
|
15
19
|
|
16
20
|
```ruby
|
17
21
|
require 'peddler'
|
22
|
+
```
|
18
23
|
|
24
|
+
Create a client. Peddler provides one for each MWS API under an eponymous namespace.
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
client = MWS::Orders::Client.new
|
28
|
+
|
29
|
+
# or the shorthand
|
19
30
|
client = MWS.orders
|
20
|
-
parser = client.get_service_status
|
21
|
-
parser.parse
|
22
31
|
```
|
23
32
|
|
24
|
-
|
25
|
-
|
26
|
-
You can set up credentials when instantiating:
|
33
|
+
Each client requires valid MWS credentials. You can set some or all when or after creating the client.
|
27
34
|
|
28
35
|
```ruby
|
29
|
-
client = MWS.
|
30
|
-
marketplace_id: "
|
31
|
-
merchant_id: "
|
32
|
-
aws_access_key_id: "
|
33
|
-
aws_secret_access_key: "
|
36
|
+
client = MWS::Orders::Client.new(
|
37
|
+
marketplace_id: "foo",
|
38
|
+
merchant_id: "bar",
|
39
|
+
aws_access_key_id: "baz",
|
40
|
+
aws_secret_access_key: "qux"
|
34
41
|
)
|
42
|
+
|
43
|
+
# Swap marketplace
|
44
|
+
client.marketplace_id = "quux"
|
35
45
|
```
|
36
46
|
|
37
|
-
Alternatively,
|
47
|
+
Alternatively, you can set these globally in the shell.
|
38
48
|
|
39
49
|
```sh
|
40
|
-
export MWS_MARKETPLACE_ID
|
41
|
-
export MWS_MERCHANT_ID
|
42
|
-
export AWS_ACCESS_KEY_ID
|
43
|
-
export AWS_SECRET_ACCESS_KEY
|
50
|
+
export MWS_MARKETPLACE_ID=foo
|
51
|
+
export MWS_MERCHANT_ID=bar
|
52
|
+
export AWS_ACCESS_KEY_ID=baz
|
53
|
+
export AWS_SECRET_ACCESS_KEY=qux
|
44
54
|
```
|
45
55
|
|
46
|
-
|
56
|
+
If you are creating a client for another seller, pass the latter's `MWSAuthToken` to the client.
|
47
57
|
|
48
|
-
|
58
|
+
```ruby
|
59
|
+
client.auth_token = "corge"
|
60
|
+
```
|
61
|
+
|
62
|
+
Once you have a client with credentials, you can make requests to the API.
|
63
|
+
|
64
|
+
Peddler returns the response wrapped in a simple parser that handles both XML documents and flat files.
|
49
65
|
|
50
66
|
```ruby
|
51
|
-
|
52
|
-
|
53
|
-
merchant_id: "...",
|
54
|
-
aws_access_key_id: "...",
|
55
|
-
aws_secret_access_key: "...",
|
56
|
-
auth_token: "..."
|
57
|
-
)
|
67
|
+
parser = client.get_service_status
|
68
|
+
parser.parse # will return Hash or a CSV object
|
58
69
|
```
|
59
70
|
|
60
|
-
|
71
|
+
You can swap the default parser with a purpose-built one.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
MWS::Orders::Client.parser = MyParser
|
75
|
+
```
|
76
|
+
|
77
|
+
For a sample implementation, see my [MWS Orders](https://github.com/hakanensari/mws-orders) library.
|
78
|
+
|
79
|
+
Finally, you can handle network errors caused by throttling or other transient issues by defining an error handler.
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
MWS::Orders::Client.on_error do |request, response|
|
83
|
+
if response.status == 503
|
84
|
+
logger.info "I was throttled"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
Alternatively, you can simply rescue.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
begin
|
93
|
+
client.some_method
|
94
|
+
rescue Excon::Errors::ServiceUnavailable
|
95
|
+
sleep 1 and retry
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
## The APIs
|
61
100
|
|
62
101
|
### Cart Information
|
63
102
|
|
64
103
|
With the MWS Cart Information API, you can retrieve shopping carts that your Amazon Webstore customers have created. The Cart Information API enables you to programmatically integrate Amazon Webstore cart information with your CRM systems, marketing applications, and other systems that require cart data.
|
65
104
|
|
66
|
-
[Read
|
105
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/CartInformation/Client)
|
67
106
|
|
68
107
|
### Customer Information
|
69
108
|
|
70
109
|
With the MWS Customer Information API, you can retrieve information from the customer accounts of your Amazon Webstore customers. This customer information includes customer name, contact information, customer account type, and associated Amazon Webstore marketplaces. The Customer Information API enables you to programmatically integrate Amazon Webstore customer account information with your CRM systems, marketing applications, and other systems that require customer data.
|
71
110
|
|
72
|
-
[Read
|
111
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/CustomerInformation/Client)
|
73
112
|
|
74
113
|
### Feeds
|
75
114
|
|
76
115
|
The MWS Feeds API lets you upload inventory and order data to Amazon. You can also use this API to get information about the processing of feeds.
|
77
116
|
|
78
|
-
[Read
|
117
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/Feeds/Client)
|
79
118
|
|
80
119
|
### Fulfillment Inbound Shipment
|
81
120
|
|
82
121
|
With the MWS Fulfillment Inbound Shipment API, you can create and update inbound shipments of inventory in the Amazon Fulfillment Network. You can also also request lists of inbound shipments or inbound shipment items based on criteria that you specify.
|
83
122
|
|
84
|
-
[Read
|
123
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/FulfillmentInboundShipment/Client)
|
85
124
|
|
86
125
|
### Fulfillment Inventory
|
87
126
|
|
88
127
|
The MWS Fulfillment Inventory API can help you stay up-to-date on the availability of your inventory in the Amazon Fulfillment Network. The Fulfillment Inventory API reports real-time availability information for your Amazon Fulfillment Network inventory regardless of whether you are selling your inventory on Amazon's retail web site or through other retail channels.
|
89
128
|
|
90
|
-
[Read
|
129
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/FulfillmentInventory/Client)
|
91
130
|
|
92
131
|
### Fulfillment Outbound Shipment
|
93
132
|
|
@@ -95,7 +134,7 @@ The MWS Fulfillment Outbound Shipment API enables you to fulfill orders placed t
|
|
95
134
|
|
96
135
|
Support for creating and cancelling fulfillment orders has been implemented, but the rest of the API is not supported yet.
|
97
136
|
|
98
|
-
[Read
|
137
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/FulfillmentOutboundShipment/Client)
|
99
138
|
|
100
139
|
### Off Amazon Payments
|
101
140
|
|
@@ -107,46 +146,46 @@ You can switch the client to the sandbox environment:
|
|
107
146
|
client = MWS.off_amazon_payments.sandbox
|
108
147
|
```
|
109
148
|
|
110
|
-
[Read
|
149
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/OffAmazonPayments/Client)
|
111
150
|
|
112
151
|
### Orders
|
113
152
|
|
114
153
|
With the MWS Orders API, you can list orders created or updated during a time frame you specify or retrieve information about specific orders.
|
115
154
|
|
116
|
-
[Read
|
155
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/Orders/Client)
|
117
156
|
|
118
157
|
### Products
|
119
158
|
|
120
159
|
The MWS Products API helps you get information to match your products to existing product listings on Amazon Marketplace websites and to make sourcing and pricing decisions for listing those products on Amazon Marketplace websites.
|
121
160
|
|
122
|
-
[Read
|
161
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/Products/Client)
|
123
162
|
|
124
163
|
### Recommendations
|
125
164
|
|
126
165
|
The Recommendations API enables you to programmatically retrieve Amazon Selling Coach recommendations by recommendation category. A recommendation is an actionable, timely, and personalized opportunity to increase your sales and performance.
|
127
166
|
|
128
|
-
[Read
|
167
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/Recommendations/Client)
|
129
168
|
|
130
169
|
### Reports
|
131
170
|
|
132
171
|
The Reports API lets you request reports about your inventory and orders.
|
133
172
|
|
134
|
-
[Read
|
173
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/Reports/Client)
|
135
174
|
|
136
175
|
### Sellers
|
137
176
|
|
138
177
|
The Sellers API lets sellers retrieve information about their seller account, such as the marketplaces they participate in.
|
139
178
|
|
140
|
-
[Read
|
179
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/Sellers/Client)
|
141
180
|
|
142
181
|
### Subscriptions
|
143
182
|
|
144
183
|
The Amazon MWS Subscriptions API section enables you to subscribe to receive notifications that are relevant to your business with Amazon. With the operations in the Subscriptions API section, you can register to receive important information from Amazon without having to poll the Amazon MWS service. Instead, the information is sent directly to you when an event occurs to which you are subscribed.
|
145
184
|
|
146
|
-
[Read
|
185
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/Subscriptions/Client)
|
147
186
|
|
148
187
|
### Webstore
|
149
188
|
|
150
189
|
With the Webstore API section of Amazon Marketplace Web Service (Amazon MWS), you can get “Email Me When Available” subscription information for items listed on your Amazon Webstore. The Webstore API section can help you plan your inventory replenishment cycle by enabling you to query for items that your customers subscribed to when they clicked the Email Me When Available button on your Webstore. The Webstore API section can also return information about the notifications that were sent to your customers when out-of-stock items came back in stock. This information, when combined with sales information that your Webstore tracks, can help you determine how many notifications were converted into sales.
|
151
190
|
|
152
|
-
[Read
|
191
|
+
[Read more](http://www.rubydoc.info/gems/peddler/MWS/Webstore/Client)
|
data/lib/peddler/client.rb
CHANGED
@@ -23,20 +23,31 @@ module Peddler
|
|
23
23
|
'MWSAuthToken' => -> { auth_token }
|
24
24
|
)
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
end
|
26
|
+
class << self
|
27
|
+
attr_reader :error_handler
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
def parser
|
30
|
+
@parser ||= Parser
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
def parser=(parser)
|
34
|
+
@parser = parser
|
35
|
+
end
|
36
|
+
|
37
|
+
def path(path = nil)
|
38
|
+
path ? @path = path : @path ||= '/'
|
39
|
+
end
|
37
40
|
|
38
|
-
|
39
|
-
|
41
|
+
def on_error(&blk)
|
42
|
+
@error_handler = blk
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def inherited(base)
|
48
|
+
base.params(params)
|
49
|
+
base.on_error &@error_handler if @error_handler
|
50
|
+
end
|
40
51
|
end
|
41
52
|
|
42
53
|
def initialize(opts = {})
|
@@ -80,6 +91,10 @@ module Peddler
|
|
80
91
|
@error_handler = blk
|
81
92
|
end
|
82
93
|
|
94
|
+
def error_handler
|
95
|
+
@error_handler || self.class.error_handler
|
96
|
+
end
|
97
|
+
|
83
98
|
def operation(action = nil)
|
84
99
|
action ? @operation = Operation.new(action) : @operation
|
85
100
|
end
|
@@ -90,9 +105,16 @@ module Peddler
|
|
90
105
|
opts.store(:response_block, Proc.new) if block_given?
|
91
106
|
res = post(opts)
|
92
107
|
|
93
|
-
parser.
|
94
|
-
rescue Excon::Errors::Error =>
|
95
|
-
handle_error(
|
108
|
+
parser.new(res, encoding)
|
109
|
+
rescue Excon::Errors::Error => e
|
110
|
+
handle_error(e) or raise
|
111
|
+
rescue NoMethodError => e
|
112
|
+
if e.message == "undefined method `new' for #{parser}"
|
113
|
+
warn "[DEPRECATION] `Parser.parse` is deprecated. Please use `Parser.new` instead."
|
114
|
+
parser.parse(res, encoding)
|
115
|
+
else
|
116
|
+
raise
|
117
|
+
end
|
96
118
|
end
|
97
119
|
|
98
120
|
private
|
@@ -117,9 +139,9 @@ module Peddler
|
|
117
139
|
self.class.parser
|
118
140
|
end
|
119
141
|
|
120
|
-
def handle_error(
|
121
|
-
return false unless
|
122
|
-
|
142
|
+
def handle_error(e)
|
143
|
+
return false unless error_handler
|
144
|
+
error_handler.call(e.request, e.response)
|
123
145
|
end
|
124
146
|
end
|
125
147
|
end
|
data/lib/peddler/marketplace.rb
CHANGED
@@ -19,7 +19,7 @@ module Peddler
|
|
19
19
|
attr_reader :id
|
20
20
|
|
21
21
|
def initialize(id)
|
22
|
-
@id = id
|
22
|
+
@id = id or fail BadId, 'missing MarketplaceId'
|
23
23
|
end
|
24
24
|
|
25
25
|
def host
|
@@ -41,7 +41,7 @@ module Peddler
|
|
41
41
|
private
|
42
42
|
|
43
43
|
def find_host
|
44
|
-
HOSTS.fetch(id) {
|
44
|
+
HOSTS.fetch(id) { fail BadId, %Q("#{id}" is not a valid MarketplaceId) }
|
45
45
|
end
|
46
46
|
|
47
47
|
def japanese?
|
data/lib/peddler/parser.rb
CHANGED
@@ -7,7 +7,7 @@ module Peddler
|
|
7
7
|
class << self
|
8
8
|
# The inevitable messiness of massaging data produced by a motley army of
|
9
9
|
# Amazon developers
|
10
|
-
def
|
10
|
+
def new(res, encoding = 'ISO-8859-1')
|
11
11
|
# Don't parse if there's no body
|
12
12
|
return res unless res.body
|
13
13
|
|
data/lib/peddler/version.rb
CHANGED
@@ -53,9 +53,11 @@ class TestMWSFulfillmentInboundShipmentClient < MiniTest::Test
|
|
53
53
|
def test_puts_transport_content
|
54
54
|
transport_details = {
|
55
55
|
'ParcelData' => {
|
56
|
-
'PackageList' =>
|
56
|
+
'PackageList' => [
|
57
|
+
{
|
57
58
|
'TrackingId' => '123'
|
58
|
-
|
59
|
+
}
|
60
|
+
]
|
59
61
|
}
|
60
62
|
}
|
61
63
|
|
@@ -64,7 +66,7 @@ class TestMWSFulfillmentInboundShipmentClient < MiniTest::Test
|
|
64
66
|
'ShipmentId' => '1',
|
65
67
|
'IsPartnered' => true,
|
66
68
|
'ShipmentType' => 'Foo',
|
67
|
-
'TransportDetails.ParcelData.PackageList.TrackingId' => '123'
|
69
|
+
'TransportDetails.ParcelData.PackageList.member.1.TrackingId' => '123'
|
68
70
|
}
|
69
71
|
|
70
72
|
@client.stub(:run, nil) do
|
@@ -4,7 +4,7 @@ require 'peddler/client'
|
|
4
4
|
|
5
5
|
class TestPeddlerClient < MiniTest::Test
|
6
6
|
module Parser
|
7
|
-
def self.
|
7
|
+
def self.new(res, *); res; end
|
8
8
|
end
|
9
9
|
|
10
10
|
def setup
|
@@ -134,7 +134,24 @@ class TestPeddlerClient < MiniTest::Test
|
|
134
134
|
assert headers.has_key?('User-Agent')
|
135
135
|
end
|
136
136
|
|
137
|
-
def
|
137
|
+
def test_error_callback_on_class
|
138
|
+
Excon.stub({}, { status: 503 })
|
139
|
+
|
140
|
+
assert_raises(Excon::Errors::ServiceUnavailable) do
|
141
|
+
@client.run
|
142
|
+
end
|
143
|
+
|
144
|
+
@klass.on_error do |_, res|
|
145
|
+
assert_equal 503, res.status
|
146
|
+
end
|
147
|
+
|
148
|
+
@client.run
|
149
|
+
|
150
|
+
Excon.stubs.clear
|
151
|
+
@klass.instance_variable_set(:@error_handler, nil)
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_error_callback_on_instance
|
138
155
|
Excon.stub({}, { status: 503 })
|
139
156
|
|
140
157
|
assert_raises(Excon::Errors::ServiceUnavailable) do
|
@@ -149,4 +166,40 @@ class TestPeddlerClient < MiniTest::Test
|
|
149
166
|
|
150
167
|
Excon.stubs.clear
|
151
168
|
end
|
169
|
+
|
170
|
+
def test_error_callback_on_client_ancestor
|
171
|
+
Excon.stub({}, { status: 503 })
|
172
|
+
|
173
|
+
assert_raises(Excon::Errors::ServiceUnavailable) do
|
174
|
+
@client.run
|
175
|
+
end
|
176
|
+
|
177
|
+
Peddler::Client.on_error do |_, res|
|
178
|
+
assert_equal 503, res.status
|
179
|
+
end
|
180
|
+
|
181
|
+
klass = Class.new(Peddler::Client)
|
182
|
+
klass.parser = Parser
|
183
|
+
client = klass.new
|
184
|
+
client.aws_access_key_id = 'key'
|
185
|
+
client.aws_secret_access_key = 'secret'
|
186
|
+
client.merchant_id = 'seller'
|
187
|
+
client.marketplace_id = 'ATVPDKIKX0DER' # US
|
188
|
+
client.operation('Foo')
|
189
|
+
client.run
|
190
|
+
|
191
|
+
Excon.stubs.clear
|
192
|
+
Peddler::Client.instance_variable_set(:@error_handler, nil)
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_deprecates_call_to_parser_parse
|
196
|
+
deprecated_parser = Module.new do
|
197
|
+
def self.parse(res, *); res; end
|
198
|
+
end
|
199
|
+
@client.stub :warn, nil do
|
200
|
+
@klass.parser = deprecated_parser
|
201
|
+
res = @client.run
|
202
|
+
assert_equal @body, res.body
|
203
|
+
end
|
204
|
+
end
|
152
205
|
end
|
@@ -14,8 +14,14 @@ class TestPeddlerMarketplace < MiniTest::Test
|
|
14
14
|
assert @marketplace.encoding
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
assert_raises(Peddler::Marketplace::BadId) do
|
17
|
+
def test_guard_against_missing_marketplace_id
|
18
|
+
assert_raises(Peddler::Marketplace::BadId, 'missing MarketplaceId') do
|
19
|
+
marketplace = Peddler::Marketplace.new(nil)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_guard_against_bad_marketplace_id
|
24
|
+
assert_raises(Peddler::Marketplace::BadId, '"123" is not a valid MarketplaceId') do
|
19
25
|
marketplace = Peddler::Marketplace.new('123')
|
20
26
|
marketplace.host
|
21
27
|
end
|
@@ -5,7 +5,7 @@ class TestPeddlerParser < MiniTest::Test
|
|
5
5
|
def assert_parser(klass, *content_types)
|
6
6
|
content_types.each do |content_type|
|
7
7
|
res = OpenStruct.new(headers: { 'Content-Type' => content_type }, body: '')
|
8
|
-
parser = Peddler::Parser.
|
8
|
+
parser = Peddler::Parser.new(res)
|
9
9
|
|
10
10
|
assert_kind_of klass, parser
|
11
11
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: peddler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hakan Ensari
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jeff
|
@@ -79,15 +79,12 @@ files:
|
|
79
79
|
- lib/peddler.rb
|
80
80
|
- lib/peddler/client.rb
|
81
81
|
- lib/peddler/flat_file_parser.rb
|
82
|
-
- lib/peddler/flat_file_response.rb
|
83
82
|
- lib/peddler/marketplace.rb
|
84
83
|
- lib/peddler/operation.rb
|
85
84
|
- lib/peddler/parser.rb
|
86
|
-
- lib/peddler/response.rb
|
87
85
|
- lib/peddler/structured_list.rb
|
88
86
|
- lib/peddler/version.rb
|
89
87
|
- lib/peddler/xml_parser.rb
|
90
|
-
- lib/peddler/xml_response.rb
|
91
88
|
- test/helper.rb
|
92
89
|
- test/integration/test_cart_information.rb
|
93
90
|
- test/integration/test_customer_information.rb
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'delegate'
|
2
|
-
require 'csv'
|
3
|
-
require 'digest/md5'
|
4
|
-
|
5
|
-
module Peddler
|
6
|
-
# @api private
|
7
|
-
class FlatFileResponse < SimpleDelegator
|
8
|
-
# http://stackoverflow.com/questions/8073920/importing-csv-quoting-error-is-driving-me-nuts
|
9
|
-
OPTIONS = { col_sep: "\t", quote_char: "\x00", headers: true }
|
10
|
-
|
11
|
-
attr_reader :content, :summary, :encoding
|
12
|
-
|
13
|
-
def initialize(res, encoding)
|
14
|
-
super(res)
|
15
|
-
@encoding = encoding
|
16
|
-
extract_content
|
17
|
-
end
|
18
|
-
|
19
|
-
def parse
|
20
|
-
CSV.parse(scrub_content, OPTIONS) if content
|
21
|
-
end
|
22
|
-
|
23
|
-
def records_count
|
24
|
-
summarize if summary?
|
25
|
-
end
|
26
|
-
|
27
|
-
def valid?
|
28
|
-
headers['Content-MD5'] == Digest::MD5.base64digest(body)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def extract_content
|
34
|
-
if summary?
|
35
|
-
@summary, @content = body.split("\n\n")
|
36
|
-
else
|
37
|
-
@content = body.dup
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def scrub_content
|
42
|
-
content.force_encoding(encoding).encode('UTF-8')
|
43
|
-
end
|
44
|
-
|
45
|
-
def summary?
|
46
|
-
body.start_with?('Feed Processing Summary')
|
47
|
-
end
|
48
|
-
|
49
|
-
def summarize
|
50
|
-
Hash[summary.split("\n\t")[1, 2].map { |line| line.split("\t\t") }]
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
data/lib/peddler/response.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'peddler/flat_file_response'
|
2
|
-
require 'peddler/xml_response'
|
3
|
-
|
4
|
-
module Peddler
|
5
|
-
# @api private
|
6
|
-
module Response
|
7
|
-
# The inevitable messiness of massaging data produced by a motley army of
|
8
|
-
# Amazon developers
|
9
|
-
def self.new(response, encoding = 'ISO-8859-1')
|
10
|
-
# Don't parse if there's no body
|
11
|
-
return response unless response.body
|
12
|
-
|
13
|
-
content_type = response.headers['Content-Type']
|
14
|
-
if content_type.start_with?('text/xml')
|
15
|
-
XMLResponse.new(response)
|
16
|
-
else
|
17
|
-
# Amazon returns a variety of content types for flat files, so we
|
18
|
-
# simply assume that anything not XML is a flat file rather than code
|
19
|
-
# defensively and check content type again.
|
20
|
-
FlatFileResponse.new(response, encoding)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/peddler/xml_response.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'delegate'
|
2
|
-
require 'multi_xml'
|
3
|
-
|
4
|
-
module Peddler
|
5
|
-
# @api private
|
6
|
-
class XMLResponse < SimpleDelegator
|
7
|
-
def next_token
|
8
|
-
parse.fetch('NextToken', false)
|
9
|
-
end
|
10
|
-
|
11
|
-
def parse
|
12
|
-
@result ||= find_result
|
13
|
-
end
|
14
|
-
|
15
|
-
def document
|
16
|
-
MultiXml.parse(body)
|
17
|
-
end
|
18
|
-
|
19
|
-
def valid?
|
20
|
-
headers['Content-Length'].to_i == body.size if headers['Content-Length']
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def find_result
|
26
|
-
results = document.values[0].find { |k, _| k.include?('Result') }
|
27
|
-
results ? results.last : nil
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|