google-dfp-api 0.3.1 → 0.3.2

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.
data/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ 0.3.2:
2
+ - Require google-ads-common 0.7.3 or later from now on.
3
+ - Support for OAuth2.0 authentication method.
4
+ - Updated User-Agent to a single standard.
5
+
1
6
  0.3.1:
2
7
  - Now require Savon-0.9.9 (fixes Content-Length bug).
3
8
  - Require google-ads-common 0.7.0 or later from now on.
data/README CHANGED
@@ -208,8 +208,8 @@ respond in gzipped format. All requests are sent uncompressed regardless.
208
208
  External dependencies should be pulled automatically on gem install. Here is the
209
209
  list though:
210
210
 
211
- - Google Ads Common library (google-ads-common-0.7.0);
212
- - Savon 'the heavy metal Ruby SOAP client' (savon-0.9.9).
211
+ - Google Ads Common library (google-ads-common);
212
+ - Savon 'the heavy metal Ruby SOAP client' (savon).
213
213
 
214
214
 
215
215
  = Where do I submit bug reports and feature requests?
@@ -2,10 +2,24 @@
2
2
  # This is an example configuration file for the Ruby DFP API client library.
3
3
  # Please fill in the required fields, and copy it over to your home directory.
4
4
  :authentication:
5
- # Authentication method, methods currently supported: OAuth, ClientLogin.
5
+ # Authentication method, methods currently supported:
6
+ # OAuth2, OAuth, ClientLogin.
6
7
  :method: ClientLogin
7
8
 
8
- # Auth parameters for OAuth method.
9
+ # Auth parameters for OAuth2.0 method.
10
+ # Set the OAuth2 client id and secret. Register your application here to
11
+ # obtain these values:
12
+ # https://code.google.com/apis/console#access
13
+ #:oauth2_client_id: INSERT_OAUTH2_CLIENT_ID_HERE
14
+ #:oauth2_client_secret: INSERT_OAUTH2_CLIENT_SECRET_HERE
15
+ # Optional, see: https://developers.google.com/accounts/docs/OAuth2WebServer
16
+ #:oauth2_callback: INSERT_OAUTH2_CALLBACK_URL_HERE
17
+ #:oauth2_state: INSERT_OAUTH2_STATE_HERE
18
+ #:oauth2_access_type: INSERT_OAUTH2_ACCESS_TYPE_HERE
19
+ #:oauth2_approval_prompt: INSERT_OAUTH2_APPROVAL_PROMPT_HERE
20
+
21
+ # Auth parameters for OAuth1.0a method.
22
+ # NOTE: OAuth1.0a method is deprecated, use OAuth2.0 instead.
9
23
  # Set the OAuth consumer key and secret. Anonymous values can be used for
10
24
  # testing, and real values can be obtained by registering your application:
