google-dfp-api 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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