paapi 0.1.8 → 0.1.11

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: 40f433f95c408becd287ae9cfa62596852bdf95f7819321c3c14bea9e9b45e52
4
- data.tar.gz: 21fab0c1b0502c992f72f4cc5844396d96757cb6fa807fd7ac0f6c80c2c97835
3
+ metadata.gz: 11e336d12ee1e47e2a5e0721d03e36b8a0ef93c85cafa1f614cac918afc9562b
4
+ data.tar.gz: 45b7564fcdf20b532538adeb6dfe1187ffc084ee1cb3788da4c61cf36bc81d05
5
5
  SHA512:
6
- metadata.gz: e43c529bfa5bf168d605af7f2b32bd5d6910acbb41047cddfeabe7c2566f3b43a9e99ea2ca3b8046d9f7ec1e06ae0e889c2a4dc4dfb840eee20c5cbf4c1dc43a
7
- data.tar.gz: 98f0ee7c98a77d301d82128c101e5108d57c20d3d096ebc8ea095f9c478289a0fcc676eb9646c4672238ba71d546d389aa07dd9279e03415bd0ada2fdae7c9b3
6
+ metadata.gz: 793a70fd48443cc4a459aa2ec81507e7430810a1eb49a2446741dfb02135780bb7868c38a2adf87f1f4e4c99783669c55370eb6495a03657e332cf1d20ce812d
7
+ data.tar.gz: ca199ef19cadde87923b8bc8708ab8887bf91c0b61e63faf522b8ecdc91eea4ef25215a296ba9fe00dc6ccd9221c9dc8d20551fb87eea4c9d5cb282996cbbdf7
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
- ## 0.1.7 ( Unreleased )
1
+ ## 0.1.9 (Unreleased)
2
+ - Fix bug allowing non-title case Request Parameters
3
+ - Add the required PartnerTag and PartnerType key values to the search body request
4
+
5
+ ## 0.1.7
2
6
  - Add gem 'net-http-persistent' for connection persistance
3
7
  - Remove the code which would use other http clients if available
4
8
  ## 0.1.3
data/lib/paapi/client.rb CHANGED
@@ -1,89 +1,94 @@
1
- require 'net/http/persistent'
2
- require 'aws-sigv4'
1
+ require "net/http/persistent"
2
+ require "aws-sigv4"
3
3
 
4
4
  module Paapi
5
5
  class Client
6
-
7
6
  attr_accessor :partner_tag, :marketplace, :resources, :condition
8
7
  attr_reader :partner_type, :access_key, :secret_key, :market, :http
9
8
 
10
- def initialize(access_key: Paapi.access_key,
11
- secret_key: Paapi.secret_key,
12
- partner_tag: Paapi.partner_tag,
13
- market: Paapi.market || DEFAULT_MARKET,
14
- condition: Paapi.condition || DEFAULT_CONDITION,
15
- resources: Paapi.resources || DEFAULT_RESOURCES,
16
- partner_type: DEFAULT_PARTNER_TYPE
17
- )
18
- raise ArgumentError unless MARKETPLACES.keys.include?(market.to_sym)
9
+ def initialize(
10
+ access_key: Paapi.access_key,
11
+ secret_key: Paapi.secret_key,
12
+ partner_tag: Paapi.partner_tag,
13
+ market: Paapi.market || DEFAULT_MARKET,
14
+ condition: Paapi.condition || DEFAULT_CONDITION,
15
+ resources: Paapi.resources || DEFAULT_RESOURCES,
16
+ partner_type: DEFAULT_PARTNER_TYPE
17
+ )
18
+ raise ArgumentError unless MARKETPLACES.key?(market.to_sym)
19
19
 
20
20
  @access_key = access_key
21
21
  @secret_key = secret_key
22
22
  @partner_type = partner_type
23
23
  @resources = resources unless resources.nil?
24
- @condition = condition
24
+ @condition = condition
25
25
  self.market = market
26
26
  @partner_tag = partner_tag if !partner_tag.nil?
27
27
 
