blurb 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bb4aebb3a2bdb46403386ed36afbd74790fb441a
4
- data.tar.gz: c4c9a3d19a8179cdaaea574cb0e8a4e20d7eefcc
2
+ SHA256:
3
+ metadata.gz: 308f8f046233821f03d87749c7bbbc5bd99d440b471f526bfffc82e50e187d07
4
+ data.tar.gz: 8e5c1636d1a129af2c21daf33fb10d2397da31b9dafafd8abdf924495c1c6775
5
5
  SHA512:
6
- metadata.gz: f5cbcd59aa71b3f3c94334c2a51fec760d7dfb328c12d7fbc9aaa0919bff768f4c33c6ac56e5e17e1edec7eb46d14b9e0210dddad68543369139b335d9fc2bc6
7
- data.tar.gz: 8c732c2235b78f7cb8cd327002e2f74340f540b24e44f36eeacd608219bfd5033345a7241bd2635c0fa7be508097b993f03c340d6f0184d04878c3aa2efc5ce7
6
+ metadata.gz: 4e7350f33658327c5a11e81835de61b2e68a141e812d335fcddab777ea3c36f3ae90bb36756c14656233106e9514bf3742e0a32d9d5ac1d90a89ab946e4c7878
7
+ data.tar.gz: 82bda34380cb304a6422fea70f0af6e14832c71a4c8339407fd192064799725fce1344baae64b915211b28064f8ae89ee1afca7217320ccc443392848c716688
@@ -6,7 +6,7 @@ version: 2
6
6
  jobs:
7
7
  build:
8
8
  docker:
9
- - image: circleci/ruby:2.4.4
9
+ - image: circleci/ruby:2.6.2
10
10
 
11
11
  steps:
12
12
  - checkout
@@ -21,6 +21,7 @@ jobs:
21
21
  - run:
22
22
  name: install dependencies
23
23
  command: |
24
+ gem install bundler -v 2.0.2
24
25
  bundle install --jobs=4 --retry=3 --path vendor/bundle
25
26
 
26
27
  - save_cache:
data/.gitignore CHANGED
@@ -11,3 +11,4 @@
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
13
  .env
14
+ .byebug_history
@@ -1,5 +1,5 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.4.4
5
- before_install: gem install bundler -v 1.14.6
4
+ - 2.6.2
5
+ before_install: gem install bundler -v 2.0.2
data/README.md CHANGED
@@ -83,50 +83,56 @@ You can find your profiles by making the following Blurb call.
83
83
 
84
84
  This will return a JSON payload of profile information for your account. You can then select the profile ID you want to use.
85
85
 
86
- ## Blurb Values Setup
87
- Before using the Blurb API wrapper you need to set your API values. Simply do that by initializing the Blurb values to your API values.
88
- If you are using Rails, see below.
89
86
 
90
- ```ruby
91
- Blurb.profile_id = "<YOUR_PROFILE_ID>"
92
- Blurb.client_id = "<YOUR_CLIENT_ID>"
93
- Blurb.client_secret = "<YOUR_CLIENT_SECRET>"
94
- Blurb.refresh_token = "<YOUR_REFRESH_TOKEN>"
95
- ```
87
+
88
+
96
89
 
97
90
  ## Rails Integration
98
91
 
99
- You can setup the Amazon API keys and tokens in an initializer script.
100
- Create a file called config/initializers/blurb.rb and setup the following values
92
+ When creating a new resource object, you may pass in a hash containing your api keys and tokens. Utilizing this approach allows you to dynamically toggle accounts and or regions with you application.
101
93
 
102
94
  ```ruby
103
- Blurb.profile_id = "<YOUR_PROFILE_ID>"
104
- Blurb.client_id = "<YOUR_CLIENT_ID>"
105
- Blurb.client_secret = "<YOUR_CLIENT_SECRET>"
106
- Blurb.refresh_token = "<YOUR_REFRESH_TOKEN>"
95
+ authorization_hash = {
96
+ client_id: 'my_client_id',
97
+ profile_id: 'my_profile_id',
98
+ client_secret: 'client_secret',
99
+ refresh_token: 'refresh_token',
100
+ region: 'my_region'
101
+ }
102
+
103
+ blurb_instance = Blurb::Keyword.new(authorization_hash)
107
104
  ```
108
105
 
109
- If you don't want to store your API values in your code which gets checked into a public repo, you can utilize ENV variables
106
+
107
+
108
+
109
+
110
+ If you only plan on using Blurb for one api account and region you can setup the Amazon API keys and tokens in an initializer script.
111
+ Create a file called config/initializers/blurb.rb and setup the following values
110
112
 