11
25
  # https://developers.google.com/accounts/docs/RegistrationForWebAppsAuto
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env ruby
2
+ # Encoding: utf-8
3
+ #
4
+ # Author:: api.dklimkin@gmail.com (Danial Klimkin)
5
+ #
6
+ # Copyright:: Copyright 2012, Google Inc. All Rights Reserved.
7
+ #
8
+ # License:: Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
17
+ # implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ #
21
+ # This example shows how to use OAuth2.0 authorization method. It is designed to
22
+ # be run from console and requires user input.
23
+ #
24
+ # Tags: UserService.getUsersByStatement
25
+
26
+ require 'dfp_api'
27
+
28
+ API_VERSION = :v201204
29
+ PAGE_SIZE = 500
30
+ MAX_RETRIES = 3
31
+
32
+ def oauth2_handling()
33
+ # Get DfpApi instance and load configuration from ~/dfp_api.yml.
34
+ dfp = DfpApi::Api.new
35
+
36
+ # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
37
+ # the configuration file or provide your own logger:
38
+ # dfp.logger = Logger.new('dfp_xml.log')
39
+
40
+ # Forcing authorization. A callback URL and other parameters could be
41
+ # specified as parameter for OAuth method.
42
+ token = dfp.authorize({:oauth_callback => 'oob'}) do |oauth_url|
43
+ # For command-line we ask user to go to URL and type in code.
44
+ verification_code = get_verification_code(oauth_url)
45
+ # Return verification code from the block.
46
+ (verification_code.empty?) ? nil : verification_code
47
+ end
48
+
49
+ # Get the UserService.
50
+ user_service = dfp.service(:UserService, API_VERSION)
51
+
52
+ # Define initial values.
53
+ offset = 0
54
+ page = Hash.new
55
+ retry_count = 0
56
+
57
+ begin
58
+ # Create statement for one page with current offset.
59
+ statement = {:query => "LIMIT %d OFFSET %d" % [PAGE_SIZE, offset]}
60
+
61
+ begin
62
+ # Get users by statement.
63
+ page = user_service.get_users_by_statement(statement)
64
+
65
+ # The second way to do OAuth authentication is to make a request and catch
66
+ # the OAuthVerificationRequired exception. Add the verification code to the
67
+ # credentials once acquired.
68
+ rescue AdsCommon::Errors::OAuth2VerificationRequired => e
69
+ if retry_count < MAX_RETRIES
70
+ verification_code = get_verification_code(e.oauth_url)
71
+ dfp.credential_handler.set_credential(
72
+ :oauth2_verification_code, verification_code)
73
+ retry_count += 1
74
+ retry
75
+ else
76
+ raise AdsCommon::Errors::AuthError, 'Failed to authenticate.'
77
+ end
78
+ end
79
+
80
+ if page[:results]
81
+ # Increase query offset by page size.
82
+ offset += PAGE_SIZE
83
+
84
+ # Get the start index for printout.
85
+ start_index = page[:start_index]
86
+
87
+ # Print details about each user in results page.
88
+ page[:results].each_with_index do |user, index|
89
+ puts "%d) User ID: %d, name: %s, email: %s" %
90
+ [index + start_index, user[:id], user[:name], user[:email]]
91
+ end
92
+ end
93
+ end while offset < page[:total_result_set_size]
94
+
95
+ # Print a footer
96
+ if page.include?(:total_result_set_size)
97
+ puts "Total number of users: %d" % page[:total_result_set_size]
98
+ end
99
+ end
100
+
101
+ # Misc util to get the verification code from the console.
102
+ def get_verification_code(url)
103
+ puts "Hit Auth error, please navigate to URL:\n\t%s" % url
104
+ print 'Log in and type the verification code: '
105
+ verification_code = gets.chomp
106
+ return verification_code
107
+ end
108
+
109
+ if __FILE__ == $0
110
+ begin
111
+ oauth2_handling()
112
+
113
+ # HTTP errors.
114
+ rescue AdsCommon::Errors::HttpError => e
115
+ puts "HTTP Error: %s" % e
116
+
117
+ # API errors.
118
+ rescue DfpApi::Errors::ApiException => e
119
+ puts "Message: %s" % e.message
120
+ puts 'Errors:'
121
+ e.errors.each_with_index do |error, index|
122
+ puts "\tError [%d]:" % (index + 1)
123
+ error.each do |field, value|
124
+ puts "\t\t%s: %s" % [field, value]
125
+ end
126
+ end
127
+ end
128
+ end
@@ -18,8 +18,11 @@
18
18
  # See the License for the specific language governing permissions and
19
19
  # limitations under the License.
20
20
  #
21
- # This example shows how to use OAuth authorization method. It is designed to be
22
- # run from console and requires user input.
21
+ # This example shows how to use OAuth1.0a authorization method. It is designed
22
+ # to be run from console and requires user input.
23
+ #
24
+ # NOTE: OAuth1.0a authorization method is deprecated, use OAuth2.0 instead.
25
+ # See oauth2_handling.rb for an example.
23
26
  #
24
27
  # Tags: UserService.getUsersByStatement
25
28
 
@@ -1,4 +1,4 @@
1
- #!/usr/bin/ruby
1
+ # Encoding: utf-8
2
2
  #