28
- @http = Net::HTTP::Persistent.new name: 'paapi'
28
+ @http = Net::HTTP::Persistent.new(name: "paapi").tap do |c|
29
+ c.open_timeout = 2
30
+ c.read_timeout = 5
31
+ c.write_timeout = 5
32
+ end
29
33
  end
30
34
 
31
35
  def market=(a_market)
32
36
  @market = a_market
33
37
  @marketplace = MARKETPLACES[market.to_sym]
34
- if !Paapi.partner_market.nil?
35
- @partner_tag = Paapi.partner_market.dig(a_market.to_sym) || @partner_tag
36
- end
38
+ return if Paapi.partner_market.nil?
39
+
40
+ @partner_tag = Paapi.partner_market[a_market.to_sym] || @partner_tag
37
41
  end
38
42
 
39
43
  def get_items(item_ids:, **options)
40
- payload = { ItemIds: Array(item_ids), Resources: @resources }.merge(options)
44
+ payload = {"PartnerTag" => partner_tag, "PartnerType" => "Associates", ItemIds: Array(item_ids), Resources: @resources}.merge(options)
41
45
  request(op: :get_items, payload: payload)
42
46
  end
43
47
 
44
- def get_variations(asin:, **options )
45
- payload = { ASIN: asin, Resources: @resources }.merge(options)
48
+ def get_variations(asin:, **options)
49
+ payload = {ASIN: asin, Resources: @resources}.merge(options)
46
50
  request(op: :get_variations, payload: payload)
47
51
  end
48
52
 
49
53
  # TODO: Currently we assume Keywords, but we need one of the following: [Keywords Actor Artist Author Brand Title ]
50
- def search_items(keywords: nil, **options )
51
- raise ArgumentError("Missing keywords") unless (options.keys | SEARCH_PARAMS).length.positive?
54
+ def search_items(**options)
55
+ options.transform_keys!(&:to_s)
56
+ raise ArgumentError.new("Missing keywords") unless (options.keys & SEARCH_PARAMS).length.positive?
52
57
 
53
- search_index = options.dig(:SearchIndex) ||'All'
58
+ search_index = options.dig(:SearchIndex) || "All"
54
59
 
55
- payload = { Keywords: keywords, Resources: @resources, ItemCount: 10, ItemPage: 1, SearchIndex: search_index }.merge(options)
60
+ payload = {"PartnerTag" => partner_tag, "PartnerType" => "Associates", "Resources" => @resources, "ItemCount" => 10, "ItemPage" => 1, "SearchIndex" => search_index}.merge(options)
56
61
 
57
62
  request(op: :search_items, payload: payload)
58
63
  end
59
64
 
60
65
  def get_browse_nodes(browse_node_ids:, **options)
61
- payload = { BrowseNodeIds: Array(browse_node_ids), Resources: @resources }.merge(options)
66
+ payload = {BrowseNodeIds: Array(browse_node_ids), Resources: @resources}.merge(options)
62
67
  request(op: :get_browse_nodes, payload: payload)
63
68
  end
64
-
69
+
65
70
  private
66
-
67
- def request(op:, payload:)
68
- raise ArguemntError unless Paapi::OPERATIONS.keys.include?(op)
69
-
71
+
72
+ def request(op:, payload:)
73
+ raise ArguemntError unless Paapi::OPERATIONS.key?(op)
74
+
70
75
  operation = OPERATIONS[op]
71
76
 
72
77
  headers = {
73
- 'X-Amz-Target' => "com.amazon.paapi5.v1.ProductAdvertisingAPIv1.#{operation.target_name}",
74
- 'Content-Encoding' => 'amz-1.0',
78
+ "X-Amz-Target" => "com.amazon.paapi5.v1.ProductAdvertisingAPIv1.#{operation.target_name}",
79
+ "Content-Encoding" => "amz-1.0"
75
80
  }
76
81
 
77
82
  default_payload = {
78
- 'Condition' => condition,
79
- 'PartnerTag' => partner_tag,
80
- 'PartnerType' => partner_type,
81
- 'Marketplace' => marketplace.site
83
+ "Condition" => condition,
84
+ "PartnerTag" => partner_tag,
85
+ "PartnerType" => partner_type,
86
+ "Marketplace" => marketplace.site
82
87
  }