111
113
  ```ruby
112
114
  Blurb.profile_id = ENV["YOUR_PROFILE_ID_VAR"]
113
115
  Blurb.client_id = ENV["YOUR_CLIENT_ID_VAR"]
114
116
  Blurb.client_secret = ENV["YOUR_CLIENT_SECRET_VAR"]
115
117
  Blurb.refresh_token = ENV["YOUR_REFRESH_TOKEN_VAR"]
118
+ Blurb.region = ENV["YOUR_REGION_VAR"]
116
119
  ```
117
120
 
118
- You could also store API values in a persistence store and initialize from there too.
119
-
120
- ## API Environments
121
-
122
- By default Blurb will run API calls to the Amazon Advertising API production environment.
123
- If you are under development and want to test out the API to see what it can do, you can set
124
- the following Blurb property to use the API test environment.
121
+ Now, you no longer need to pass in an authorization hash when initializing the resource object.
125
122
 
126
123
  ```ruby
127
- Blurb.test_env = true
124
+ blurb_instance = Blurb::Keyword.new()
128
125
  ```
129
126
 
127
+ ### Valid Region Codes
128
+
129
+ Region Code | Region | Notes
130
+ --- | --- | ---
131
+ TEST | Sandbox Environment | All marketplaces
132
+ NA | North America | Covers US and CA marketplaces
133
+ EU | Europe | Covers UK, FR, IT, ES, and DE marketplaces
134
+ FE | Far East | Cover JP and AU marketplaces
135
+
130
136
  ## Usage
131
137
 
132
138
  All API calls have been setup as closely as possible to REST Resource calls.
@@ -138,19 +144,6 @@ For example, to use the keywords resource object:
138
144
  blurb_instance = Blurb::Keyword.new()