3
3
  # Authors:: api.dklimkin@gmail.com (Danial Klimkin)
4
4
  #
@@ -17,10 +17,7 @@
17
17
  # See the License for the specific language governing permissions and
18
18
  # limitations under the License.
19
19
  #
20
- # Contains the main classes for the client library. Takes care of all
21
- # dependencies.
22
-
23
- gem 'google-ads-common', '~>0.7.0'
20
+ # Contains the main classes for the client library.
24
21
 
25
22
  require 'ads_common/api'
26
23
  require 'ads_common/savon_headers/oauth_header_handler'
@@ -56,7 +53,7 @@ module DfpApi
56
53
  handler = case auth_method
57
54
  when :CLIENTLOGIN
58
55
  DfpApi::ClientLoginHeaderHandler
59
- when :OAUTH
56
+ when :OAUTH, :OAUTH2
60
57
  AdsCommon::SavonHeaders::OAuthHeaderHandler
61
58
  else
62
59
  raise AdsCommon::Errors::AuthError,
@@ -1,4 +1,4 @@
1
- #!/usr/bin/ruby
1
+ # Encoding: utf-8
2
2
  #
3
3
  # Authors:: api.dklimkin@gmail.com (Danial Klimkin)
4
4
  #
@@ -36,14 +36,27 @@ module DfpApi
36
36
  return result
37
37
  end
38
38
 
39
+ # Generates string to user as user agent in HTTP headers.
40
+ def generate_http_user_agent(extra_ids = [])
41
+ extra_ids, agent_app = get_user_agent_data(extra_ids)
42
+ super(extra_ids, agent_app)
43
+ end
44
+
39
45
  # Generates string to user as user agent in SOAP headers.
40
46
  def generate_soap_user_agent(extra_ids = [])
41
- extra_ids << ["DfpApi-Ruby-%s" % DfpApi::ApiConfig::CLIENT_LIB_VERSION]
42
- super(extra_ids)
47
+ extra_ids, agent_app = get_user_agent_data(extra_ids)
48
+ super(extra_ids, agent_app)
43
49
  end
44
50
 
45
51
  private
46
52
 
53
+ # Returns agent name and data for user-agent string generation.
54
+ def get_user_agent_data(extra_ids)
55
+ agent_app = @config.read('authentication.application_name')
56
+ extra_ids << ["DfpApi-Ruby/%s" % DfpApi::ApiConfig::CLIENT_LIB_VERSION]
57
+ return [extra_ids, agent_app]
58
+ end
59
+
47
60
  # Validates that the right credentials are being used for the chosen
48
61
  # environment.
49
62
  # TODO(dklimkin): implement NetworkCode check.
@@ -21,6 +21,6 @@
21
21
 
22
22
  module DfpApi
23
23
  module ApiConfig
24
- CLIENT_LIB_VERSION = '0.3.1'
24
+ CLIENT_LIB_VERSION = '0.3.2'
25
25
  end