83
88
 
84
89
  payload = default_payload.merge(payload)
85
-
86
- endpoint = "https://#{marketplace.host}/paapi5/#{operation.endpoint_suffix}"
90
+ puts payload
91
+ endpoint = "https://#{marketplace.host}/paapi5/#{operation.endpoint_suffix}"
87
92
 
88
93
  signer = Aws::Sigv4::Signer.new(
89
94
  service: operation.service,
@@ -96,21 +101,21 @@ module Paapi
96
101
 
97
102
  signature = signer.sign_request(http_method: operation.http_method, url: endpoint, headers: headers, body: payload.to_json)
98
103
 
99
- headers['Host'] = marketplace.host
100
- headers['X-Amz-Date'] = signature.headers['x-amz-date']
101
- headers['X-Amz-Content-Sha256']= signature.headers['x-amz-content-sha256']
102
- headers['Authorization'] = signature.headers['authorization']
103
- headers['Content-Type'] = 'application/json; charset=utf-8'
104
+ headers["Host"] = marketplace.host
105
+ headers["X-Amz-Date"] = signature.headers["x-amz-date"]
106
+ headers["X-Amz-Content-Sha256"] = signature.headers["x-amz-content-sha256"]
107
+ headers["Authorization"] = signature.headers["authorization"]
108
+ headers["Content-Type"] = "application/json; charset=utf-8"
104
109
 
105
- Response.new( post(url: endpoint, body: payload, headers: headers))
110
+ Response.new(post(url: endpoint, body: payload, headers: headers))
106
111
  end
107
112
 
108
113
  def post(url:, body:, headers:)
109
114
  uri = URI.parse(url)
110
115
 
111
116
  post_request = Net::HTTP::Post.new(uri.path)
112
- post_request.content_type = 'application/json; charset=UTF-8'
113
-
117
+ post_request.content_type = "application/json; charset=UTF-8"
118
+
114
119
  headers.each { |k, v| post_request[k] = v }
115
120
  post_request.body = body.to_json
116
121
 
data/lib/paapi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Paapi
2
- VERSION = '0.1.8'
2
+ VERSION = '0.1.11'
3
3
  end
data/lib/paapi.rb CHANGED
@@ -1,81 +1,82 @@
1
- require 'paapi/version'
1
+ require "paapi/version"
2
2
 
3
- require 'paapi/client'
4
- require 'paapi/item'
5
- require 'paapi/listing'
6
- require 'paapi/response'
3
+ require "paapi/client"
4
+ require "paapi/item"
5
+ require "paapi/listing"
6
+ require "paapi/response"
7
7
 
8
8
  module Paapi
9
9
  class Error < StandardError; end
10
+
10
11
  class NotImplemented < StandardError; end
11
- SEARCH_PARAMS = %i[keywords actor, artist, author, brand title].freeze
12
- DEFAULT_PARTNER_TYPE = 'Associates'
12
+ SEARCH_PARAMS = %w[Keywords Actor Artist Author Brand Title].freeze
13
+ DEFAULT_PARTNER_TYPE = "Associates"
13
14
  DEFAULT_MARKET = :us
14
- DEFAULT_CONDITION = 'Any'
15
+ DEFAULT_CONDITION = "Any"
15
16
  DEFAULT_RESOURCES = [
16
- 'Images.Primary.Large',
17
- 'ItemInfo.ByLineInfo',
18
- 'ItemInfo.ContentInfo',
19
- 'ItemInfo.ExternalIds',
20
- 'ItemInfo.Features',
21
- 'ItemInfo.ManufactureInfo',
22
- 'ItemInfo.ProductInfo',
23
- 'ItemInfo.TechnicalInfo', # Includes format when Kindle
24
- 'ItemInfo.Title',
25
- 'ItemInfo.TradeInInfo',
26
- 'Offers.Listings.Availability.Message',
27
- 'Offers.Listings.Condition',
28
- 'Offers.Listings.Condition.SubCondition',
29
- 'Offers.Listings.DeliveryInfo.IsAmazonFulfilled',
30
- 'Offers.Listings.DeliveryInfo.IsFreeShippingEligible',
31
- 'Offers.Listings.DeliveryInfo.IsPrimeEligible',
32
- 'Offers.Listings.MerchantInfo',
33
- 'Offers.Listings.Price',
34
- 'Offers.Listings.SavingBasis'
17
+ "Images.Primary.Large",
18
+ "ItemInfo.ByLineInfo",
19
+ "ItemInfo.ContentInfo",
20
+ "ItemInfo.ExternalIds",
21
+ "ItemInfo.Features",
22
+ "ItemInfo.ManufactureInfo",
23
+ "ItemInfo.ProductInfo",
24
+ "ItemInfo.TechnicalInfo", # Includes format when Kindle
25
+ "ItemInfo.Title",
26
+ "ItemInfo.TradeInInfo",
27
+ "Offers.Listings.Availability.Message",
28
+ "Offers.Listings.Condition",
29
+ "Offers.Listings.Condition.SubCondition",
30
+ "Offers.Listings.DeliveryInfo.IsAmazonFulfilled",
31
+ "Offers.Listings.DeliveryInfo.IsFreeShippingEligible",
32
+ "Offers.Listings.DeliveryInfo.IsPrimeEligible",
33
+ "Offers.Listings.MerchantInfo",
34
+ "Offers.Listings.Price",
35
+ "Offers.Listings.SavingBasis"
35
36
  ].freeze
36
37
 
37
38
  Locale = Struct.new(:key, :name, :host, :region) do
38
39
  def site
39
- host.sub('webservices', 'www')
40
+ host.sub("webservices", "www")
40
41
  end
41
42
  end
42
43
 
43
44
  MARKETPLACES = {
44
- au: Locale.new(:au, 'Australia', 'webservices.amazon.com.au', 'us-west-2'),
45
- br: Locale.new(:br, 'Brazil', 'webservices.amazon.com.br', 'us-east-1'),
46
- ca: Locale.new(:ca, 'Canada', 'webservices.amazon.ca', 'us-east-1'),
47
- fr: Locale.new(:fr, 'France', 'webservices.amazon.fr', 'eu-west-1'),
48
- de: Locale.new(:de, 'Germany', 'webservices.amazon.de', 'eu-west-1'),
49
- in: Locale.new(:in, 'India', 'webservices.amazon.in', 'eu-west-1'),
50
- it: Locale.new(:it, 'Italy', 'webservices.amazon.it', 'eu-west-1'),
51
- jp: Locale.new(:jp, 'Japan', 'webservices.amazon.co.jp', 'us-west-2'),
52
- mx: Locale.new(:mx, 'Mexico', 'webservices.amazon.com.mx', 'us-east-1'),
53
- es: Locale.new(:es, 'Spain', 'webservices.amazon.es', 'eu-west-1'),
54
- tr: Locale.new(:tk, 'Turkey', 'webservices.amazon.com.tr', 'eu-west-1'),
55
- ae: Locale.new(:ae, 'United Arab Emirates', 'webservices.amazon.ae', 'eu-west-1'),
56
- uk: Locale.new(:uk, 'United Kingdom', 'webservices.amazon.co.uk', 'eu-west-1'),
57
- us: Locale.new(:us, 'United States', 'webservices.amazon.com', 'us-east-1'),
45
+ au: Locale.new(:au, "Australia", "webservices.amazon.com.au", "us-west-2"),
46
+ br: Locale.new(:br, "Brazil", "webservices.amazon.com.br", "us-east-1"),
47
+ ca: Locale.new(:ca, "Canada", "webservices.amazon.ca", "us-east-1"),
48
+ fr: Locale.new(:fr, "France", "webservices.amazon.fr", "eu-west-1"),
49
+ de: Locale.new(:de, "Germany", "webservices.amazon.de", "eu-west-1"),
50
+ in: Locale.new(:in, "India", "webservices.amazon.in", "eu-west-1"),
51
+ it: Locale.new(:it, "Italy", "webservices.amazon.it", "eu-west-1"),
52
+ jp: Locale.new(:jp, "Japan", "webservices.amazon.co.jp", "us-west-2"),
53
+ mx: Locale.new(:mx, "Mexico", "webservices.amazon.com.mx", "us-east-1"),
54
+ es: Locale.new(:es, "Spain", "webservices.amazon.es", "eu-west-1"),
55
+ tr: Locale.new(:tk, "Turkey", "webservices.amazon.com.tr", "eu-west-1"),
56
+ ae: Locale.new(:ae, "United Arab Emirates", "webservices.amazon.ae", "eu-west-1"),
57
+ uk: Locale.new(:uk, "United Kingdom", "webservices.amazon.co.uk", "eu-west-1"),
58
+ us: Locale.new(:us, "United States", "webservices.amazon.com", "us-east-1")
58
59
  }.freeze
59
60
 
60
- Operation = Struct.new(:target_name, :endpoint_suffix, :http_method, :service )
61
+ Operation = Struct.new(:target_name, :endpoint_suffix, :http_method, :service)
61
62
 
62
63
  OPERATIONS = {
63
- get_browse_nodes: Operation.new( 'GetBrowseNodes', 'getbrowsenodes', 'POST', 'ProductAdvertisingAPI' ),
64
- get_items: Operation.new( 'GetItems', 'getitems', 'POST', 'ProductAdvertisingAPI' ),
65
- get_variations: Operation.new( 'GetVariations', 'getvariations', 'POST', 'ProductAdvertisingAPI' ),
66
- search_items: Operation.new( 'SearchItems', 'searchitems', 'POST', 'ProductAdvertisingAPI' )
64
+ get_browse_nodes: Operation.new("GetBrowseNodes", "getbrowsenodes", "POST", "ProductAdvertisingAPI"),
65
+ get_items: Operation.new("GetItems", "getitems", "POST", "ProductAdvertisingAPI"),
66
+ get_variations: Operation.new("GetVariations", "getvariations", "POST", "ProductAdvertisingAPI"),
67
+ search_items: Operation.new("SearchItems", "searchitems", "POST", "ProductAdvertisingAPI")
67
68
  }.freeze
68
69
 
69
70
  class << self
70
71
  attr_accessor :access_key,
71
- :secret_key,
72
- :partner_tag,
73
- :partner_type,
74
- :market,
75
- :partner_market,
76
- :condition,
77
- :resources,
78
- :test_mode
72
+ :secret_key,
73
+ :partner_tag,
74
+ :partner_type,
75
+ :market,
76
+ :partner_market,
77
+ :condition,
78
+ :resources,
79
+ :test_mode
79
80
 
80
81
  def configure
81
82
  yield self
@@ -85,7 +86,6 @@ module Paapi
85
86
  end
86
87
 
87
88
  def symbolize_keys(hash)
88
- Hash[hash.map{|k,v| v.is_a?(Hash) ? [k.to_sym, symbolize_keys(v)] : [k.to_sym, v] }]
89
+ hash.map { |k, v| v.is_a?(Hash) ? [k.to_sym, symbolize_keys(v)] : [k.to_sym, v] }.to_h
89
90
  end
90
91
  end
91
-
data/paapi.gemspec CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency 'rake', '>= 12.3.r3'
30
30
  spec.add_development_dependency 'minitest', '~> 5.0'
31
31
  spec.add_development_dependency 'byebug', '~> 11'
32
+ spec.add_development_dependency 'standard'
32
33
 
33
34
  spec.add_dependency 'aws-sigv4', '~> 1'
34
35
  spec.add_dependency 'net-http-persistent', '~> 4.0', '>= 4.0.1'
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.1.8
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Milne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-20 00:00:00.000000000 Z
11
+ date: 2024-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '11'
69
+ - !ruby/object:Gem::Dependency
70
+ name: standard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: aws-sigv4
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -145,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
159
  - !ruby/object:Gem::Version
146
160
  version: '0'
147
161
  requirements: []
148
- rubygems_version: 3.4.12
162
+ rubygems_version: 3.5.17
149
163
  signing_key:
150
164
  specification_version: 4
151
165
  summary: Client library for Amazon's Product Advertising API v5