139
145
  ```
140
146
 
141
- Optionally, you may pass in a set of account credentials to override the default API keys and tokens
142
-
143
- ```ruby
144
- authorization_hash = {
145
- client_id: 'my_client_id',
146
- profile_id: 'my_profile_id',
147
- client_secret: 'client_secret',
148
- refresh_token: 'refresh_token'
149
- }
150
-
151
- blurb_instance = Blurb::Keyword.new(authorization_hash)
152
- ```
153
-
154
147
  In calls that require 'campaign_type' as a parameter, you must pass in either 'sp' for sponsored products or 'hsa' for sponsored brands (formerly known as headline search ads).
155
148
 
156
149
  NOTE: Not all API endpoints are currently supported by Blurb. Over time we will get more
@@ -380,6 +373,15 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
380
373
 
381
374
  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).
382
375
 
376
+ In order to run the rspec test suite, you will need the following variables in a .env file:
377
+
378
+ ```
379
+ PROFILE_ID
380
+ CLIENT_ID
381
+ CLIENT_SECRET
382
+ REFRESH_TOKEN
383
+ ```
384
+
383
385
  ## Contributing
384
386
 
385
387
  Bug reports and pull requests are welcome on GitHub at https://github.com/iserve-products/blurb. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
@@ -5,6 +5,7 @@ require "blurb"
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
8
+ require 'dotenv/load'
8
9
 
9
10
  # (If you use this, don't forget to add pry to your Gemfile!)
10
11
  # require "pry"
@@ -1,13 +1,12 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'blurb/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = "blurb"
8
- spec.version = Blurb::VERSION
9
- spec.authors = ["dlbunker"]
10
- spec.email = ["dan@iserve.com"]
7
+ spec.version = "0.4.0"
8
+ spec.authors = ["dlbunker", "eamigo13"]
9
+ spec.email = ["evan@pattern.com"]
11
10
 
12
11
  spec.summary = %q{Ruby gem for the Amazon Advertising API}
13
12
  spec.description = %q{Amazon released a new Advertising API in 2017. This gem will integrate and allow you to make API calls to Amazon.}
@@ -30,12 +29,16 @@ Gem::Specification.new do |spec|
30
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
30
  spec.require_paths = ["lib"]
32
31
 
33
- spec.add_development_dependency "bundler", "~> 1.14"
32
+ spec.add_development_dependency "bundler", "~> 2.0"
34
33
  spec.add_development_dependency "rake", "~> 10.0"
35
34
  spec.add_development_dependency "rspec", "~> 3.0"
36
35
  spec.add_development_dependency "rspec_junit_formatter", "~> 0.3.0"
36
+ spec.add_development_dependency "dotenv"
37
+ spec.add_development_dependency "byebug"
38
+ spec.add_development_dependency "faker", "~> 2.1.0"
37
39
 
38
40
  spec.add_runtime_dependency "rest-client", "~> 2.0"
39
41
  spec.add_runtime_dependency "oauth2", "~> 1.4.0"
42
+ spec.add_runtime_dependency "activesupport"
40
43
 
41
44
  end
@@ -1,32 +1,26 @@
1
- require "oauth2"
2
- require "rest-client"
1
+ require "blurb/account"
2
+ require "blurb/client"
3
3
 
4
- require "blurb/version"
5
- require "blurb/base_resource"
4
+ class Blurb
5
+ attr_accessor :client, :account
6
6
 
7
- require "blurb/bid_recommendation"
8
- require "blurb/campaign"
9
- require "blurb/profile"
10
- require "blurb/report"
11
- require "blurb/snapshot"
12
- require "blurb/suggested_keyword"
13
- require "blurb/keyword"
14
- require "blurb/ad_group"
15
-
16
- module Blurb
17
-
18
- def self.default_account
19
- {
20
- client_secret: self.client_secret,
21
- client_id: self.client_id,
22
- refresh_token: self.refresh_token,
23
- profile_id: self.profile_id,
24
- eu_env: self.eu_env
25
- }
7
+ def initialize(
8
+ # Default to env variables
9
+ client_id: ENV["BLURB_CLIENT_ID"],
10
+ client_secret: ENV["BLURB_CLIENT_SECRET"],
11
+ refresh_token: ENV["BLURB_REFRESH_TOKEN"],
12
+ region: ENV["BLURB_REGION"],
13
+ profile_id: ENV["BLURB_PROFILE_ID"] # profile_id can be left nil
14
+ )
15
+ @client = Client.new(client_id: client_id, client_secret: client_secret)
16
+ @account = Account.new(refresh_token: refresh_token, region: region, client: @client, profile_id: profile_id)
26
17
  end
27
18
 
28
- class << self
29
- attr_accessor :client_secret, :client_id, :refresh_token, :profile_id, :test_env, :eu_env
19
+ def profiles
20
+ @account.profiles
30
21
  end
31
22
 
23
+ def active_profile
24
+ @account.active_profile
25
+ end
32
26
  end
@@ -0,0 +1,108 @@
1
+ require "oauth2"
2
+ require "blurb/client"
3
+ require "blurb/profile"
4
+
5
+ class Blurb
6
+ class Account < BaseClass
7
+ attr_accessor :refresh_token, :api_url, :client, :profiles, :active_profile
8
+
9
+ API_URLS = {
10
+ "TEST" => "https://advertising-api-test.amazon.com",
11
+ "NA" => "https://advertising-api.amazon.com",
12
+ "EU" => "https://advertising-api-eu.amazon.com",
13
+ "FE" => "https://advertising-api-fe.amazon.com"
14
+ }
15
+
16
+ def initialize(refresh_token:, region:, client:, profile_id: nil)
17
+ @refresh_token = refresh_token
18
+ @api_url = API_URLS[region]
19
+ @client = client
20
+ @token_refreshed_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) # current time
21
+ @authorization_token = retrieve_token
22
+ initialize_profiles(profile_id)
23
+ end
24
+
25
+ def initialize_profiles(profile_id=nil)
26
+ @profiles = []
27
+ if profile_id
28
+ @profiles << Profile.new(
29
+ profile_id: profile_id,
30
+ account: self
31
+ )
32
+ else
33
+ amazon_profiles = profile_list()
34
+ amazon_profiles.each do |p|
35
+ @profiles << Profile.new(
36
+ profile_id: p[:profile_id],
37
+ account: self
38
+ )
39
+ end
40
+ end
41
+ @active_profile = @profiles.first
42
+ end
43
+
44
+ def set_active_profile(profile_id)
45
+ @active_profile = get_profile(profile_id)
46
+ end
47
+
48
+ def get_profile(profile_id)
49
+ @profiles.find{ |p| p.profile_id == profile_id }
50
+ end
51
+
52
+ def profile_list
53
+ profile_request("/v2/profiles")
54
+ end
55
+
56
+ def retrieve_profile(profile_id)
57
+ profile_request("/v2/profiles/#{profile_id}")
58
+ end
59
+
60
+ def retrieve_token
61
+ current_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
62
+ elapsed_time = current_time - @token_refreshed_at
63
+
64
+ # refresh the token if it's been over an hour
65
+ if @authorization_token.nil? || elapsed_time >= 3600 # 1 hour #Look at using amazons expires_inblurb/
66
+ response = authorization_client.request(:post, "/auth/o2/token",
67
+ {
68
+ body: {
69
+ grant_type: "refresh_token",
70
+ client_id: @client.client_id,
71
+ refresh_token: @refresh_token,
72
+ client_secret: @client.client_secret
73
+ }
74
+ }
75
+ )
76
+
77
+ @authorization_token = JSON.parse(response.body)['access_token']
78
+ @token_refreshed_at = current_time
79
+ end
80
+
81
+ return @authorization_token
82
+ end
83
+
84
+ private
85
+
86
+ def profile_request(api_path)
87
+ request = Request.new(
88
+ url: "#{@api_url}#{api_path}",
89
+ request_type: :get,
90
+ headers: {
91
+ "Authorization" => "Bearer #{retrieve_token()}",
92
+ "Content-Type" => "application/json",
93
+ "Amazon-Advertising-API-ClientId" => @client.client_id
94
+ }
95
+ )
96
+
97
+ request.make_request
98
+ end
99
+
100
+ def authorization_client
101
+ return OAuth2::Client.new(
102
+ "",
103
+ "",
104
+ :site => "https://api.amazon.com"
105
+ )
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,8 @@
1
+ class Blurb
2
+ class BaseClass
3
+ CAMPAIGN_TYPE_CODES = {
4
+ sp: 'sp',
5
+ sb: 'hsa'
6
+ }.freeze
7
+ end
8
+ end
@@ -0,0 +1,23 @@
1
+ require 'blurb/request_collection_with_campaign_type'
2
+
3
+ class Blurb
4
+ class CampaignRequests < RequestCollectionWithCampaignType
5
+ def create_bulk(create_array)
6
+ create_array = map_campaign_payload(create_array)
7
+ super(create_array)
8
+ end
9
+
10
+ def update_bulk(update_array)
11
+ update_array = map_campaign_payload(update_array)
12
+ super(update_array)
13
+ end
14
+
15
+ private
16
+
17
+ def map_campaign_payload(payload)
18
+ campaign_type_string = "sponsoredProducts" if @campaign_type == CAMPAIGN_TYPE_CODES[:sp]
19
+ campaign_type_string = "sponsoredBrands" if @campaign_type == CAMPAIGN_TYPE_CODES[:sb]
20
+ payload.each{ |p| p[:campaign_type] = campaign_type_string }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ require "blurb/base_class"
2
+
3
+ class Blurb
4
+ class Client < BaseClass
5
+ attr_accessor :client_id, :client_secret
6
+
7
+ def initialize(client_id:, client_secret:)
8
+ @client_id = client_id
9
+ @client_secret = client_secret
10
+ end
11
+ end
12
+ end
@@ -1,12 +1,146 @@
1
- module Blurb
2
- class Profile < BaseResource
1
+ require "blurb/account"
2
+ require "blurb/campaign_requests"
3
+ require "blurb/snapshot_requests"
4
+ require "blurb/report_requests"
5
+ require "blurb/request_collection"
6
+ require "blurb/request_collection_with_campaign_type"
7
+ require "blurb/suggested_keyword_requests"
3
8
 
4
- def list()
5
- profile_request("/v2/profiles")
9
+ class Blurb
10
+ class Profile < BaseClass
11
+
12
+ attr_accessor(
13
+ :account,
14
+ :ad_groups,
15
+ :campaign_negative_keywords,
16
+ :portfolios,
17
+ :product_ads,
18
+ :profile_id,
19
+ :suggested_keywords,
20
+ )
21
+
22
+ def initialize(profile_id:, account:)
23
+ @profile_id = profile_id
24
+ @account = account
25
+
26
+ @sp_campaigns = CampaignRequests.new(
27
+ headers: headers_hash,
28
+ base_url: @account.api_url,
29
+ resource: "campaigns",
30
+ campaign_type: CAMPAIGN_TYPE_CODES[:sp]
31
+ )
32
+ @sb_campaigns = CampaignRequests.new(
33
+ headers: headers_hash,
34
+ base_url: @account.api_url,
35
+ resource: "campaigns",
36
+ campaign_type: CAMPAIGN_TYPE_CODES[:sb]
37
+ )
38
+ @sp_keywords = RequestCollectionWithCampaignType.new(
39
+ headers: headers_hash,
40
+ base_url: @account.api_url,
41
+ resource: "keywords",
42
+ campaign_type: CAMPAIGN_TYPE_CODES[:sp]
43
+ )
44
+ @sb_keywords = RequestCollectionWithCampaignType.new(
45
+ headers: headers_hash,
46
+ base_url: @account.api_url,
47
+ resource: "keywords",
48
+ campaign_type: CAMPAIGN_TYPE_CODES[:sb]
49
+ )
50
+ @sp_snapshots = SnapshotRequests.new(
51
+ headers: headers_hash,
52
+ base_url: @account.api_url,
53
+ campaign_type: CAMPAIGN_TYPE_CODES[:sp]
54
+ )
55
+ @sb_snapshots = SnapshotRequests.new(
56
+ headers: headers_hash,
57
+ base_url: @account.api_url,
58
+ campaign_type: CAMPAIGN_TYPE_CODES[:sb]
59
+ )
60
+ @sp_reports = ReportRequests.new(
61
+ headers: headers_hash,
62
+ base_url: @account.api_url,
63
+ campaign_type: CAMPAIGN_TYPE_CODES[:sp]
64
+ )
65
+ @sb_reports = ReportRequests.new(
66
+ headers: headers_hash,
67
+ base_url: @account.api_url,
68
+ campaign_type: CAMPAIGN_TYPE_CODES[:sb]
69
+ )
70
+ @ad_groups = RequestCollection.new(
71
+ headers: headers_hash,
72
+ base_url: "#{@account.api_url}/v2/sp/adGroups"
73
+ )
74
+ @product_ads = RequestCollection.new(
75
+ headers: headers_hash,
76
+ base_url: "#{account.api_url}/v2/sp/productAds"
77
+ )
78
+ @sp_negative_keywords = RequestCollectionWithCampaignType.new(
79
+ headers: headers_hash,
80
+ base_url: @account.api_url,
81
+ resource: 'negativeKeywords',
82
+ campaign_type: CAMPAIGN_TYPE_CODES[:sp]
83
+ )
84
+ @sb_negative_keywords = RequestCollectionWithCampaignType.new(
85
+ headers: headers_hash,
86
+ base_url: @account.api_url,
87
+ resource: 'negativeKeywords',
88
+ campaign_type: CAMPAIGN_TYPE_CODES[:sb]
89
+ )
90
+ @campaign_negative_keywords = RequestCollection.new(
91
+ headers: headers_hash,
92
+ base_url: "#{@account.api_url}/v2/sp/campaignNegativeKeywords"
93
+ )
94
+ @portfolios = RequestCollection.new(
95
+ headers: headers_hash,
96
+ base_url: "#{@account.api_url}/v2/portfolios"
97
+ )
98
+ @suggested_keywords = SuggestedKeywordRequests.new(
99
+ headers: headers_hash,
100
+ base_url: "#{@account.api_url}/v2/sp"
101
+ )
102
+ end
103
+
104
+ def campaigns(campaign_type)
105
+ return @sp_campaigns if campaign_type == :sp
106
+ return @sb_campaigns if campaign_type == :sb || campaign_type == :hsa
107
+ end
108
+
109
+ def keywords(campaign_type)
110
+ return @sp_keywords if campaign_type == :sp
111
+ return @sb_keywords if campaign_type == :sb || campaign_type == :hsa
112
+ end
113
+
114
+ def negative_keywords(campaign_type)
115
+ return @sp_negative_keywords if campaign_type == :sp
116
+ return @sb_negative_keywords if campaign_type == :sb || campaign_type == :hsa
6
117
  end
7
118
 
8
- def retrieve(profile_id)
9
- profile_request("/v2/profiles/#{profile_id}")
119
+ def snapshots(campaign_type)
120
+ return @sp_snapshots if campaign_type == :sp
121
+ return @sb_snapshots if campaign_type == :sb || campaign_type == :hsa
122
+ end
123
+
124
+ def reports(campaign_type)
125
+ return @sp_reports if campaign_type == :sp
126
+ return @sb_reports if campaign_type == :sb || campaign_type == :hsa
127
+ end
128
+
129
+ def profile_details
130
+ @account.retrieve_profile(@profile_id)
131
+ end
132
+
133
+ def headers_hash(opts = {})
134
+ headers_hash = {
135
+ "Authorization" => "Bearer #{@account.retrieve_token()}",
136
+ "Content-Type" => "application/json",
137
+ "Amazon-Advertising-API-Scope" => @profile_id,
138
+ "Amazon-Advertising-API-ClientId" => @account.client.client_id
139
+ }
140
+
141
+ headers_hash["Content-Encoding"] = "gzip" if opts[:gzip]
142
+
143
+ return headers_hash
10
144
  end
11
145
  end
12
146
  end