26
26
  end
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Author:: api.dklimkin@gmail.com (Danial Klimkin)
4
+ #
5
+ # Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
6
+ #
7
+ # License:: Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
16
+ # implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+ # Tests issue #16.
21
+
22
+ require 'nori'
23
+ require 'savon'
24
+ require 'test/unit'
25
+
26
+ require 'ads_common/results_extractor'
27
+ require 'dfp_api/v201204/line_item_service_registry'
28
+
29
+ class TestDfpApi < Test::Unit::TestCase
30
+
31
+ def setup()
32
+ @registry = DfpApi::V201204::LineItemService::LineItemServiceRegistry
33
+ end
34
+
35
+ def test_issue_16()
36
+ data = Nori.parse(get_xml_text())[:envelope][:body]
37
+ extractor = AdsCommon::ResultsExtractor.new(@registry)
38
+ result = extractor.extract_result(data, 'get_line_items_by_statement')
39
+ targeting = result[:results][0][:targeting][:inventory_targeting]
40
+ assert_equal([1234567, 23456], targeting[:targeted_placement_ids])
41
+ end
42
+
43
+ def get_xml_text()
44
+ return <<EOT
45
+ <?xml version="1.0"?>
46
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
47
+ <soap:Header>
48
+ <ResponseHeader xmlns="https://www.google.com/apis/ads/publisher/v201101">
49
+ <requestId>dac42656454</requestId>
50
+ <responseTime>9</responseTime>
51
+ </ResponseHeader>
52
+ </soap:Header>
53
+ <soap:Body>
54
+ <getLineItemsByStatementResponse
55
+ xmlns="https://www.google.com/apis/ads/publisher/v201101">
56
+ <rval>
57
+ <totalResultSetSize>1</totalResultSetSize>
58
+ <startIndex>0</startIndex>
59
+ <results>
60
+ <orderId>345678</orderId>
61
+ <id>89012</id>
62
+ <name>some name</name>
63
+ <orderName>someOrderName</orderName>
64
+ <startDateTime>
65
+ <date>
66
+ <year>2011</year>
67
+ <month>1</month>
68
+ <day>1</day>
69
+ </date>
70
+ <hour>0</hour>
71
+ <minute>0</minute>
72
+ <second>0</second>
73
+ <timeZoneID>America/New_York</timeZoneID>
74
+ </startDateTime>
75
+ <startDateTimeType>USE_START_DATE_TIME</startDateTimeType>
76
+ <endDateTime>
77
+ <date>
78
+ <year>2011</year>
79
+ <month>2</month>
80
+ <day>1</day>
81
+ </date>
82
+ <hour>23</hour>
83
+ <minute>59</minute>
84
+ <second>0</second>
85
+ <timeZoneID>America/New_York</timeZoneID>
86
+ </endDateTime>
87
+ <unlimitedEndDateTime>false</unlimitedEndDateTime>
88
+ <creativeRotationType>OPTIMIZED</creativeRotationType>
89
+ <deliveryRateType>EVENLY</deliveryRateType>
90
+ <roadblockingType>ONE_OR_MORE</roadblockingType>
91
+ <lineItemType>STANDARD</lineItemType>
92
+ <unitType>IMPRESSIONS</unitType>
93
+ <duration>LIFETIME</duration>
94
+ <unitsBought>3</unitsBought>
95
+ <costPerUnit>
96
+ <currencyCode>USD</currencyCode>
97
+ <microAmount>0</microAmount>
98
+ </costPerUnit>
99
+ <valueCostPerUnit>
100
+ <currencyCode>USD</currencyCode>
101
+ <microAmount>0</microAmount>
102
+ </valueCostPerUnit>
103
+ <costType>CPM</costType>
104
+ <discountType>PERCENTAGE</discountType>
105
+ <discount>0.0</discount>
106
+ <creativeSizes>
107
+ <width>160</width>
108
+ <height>600</height>
109
+ <isAspectRatio>false</isAspectRatio>
110
+ </creativeSizes>
111
+ <creativeSizes>
112
+ <width>336</width>
113
+ <height>280</height>
114
+ <isAspectRatio>false</isAspectRatio>
115
+ </creativeSizes>
116
+ <creativeSizes>
117
+ <width>728</width>
118
+ <height>90</height>
119
+ <isAspectRatio>false</isAspectRatio>
120
+ </creativeSizes>
121
+ <allowOverbook>false</allowOverbook>
122
+ <stats>
123
+ <impressionsDelivered>123</impressionsDelivered>
124
+ <clicksDelivered>345</clicksDelivered>
125
+ </stats>
126
+ <deliveryIndicator>
127
+ <expectedDeliveryPercentage>11.11111</expectedDeliveryPercentage>
128
+ <actualDeliveryPercentage>22.222</actualDeliveryPercentage>
129
+ </deliveryIndicator>
130
+ <budget>
131
+ <currencyCode>USD</currencyCode>
132
+ <microAmount>0</microAmount>
133
+ </budget>
134
+ <status>DELIVERING</status>
135
+ <reservationStatus>RESERVED</reservationStatus>
136
+ <isArchived>false</isArchived>
137
+ <LineItemSummary.Type>LineItem</LineItemSummary.Type>
138
+ <targeting>
139
+ <inventoryTargeting>
140
+ <targetedPlacementIds>1234567</targetedPlacementIds>
141
+ <targetedPlacementIds>23456</targetedPlacementIds>
142
+ </inventoryTargeting>
143
+ </targeting>
144
+ </results>
145
+ </rval>
146
+ </getLineItemsByStatementResponse>
147
+ </soap:Body>
148
+ </soap:Envelope>
149
+ EOT
150
+ end
151
+ end
@@ -27,3 +27,6 @@ require 'test/unit'
27
27
 
