paapi 0.0.3 → 0.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4bac67043fb32a957f0b015eb468efbcc852b9e5285940ff152bdc012b4c751
4
- data.tar.gz: e4f35c14a82bf615d95167b869cb7b73c69cc85e7f05bd0ef1c37a96556b5b78
3
+ metadata.gz: c51a902c63c17b386688df97e49c8b201fb3309de82ace4b9e9b5d9f420923ff
4
+ data.tar.gz: c312da6d5bfb22c21b43f5449e616c48fcf661dfd08e9e4b2e106512c6c5575d
5
5
  SHA512:
6
- metadata.gz: 5943daef94869da7e96ca4d1b1b35fdd98f58f90bcebd7a00c24e1b11baf32cc5488986104b2d8edc95637076630437aaa2a5467683a8ca219e8a2a31b99aed4
7
- data.tar.gz: 7dd1fd49d4c63a6e6ff67d2881137f0c7bd5c0fe6e166a917929b3f08d69f1a31dbbf63d3d5720f75fce53f3ff67fe0b5b3d097858eff99c362e0731fed68aec
6
+ metadata.gz: f76777564d20118875ecb809a5c32c88a7d58245b3012947a4a55ac150e182e88cf34179de9e60999dd03b404cd9dea136346e12aec7199161ab122bf62f6f00
7
+ data.tar.gz: b2c64410108d2d2e4ce5e8bed0a1da8eee6d4fff83fd3c176b737e771d030cb5972c6e9cf84a3b26de2673f6b15116a622b7d3423b1bde252fbfd66c97e1dcdc
data/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  `paapi` is a slim wrapper around [Amazon's Product Advertising API 5.0](https://webservices.amazon.com/paapi5/documentation/).
4
4
 
5
- This gem is under development and currently incomplete.
5
+ This gem is under heavy development and currently incomplete.
6
+
7
+ [![Build Status](https://travis-ci.org/dkam/paapi.svg?branch=master)](https://travis-ci.org/dkam/paapi)
6
8
 
7
9
  ## Installation
8
10
 
@@ -24,7 +26,7 @@ Or install it yourself as:
24
26
 
25
27
  ### Configuration
26
28
 
27
- The library can be initialised with a Rails initializer such as
29
+ The library can be configured with an initializer. For Rails, create the file `config/initializers/paapi.rb`
28
30
 
29
31
  ```ruby
30
32
  Paapi.configure do |config|
@@ -83,6 +85,8 @@ gv = client.get_variations(asin: 'B00422MCUS')
83
85
 
84
86
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
85
87
 
88
+ If you create a file `config.rb`, it will be loaded by `bin/console`, allowing you to configure keys and markets.
89
+
86
90
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
87
91
 
88
92
  ## Contributing
data/bin/console CHANGED
@@ -11,4 +11,5 @@ require 'paapi'
11
11
  # Pry.start
12
12
 
13
13
  require 'irb'
14
+ load 'config.rb' if File.exist? 'config.rb'
14
15
  IRB.start(__FILE__)
data/lib/paapi/client.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require 'http'
2
+ require 'aws-sigv4'
2
3
 
3
4
  module Paapi
4
5
  class Client
5
- include AwsRequest
6
+
6
7
  attr_accessor :partner_tag, :marketplace, :resources
7
8
  attr_reader :partner_type, :access_key, :secret_key, :market
8
9
 
@@ -14,13 +15,14 @@ module Paapi
14
15
  partner_type: DEFAULT_PARTNER_TYPE
15
16
  )
16
17
  raise ArgumentError unless MARKETPLACES.keys.include?(market.to_sym)
18
+
17
19
  @access_key = access_key
18
20
  @secret_key = secret_key
19
21
  @partner_type = partner_type
20
22
  @resources = resources unless resources.nil?
21
23
 
22
24
  self.market = market
23
- @partner_tag = partner_tag if !partner_tag.nil?
25
+ @partner_tag = partner_tag if !partner_tag.nil?
24
26
  end
25
27
 
26
28
  def market=(a_market)
@@ -33,23 +35,14 @@ module Paapi
33
35
 
34
36
  def get_items(item_ids:, **options)
35
37
  payload = { ItemIds: Array(item_ids), Resources: @resources }
36
-
37
- res = do_request(op: :get_items, payload: payload)
38
-
39
- # Errors, ItemResults -> Items -> Item
40
- return Response.new(res)
38
+ request(op: :get_items, payload: payload)
41
39
  end
42
40
 
43
41
  def get_variations(asin:, **options )
44
42
  payload = { ASIN: asin, Resources: @resources }
45
-
46
- res = do_request(op: :get_variations, payload: payload)
47
-
48
- # Errors, VariationsResult->Items
49
- Response.new(res)
43
+ request(op: :get_variations, payload: payload)
50
44
  end
51
45
 
52
-
53
46
  # TODO: Currently we assume Keywords, but we need one of the follow: [Keywords Actor Artist Author Brand Title ]
54
47
  def search_items(keywords: nil, **options )
55
48
  raise ArgumentError("Missing keywords") unless (options.keys | SEARCH_PARAMS).length.positive?
@@ -58,18 +51,56 @@ module Paapi
58
51
 
59
52
  payload = { Keywords: keywords, Resources: @resources, ItemCount: 10, ItemPage: 1, SearchIndex: search_index }.merge(options)
60
53
 
61
- res = do_request(op: :search_items, payload: payload)
62
-
63
- Response.new(res)
54
+ request(op: :search_items, payload: payload)
64
55
  end
65
56
 
66
57
  def get_browse_nodes(browse_node_ids:, **options)
67
- resources = ['BrowseNodes.Ancestor', 'BrowseNodes.Children']
68
58
  payload = { BrowseNodeIds: Array(browse_node_ids), Resources: @resources }.merge(options)
69
-
70
- res = do_request(op: :get_browse_nodes, payload: payload)
71
-
72
- Response.new(res)
59
+ request(op: :get_browse_nodes, payload: payload)
60
+ end
61
+
62
+ private
63
+
64
+ def request(op:, payload:)
65
+ raise ArguemntError unless Paapi::OPERATIONS.keys.include?(op)
66
+
67
+ operation = OPERATIONS[op]
68
+
69
+ headers = {
70
+ 'X-Amz-Target' => "com.amazon.paapi5.v1.ProductAdvertisingAPIv1.#{operation.target_name}",
71
+ 'Content-Encoding' => 'amz-1.0',
72
+ }
73
+
74
+ default_payload = {
75
+ 'PartnerTag' => partner_tag,
76
+ 'PartnerType' => partner_type,
77
+ 'Marketplace' => marketplace.site
78
+ }
79
+
80
+ payload = default_payload.merge(payload)
81
+
82
+ endpoint = "https://#{marketplace.host}/paapi5/#{operation.endpoint_suffix}"
83
+
84
+ signer = Aws::Sigv4::Signer.new(
85
+ service: operation.service,
86
+ region: marketplace.region,
87
+ access_key_id: access_key,
88
+ secret_access_key: secret_key,
89
+ http_method: operation.http_method,
90
+ endpoint: marketplace.host
91
+ )
92
+
93
+ signature = signer.sign_request(http_method: operation.http_method, url: endpoint, headers: headers, body: payload.to_json)
94
+
95
+ headers['Host'] = marketplace.host
96
+ headers['X-Amz-Date'] = signature.headers['x-amz-date']
97
+ headers['X-Amz-Content-Sha256']= signature.headers['x-amz-content-sha256']
98
+ headers['Authorization'] = signature.headers['authorization']
99
+ headers['Content-Type'] = 'application/json; charset=utf-8'
100
+
101
+ Response.new( HTTP.headers(headers).post(endpoint, json: payload ) )
73
102
  end
74
103
  end
104
+
105
+
75
106
  end
data/lib/paapi/item.rb CHANGED
@@ -2,9 +2,13 @@ require 'nameable'
2
2
 
3
3
  module Paapi
4
4
  class Item
5
- attr_accessor :raw
5
+ attr_accessor :hash
6
6
  def initialize(data)
7
- @raw = data
7
+ @hash = data
8
+ end
9
+
10
+ def listings
11
+ get(['Offers', 'Listings']).map {|d| Listing.new(d)}
8
12
  end
9
13
 
10
14
  def asin
@@ -22,20 +26,20 @@ module Paapi
22
26
  def title
23
27
  get(%w{ItemInfo Title DisplayValue})
24
28
  end
25
-
29
+
26
30
  def manufacturer
27
31
  get(%w{ItemInfo ByLineInfo Manufacturer DisplayValue})
28
32
  end
29
-
33
+
30
34
  def publisher
31
35
  manufacturer
32
36
  end
33
-
37
+
34
38
  def publication_date
35
39
  d = get(%w{ItemInfo ContentInfo PublicationDate DisplayValue})
36
40
  return d.nil? ? nil : Date.parse(d)
37
41
  end
38
-
42
+
39
43
  def release_date
40
44
  d = get(%w{ItemInfo ProductInfo ReleaseDate DisplayValue})
41
45
  return d.nil? ? nil : Date.parse(d)
@@ -44,33 +48,33 @@ module Paapi
44
48
  def contributors
45
49
  get(%w{ItemInfo ByLineInfo Contributors})
46
50
  end
47
-
51
+
48
52
  def contributors_of(kind)
49
- contributors&.select { |e| e['Role'] == kind }&.map { |e| Nameable(e['Name'])}
53
+ contributors&.select { |e| e['Role'] == kind.to_s.gsub(/([[:alpha:]]+)/) { |w| w.capitalize } }&.map { |e| Nameable(e['Name'])}
50
54
  end
51
-
55
+
56
+ def actors
57
+ contributors_of 'Actor'
58
+ end
59
+
60
+ def artists
61
+ contributors_of 'Artist'
62
+ end
63
+
52
64
  def authors
53
65
  contributors_of 'Author'
54
66
  end
55
-
67
+
56
68
  def illustrators
57
69
  contributors_of 'Illustrator'
58
70
  end
59
-
60
- def actors
61
- contributors_of 'Actor'
62
- end
63
71
 
64
72
  def narrators
65
73
  contributors_of 'Narrator'
66
74
  end
67
-
68
- def publishers
69
- contributors_of 'Publisher'
70
- end
71
75
 
72
- def release_date
73
- get(%w{ItemInfo ReleaseDate})
76
+ def publishers
77
+ contributors_of 'Publisher'
74
78
  end
75
79
 
76
80
  def eans
@@ -84,7 +88,7 @@ module Paapi
84
88
  def features
85
89
  get(%w{ItemInfo Features DisplayValues})&.join(' ')
86
90
  end
87
-
91
+
88
92
  def brand
89
93
  get(%w{ItemInfo ByLineInfo Brand DisplayValue})
90
94
  end
@@ -93,6 +97,10 @@ module Paapi
93
97
  get(%w{ItemInfo ManufactureInfo ItemPartNumber DisplayValue})
94
98
  end
95
99
 
100
+ def model
101
+ get(%w{ItemInfo ManufactureInfo Model})
102
+ end
103
+
96
104
  def package
97
105
  get(%w{ItemInfo TechnicalInfo Formats DisplayValues})
98
106
  end
@@ -102,12 +110,12 @@ module Paapi
102
110
  end
103
111
 
104
112
  def get(keys)
105
- @raw.dig(*keys)
113
+ @hash.dig(*keys)
106
114
  end
107
-
115
+
108
116
  def self.to_items(data)
109
117
  data.map {|d| Item.new(d)}
110
118
  end
111
-
119
+
112
120
  end
113
121
  end
@@ -2,41 +2,25 @@ require 'json'
2
2
 
3
3
  module Paapi
4
4
  class Response
5
- attr_reader :http_response, :data, :datas, :doc, :items
5
+ attr_reader :http_response, :json, :datas, :doc, :items
6
6
 
7
7
  def initialize(response)
8
8
  @http_response = response
9
- @data = JSON.parse(response.body.to_s)
10
-
11
- @datas = symbolise(JSON.parse(response.body.to_s))
12
- @doc = JSON.parse(@datas.to_json, object_class: OpenStruct)
9
+ @json = JSON.parse(response.body.to_s)
13
10
 
14
- @items_data = @data.dig('ItemsResult', 'Items')
15
- @items_data ||= @data.dig('SearchResult', 'Items')
11
+ @items_data = @json.dig('ItemsResult', 'Items')
12
+ @items_data ||= @json.dig('SearchResult', 'Items')
16
13
  @items_data ||= []
17
-
14
+
18
15
  @items = @items_data.map {|d| Item.new(d)}
19
16
 
20
17
  end
21
-
22
- def snake_case(s)
23
- return s.downcase if s.match(/\A[A-Z]+\z/)
24
- s.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
25
- gsub(/([a-z])([A-Z])/, '\1_\2').
26
- downcase
27
- end
28
-
29
- def symbolise(obj)
30
- if obj.is_a? Hash
31
- return obj.inject({}) do |memo, (k, v)|
32
- memo.tap { |m| m[snake_case(k)] = symbolise(v) }
33
- end
34
- elsif obj.is_a? Array
35
- return obj.map { |memo| symbolise(memo) }
36
- end
37
- obj
18
+
19
+ def result_count
20
+ @json.dig('SearchResult', 'TotalResultCount')
38
21
  end
39
22
 
40
-
23
+
24
+
41
25
  end
42
26
  end
data/lib/paapi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Paapi
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
data/lib/paapi.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'paapi/version'
2
2
 
3
- require 'paapi/aws_request'
4
3
  require 'paapi/client'
5
4
  require 'paapi/item'
6
5
  require 'paapi/response'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Milne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-19 00:00:00.000000000 Z
11
+ date: 2019-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -138,7 +138,6 @@ files:
138
138
  - bin/console
139
139
  - bin/setup
140
140
  - lib/paapi.rb
141
- - lib/paapi/aws_request.rb
142
141
  - lib/paapi/client.rb
143
142
  - lib/paapi/item.rb
144
143
  - lib/paapi/response.rb
@@ -1,47 +0,0 @@
1
- require 'http'
2
- require 'aws-sigv4'
3
-
4
- # https://webservices.amazon.com/paapi5/documentation/common-request-parameters.html
5
- module Paapi
6
- module AwsRequest
7
- def do_request(op:, payload:)
8
- raise ArguemntError unless Paapi::OPERATIONS.keys.include?(op)
9
-
10
- operation = OPERATIONS[op]
11
-
12
- headers = {
13
- 'X-Amz-Target' => "com.amazon.paapi5.v1.ProductAdvertisingAPIv1.#{operation.target_name}",
14
- 'Content-Encoding' => 'amz-1.0',
15
- }
16
-
17
- default_payload = {
18
- 'PartnerTag' => partner_tag,
19
- 'PartnerType' => partner_type,
20
- 'Marketplace' => marketplace.site
21
- }
22
-
23
- payload = default_payload.merge(payload)
24
-
25
- endpoint = "https://#{marketplace.host}/paapi5/#{operation.endpoint_suffix}"
26
-
27
- signer = Aws::Sigv4::Signer.new(
28
- service: operation.service,
29
- region: marketplace.region,
30
- access_key_id: access_key,
31
- secret_access_key: secret_key,
32
- http_method: operation.http_method,
33
- endpoint: marketplace.host
34
- )
35
-
36
- signature = signer.sign_request(http_method: operation.http_method, url: endpoint, headers: headers, body: payload.to_json)
37
-
38
- headers['Host'] = marketplace.host
39
- headers['X-Amz-Date'] = signature.headers['x-amz-date']
40
- headers['X-Amz-Content-Sha256']= signature.headers['x-amz-content-sha256']
41
- headers['Authorization'] = signature.headers['authorization']
42
- headers['Content-Type'] = 'application/json; charset=utf-8'
43
-
44
- HTTP.headers(headers).post(endpoint, json: payload )
45
- end
46
- end
47
- end