28
28
  # DFP API units tests.
29
29
  Dir.glob('./test/dfp_api/test_*.rb').each {|file| require file}
30
+
31
+ # DFP API bug tests.
32
+ Dir.glob('./test/bugs/test_*.rb').each {|file| require file}
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-dfp-api
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
5
- prerelease: false
4
+ hash: 23
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 1
10
- version: 0.3.1
9
+ - 2
10
+ version: 0.3.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Danial Klimkin
@@ -15,41 +15,24 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-05-16 00:00:00 +04:00
19
- default_executable:
18
+ date: 2012-06-21 00:00:00 Z
20
19
  dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: savon
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- hash: 41
30
- segments:
31
- - 0
32
- - 9
33
- - 9
34
- version: 0.9.9
35
- type: :runtime
36
- version_requirements: *id001
37
20
  - !ruby/object:Gem::Dependency
38
21
  name: google-ads-common
39
22
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
41
24
  none: false
42
25
  requirements:
43
26
  - - ~>
44
27
  - !ruby/object:Gem::Version
45
- hash: 3
28
+ hash: 5
46
29
  segments:
47
30
  - 0
48
31
  - 7
49
- - 0
50
- version: 0.7.0
32
+ - 3
33
+ version: 0.7.3
51
34
  type: :runtime
52
- version_requirements: *id002
35
+ version_requirements: *id001
53
36
  description: google-dfp-api is a DFP API client library for Ruby
54
37
  email:
55
38
  - api.dklimkin@gmail.com
@@ -172,6 +155,7 @@ files:
172
155
  - examples/v201111/line_item_service/get_line_item.rb
173
156
  - examples/v201204/common/error_handling.rb
174
157
  - examples/v201204/common/oauth_handling.rb
158
+ - examples/v201204/common/oauth2_handling.rb
175
159
  - examples/v201204/suggested_ad_unit_service/get_all_suggested_ad_units.rb
176
160
  - examples/v201204/suggested_ad_unit_service/approve_all_suggested_ad_units.rb
177
161
  - examples/v201204/suggested_ad_unit_service/get_suggested_ad_unit.rb
@@ -774,6 +758,7 @@ files:
774
758
  - lib/dfp_api/v201201/creative_service.rb
775
759
  - lib/dfp_api/v201201/user_service_registry.rb
776
760
  - lib/dfp_api/client_login_header_handler.rb
761
+ - test/bugs/test_issue_00000016.rb
777
762
  - test/dfp_api/test_dfp_api.rb
778
763
  - test/dfp_api/test_config.yml
779
764
  - test/suite_unittests.rb
@@ -781,7 +766,6 @@ files:
781
766
  - README
782
767
  - ChangeLog
783
768
  - dfp_api.yml
784
- has_rdoc: true
785
769
  homepage: http://code.google.com/p/google-api-ads-ruby/
786
770
  licenses: []
787
771
 
@@ -813,9 +797,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
813
797
  requirements: []
814
798
 
815
799
  rubyforge_project: google-dfp-api
816
- rubygems_version: 1.3.7
800
+ rubygems_version: 1.8.24
817
801
  signing_key:
818
802
  specification_version: 3
819
803
  summary: Ruby Client libraries for DFP API
820
804
  test_files:
805
+ - test/bugs/test_issue_00000016.rb
821
806
  - test/dfp_api/test_dfp_api.rb