adwords4r 13.0.1 → 15.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/Authors.txt +2 -1
  2. data/ChangeLog.txt +28 -0
  3. data/Copying.txt +1 -1
  4. data/{Licence.txt → License.txt} +1 -1
  5. data/Rakefile +49 -54
  6. data/Readme.txt +78 -24
  7. data/adwords.properties +1 -1
  8. data/examples/account_info.rb +20 -26
  9. data/examples/create_all.rb +51 -53
  10. data/examples/create_all_v200902.rb +204 -0
  11. data/examples/keyword_suggestions.rb +35 -38
  12. data/examples/multiple_versions.rb +167 -0
  13. data/examples/reports.rb +37 -75
  14. data/lib/adwords4r.rb +123 -123
  15. data/lib/adwords4r/adwordslogger.rb +56 -0
  16. data/lib/adwords4r/apiextensions.rb +79 -0
  17. data/lib/adwords4r/authtoken.rb +56 -0
  18. data/lib/adwords4r/credentials.rb +115 -19
  19. data/lib/adwords4r/services.rb +139 -14
  20. data/lib/adwords4r/soap4rpatches.rb +129 -0
  21. data/lib/adwords4r/v13/AccountService.rb +11 -11
  22. data/lib/adwords4r/v13/AccountServiceDriver.rb +7 -5
  23. data/lib/adwords4r/v13/AccountServiceMappingRegistry.rb +56 -56
  24. data/lib/adwords4r/v13/AdGroupService.rb +9 -9
  25. data/lib/adwords4r/v13/AdGroupServiceDriver.rb +11 -9
  26. data/lib/adwords4r/v13/AdGroupServiceMappingRegistry.rb +47 -47
  27. data/lib/adwords4r/v13/AdService.rb +37 -37
  28. data/lib/adwords4r/v13/AdServiceDriver.rb +12 -10
  29. data/lib/adwords4r/v13/AdServiceMappingRegistry.rb +148 -148
  30. data/lib/adwords4r/v13/CampaignService.rb +46 -25
  31. data/lib/adwords4r/v13/CampaignServiceDriver.rb +23 -13
  32. data/lib/adwords4r/v13/CampaignServiceMappingRegistry.rb +169 -135
  33. data/lib/adwords4r/v13/CriterionService.rb +19 -19
  34. data/lib/adwords4r/v13/CriterionServiceDriver.rb +11 -9
  35. data/lib/adwords4r/v13/CriterionServiceMappingRegistry.rb +90 -90
  36. data/lib/adwords4r/v13/InfoService.rb +3 -3
  37. data/lib/adwords4r/v13/InfoServiceDriver.rb +10 -8
  38. data/lib/adwords4r/v13/InfoServiceMappingRegistry.rb +29 -29
  39. data/lib/adwords4r/v13/KeywordToolService.rb +10 -10
  40. data/lib/adwords4r/v13/KeywordToolServiceDriver.rb +4 -2
  41. data/lib/adwords4r/v13/KeywordToolServiceMappingRegistry.rb +37 -37
  42. data/lib/adwords4r/v13/ReportService.rb +13 -13
  43. data/lib/adwords4r/v13/ReportServiceDriver.rb +9 -7
  44. data/lib/adwords4r/v13/ReportServiceMappingRegistry.rb +54 -54
  45. data/lib/adwords4r/v13/SiteSuggestionService.rb +15 -15
  46. data/lib/adwords4r/v13/SiteSuggestionServiceDriver.rb +6 -4
  47. data/lib/adwords4r/v13/SiteSuggestionServiceMappingRegistry.rb +57 -57
  48. data/lib/adwords4r/v13/TrafficEstimatorService.rb +17 -17
  49. data/lib/adwords4r/v13/TrafficEstimatorServiceDriver.rb +6 -4
  50. data/lib/adwords4r/v13/TrafficEstimatorServiceMappingRegistry.rb +96 -96
  51. data/lib/adwords4r/v200902/AdGroupAdService.rb +2021 -0
  52. data/lib/adwords4r/v200902/AdGroupAdServiceDriver.rb +63 -0
  53. data/lib/adwords4r/v200902/AdGroupAdServiceMappingRegistry.rb +2234 -0
  54. data/lib/adwords4r/v200902/AdGroupCriterionService.rb +1209 -0
  55. data/lib/adwords4r/v200902/AdGroupCriterionServiceDriver.rb +63 -0
  56. data/lib/adwords4r/v200902/AdGroupCriterionServiceMappingRegistry.rb +1434 -0
  57. data/lib/adwords4r/v200902/AdGroupService.rb +968 -0
  58. data/lib/adwords4r/{v12/KeywordToolServiceDriver.rb → v200902/AdGroupServiceDriver.rb} +15 -13
  59. data/lib/adwords4r/v200902/AdGroupServiceMappingRegistry.rb +1114 -0
  60. data/lib/adwords4r/v200902/CampaignCriterionService.rb +741 -0
  61. data/lib/adwords4r/v200902/CampaignCriterionServiceDriver.rb +63 -0
  62. data/lib/adwords4r/v200902/CampaignCriterionServiceMappingRegistry.rb +904 -0
  63. data/lib/adwords4r/v200902/CampaignService.rb +1249 -0
  64. data/lib/adwords4r/v200902/CampaignServiceDriver.rb +63 -0
  65. data/lib/adwords4r/v200902/CampaignServiceMappingRegistry.rb +1466 -0
  66. data/lib/adwords4r/v200902/CampaignTargetService.rb +1156 -0
  67. data/lib/adwords4r/v200902/CampaignTargetServiceDriver.rb +63 -0
  68. data/lib/adwords4r/v200902/CampaignTargetServiceMappingRegistry.rb +1304 -0
  69. data/setup.rb +0 -0
  70. metadata +57 -65
  71. data/lib/adwords4r/v12/AccountService.rb +0 -215
  72. data/lib/adwords4r/v12/AccountServiceDriver.rb +0 -69
  73. data/lib/adwords4r/v12/AccountServiceMappingRegistry.rb +0 -243
  74. data/lib/adwords4r/v12/AdGroupService.rb +0 -263
  75. data/lib/adwords4r/v12/AdGroupServiceDriver.rb +0 -109
  76. data/lib/adwords4r/v12/AdGroupServiceMappingRegistry.rb +0 -280
  77. data/lib/adwords4r/v12/AdService.rb +0 -769
  78. data/lib/adwords4r/v12/AdServiceDriver.rb +0 -125
  79. data/lib/adwords4r/v12/AdServiceMappingRegistry.rb +0 -813
  80. data/lib/adwords4r/v12/CampaignService.rb +0 -498
  81. data/lib/adwords4r/v12/CampaignServiceDriver.rb +0 -133
  82. data/lib/adwords4r/v12/CampaignServiceMappingRegistry.rb +0 -642
  83. data/lib/adwords4r/v12/CriterionService.rb +0 -445
  84. data/lib/adwords4r/v12/CriterionServiceDriver.rb +0 -117
  85. data/lib/adwords4r/v12/CriterionServiceMappingRegistry.rb +0 -509
  86. data/lib/adwords4r/v12/InfoService.rb +0 -242
  87. data/lib/adwords4r/v12/InfoServiceDriver.rb +0 -109
  88. data/lib/adwords4r/v12/InfoServiceMappingRegistry.rb +0 -228
  89. data/lib/adwords4r/v12/KeywordToolService.rb +0 -205
  90. data/lib/adwords4r/v12/KeywordToolServiceMappingRegistry.rb +0 -227
  91. data/lib/adwords4r/v12/ReportService.rb +0 -322
  92. data/lib/adwords4r/v12/ReportServiceDriver.rb +0 -101
  93. data/lib/adwords4r/v12/ReportServiceMappingRegistry.rb +0 -298
  94. data/lib/adwords4r/v12/SiteSuggestionService.rb +0 -242
  95. data/lib/adwords4r/v12/SiteSuggestionServiceDriver.rb +0 -77
  96. data/lib/adwords4r/v12/SiteSuggestionServiceMappingRegistry.rb +0 -271
  97. data/lib/adwords4r/v12/TrafficEstimatorService.rb +0 -312
  98. data/lib/adwords4r/v12/TrafficEstimatorServiceDriver.rb +0 -77
  99. data/lib/adwords4r/v12/TrafficEstimatorServiceMappingRegistry.rb +0 -483
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Copyright 2009, Google Inc. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+ # This code sample illustrates how to access services from multiple API versions
18
+ # simultaneously. It gets a list of all campaigns with stats using v2009, and
19
+ # then schedules a campaign performance report for the ones with less than 10
20
+ # impressions, using v13.
21
+
22
+ require 'rubygems'
23
+ gem 'soap4r', '= 1.5.8'
24
+ require 'adwords4r'
25
+
26
+
27
+ def main()
28
+ begin
29
+ # AdWords::AdWordsCredentials.new will read a credentials file from
30
+ # ENV['HOME']/adwords.properties when called without parameters.
31
+ # The latest versioned release of the API will be assumed.
32
+ #
33
+ # Credentials for this example must be for the Sandbox environment.
34
+ # Sandbox environment credentials overview:
35
+ # http://www.google.com/apis/adwords/developer/adwords_api_sandbox.html
36
+ #
37
+ # Instead of reading them from a file, the credentials can be
38
+ # specified inline as a hash:
39
+ #
40
+ # creds = {
41
+ # 'developerToken' => 'user@domain.com++USD',
42
+ # 'useragent' => 'Sample User Agent',
43
+ # 'password' => 'password',
44
+ # 'email' => 'user@domain.com',
45
+ # 'clientEmail' => 'client_1+user@domain.com',
46
+ # 'applicationToken' => 'IGNORED',
47
+ # 'alternateUrl' => 'https://sandbox.google.com/api/adwords/v13/'
48
+ # }
49
+ # adwords = AdWords::API.new(AdWords::AdWordsCredentials.new(creds))
50
+ adwords = AdWords::API.new
51
+
52
+ # Get the v200902 campaign service and the v13 report service
53
+ campaign_srv = adwords.get_service(200902, 'Campaign')
54
+ report_srv = adwords.get_service(13, 'Report')
55
+
56
+ # Retrieve list of all campaigns with their stats for this year, via v200902
57
+ selector = AdWords::V200902::CampaignService::CampaignSelector.new
58
+ stats_selector = {
59
+ :dateRange => {
60
+ :min => {
61
+ :day => 1,
62
+ :month => 1,
63
+ :year => Time.new.year
64
+ },
65
+ :max => {
66
+ :day => 31,
67
+ :month => 12,
68
+ :year => Time.new.year
69
+ }
70
+ }
71
+ }
72
+ response = campaign_srv.get(selector)
73
+ campaigns = response.rval.entries
74
+ campaigns.each do |campaign|
75
+ puts 'Campaign id %d was successfully retrieved.' % campaign.id.id
76
+ end
77
+
78
+ # Schedule yearly campaign report for all campaigns with less than 10
79
+ # impressions, using v13
80
+ report_name = 'Campaign Report-%s' % DateTime.now.to_s
81
+ job = AdWords::V13::ReportService::DefinedReportJob.new
82
+ job.selectedReportType = 'Campaign'
83
+ job.aggregationTypes = 'Yearly'
84
+ job.name = report_name
85
+ job.selectedColumns = %w{Campaign CampaignId Clicks Impressions}
86
+ job.startDay = Time.new.year.to_s + '-01-01'
87
+ job.endDay = Time.new.year.to_s + '-01-31'
88
+ campaign_ids = []
89
+ campaigns.each do |campaign|
90
+ campaign_ids << campaign.id.id if campaign.stats.impressions < 10
91
+ end
92
+ job.campaigns = campaign_ids
93
+
94
+ # Validate the report definition to make sure it is valid.
95
+ # If it is not, an AdWords::Error::ApiError will be thrown.
96
+ report_srv.validateReportJob(job)
97
+
98
+ # Since validation passed, schedule the report.
99
+ job_id = report_srv.scheduleReportJob(job).scheduleReportJobReturn
100
+ sleep_interval = 10
101
+ puts 'Scheduled report with id %d. Now sleeping %d seconds.' %
102
+ [job_id, sleep_interval]
103
+ sleep(sleep_interval)
104
+
105
+ puts 'Waiting for report to become available for download...'
106
+ begin
107
+ # Invoke client-side method that handles waiting and downloading the
108
+ # report. This method is blocking for the calling thread.
109
+ report_data = report_srv.downloadXmlReport(job_id)
110
+ file_name = '%s.xml' % report_name # Add path to write report elsewhere.
111
+ open(file_name, 'w') {|file| file.puts(report_data)}
112
+ puts 'Report has been written to %s' % file_name
113
+ rescue AdWords::Error::Error => e
114
+ puts 'Error downloading report: %s' % e
115
+ rescue Errno::ENOENT, Errno::EACCES => e
116
+ puts 'Unable to write file: %s' % e
117
+ end
118
+
119
+ rescue Errno::ECONNRESET, SOAP::HTTPStreamError, SocketError => e
120
+ # This exception indicates a connection-level error.
121
+ # In general, it is likely to be transitory.
122
+ puts 'Connection Error: %s' % e
123
+ puts 'Source: %s' % e.backtrace.first
124
+
125
+ rescue AdWords::Error::UnknownAPICall => e
126
+ # This exception is thrown when an unknown SOAP method is invoked.
127
+ puts e
128
+ puts 'Source: %s' % e.backtrace.first
129
+
130
+ rescue AdWords::Error::ApiError => e
131
+ # This exception maps to receiving a SOAP Fault back from the service.
132
+ # The e.soap_faultstring_ex, e.code_ex, and potentially e.trigger_ex
133
+ # attributes are the most useful, but other attributes may be populated
134
+ # as well. To display all attributes, the following can be used:
135
+ #
136
+ # e.instance_variables.each do |var|
137
+ # value = e.instance_variable_get(var)
138
+ # if ! value.nil?
139
+ # puts '%s => %s' % [var, value]
140
+ # end
141
+ # end
142
+ puts 'SOAP Error: %s (code: %d)' % [e.soap_faultstring_ex, e.code_ex]
143
+ puts 'Trigger: %s' % e.trigger_ex unless e.trigger_ex.nil?
144
+ puts 'Source: %s' % e.backtrace.first
145
+
146
+ ensure
147
+ # Display API unit usage info. This data is stored as a class variable
148
+ # in the AdWords::API class and accessed via static methods.
149
+ # total_units() returns a running total of units used in the scope of the
150
+ # current program. last_units() returns the number used in the last call.
151
+ puts
152
+ puts '%d API units consumed total (%d in last call).' %
153
+ [adwords.total_units, adwords.last_units]
154
+ end
155
+ end
156
+
157
+
158
+ if __FILE__ == $0
159
+ # The adwords4r library can log all SOAP requests and responses to files.
160
+ # This is often useful for debugging purposes.
161
+ # To enable this, set the ADWORDS4R_DEBUG environement varaible to 'true'.
162
+ # This can be done either from your operating system environment or via
163
+ # code, as done below.
164
+ ENV['ADWORDS4R_DEBUG'] = 'false'
165
+
166
+ main()
167
+ end
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/ruby
2
2
  #
3
- # Copyright 2008, Google Inc. All Rights Reserved.
3
+ # Copyright 2009, Google Inc. All Rights Reserved.
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
18
18
  # using the adwords4r client library.
19
19
 
20
20
  require 'rubygems'
21
- gem 'soap4r', '>= 1.5.8'
21
+ gem 'soap4r', '= 1.5.8'
22
22
  require 'adwords4r'
23
23
 
24
24
 
@@ -38,96 +38,62 @@ def main()
38
38
  # specified inline as a hash:
39
39
  #
40
40
  # creds = {
41
- # 'developerToken' => 'user@domain.com++USD',
42
- # 'useragent' => 'Sample User Agent',
43
- # 'password' => 'password',
44
- # 'email' => 'user@domain.com',
45
- # 'clientEmail' => 'client_1+user@domain.com',
46
- # 'applicationToken' => 'IGNORED',
47
- # 'alternateUrl' => 'https://sandbox.google.com/api/adwords/v13/',
41
+ # 'developerToken' => 'user@domain.com++USD',
42
+ # 'useragent' => 'Sample User Agent',
43
+ # 'password' => 'password',
44
+ # 'email' => 'user@domain.com',
45
+ # 'clientEmail' => 'client_1+user@domain.com',
46
+ # 'applicationToken' => 'IGNORED',
47
+ # 'alternateUrl' => 'https://sandbox.google.com/api/adwords/v13/',
48
48
  # }
49
- # adwords = AdWords::API.new(AdWords::AdWordsCredentials.new(creds), 13)
50
-
49
+ # adwords = AdWords::API.new(AdWords::AdWordsCredentials.new(creds))
51
50
  adwords = AdWords::API.new
52
-
51
+
53
52
  report_name = 'Report-%s' % DateTime.now.to_s
54
-
53
+
55
54
  # The following example creates a Structure report with Keyword aggregation.
56
55
  # Because it is a Structure report, startDay and endDay values are ignored.
57
56
  # See http://www.google.com/apis/adwords/developer/ReportService.html for
58
57
  # more information about the different reports you can create.
59
-
60
- job = AdWords::DefinedReportJob.new
58
+ job = AdWords::V13::ReportService::DefinedReportJob.new
61
59
  job.selectedReportType = 'Structure'
62
60
  job.aggregationTypes = 'Keyword'
63
61
  job.name = report_name
64
62
  job.selectedColumns = %w{Campaign AdGroup Keyword KeywordTypeDisplay}
65
- job.startDay = '2008-01-01'
66
- job.endDay = '2008-01-31'
67
-
63
+ job.startDay = '2009-01-01'
64
+ job.endDay = '2009-01-31'
65
+
66
+ report_srv = adwords.get_service(13, 'Report')
68
67
  # Validate the report definition to make sure it is valid.
69
68
  # If it is not, an AdWords::Error::ApiError will be thrown.
69
+ report_srv.validateReportJob(job)
70
70
 
71
- adwords.validateReportJob(job)
72
-
73
71
  # Since validation passed, schedule the report.
74
-
75
- job_id = adwords.scheduleReportJob(job).scheduleReportJobReturn
72
+ job_id = report_srv.scheduleReportJob(job).scheduleReportJobReturn
76
73
  sleep_interval = 10
77
74
  puts 'Scheduled report with id %d. Now sleeping %d seconds.' %
78
- [job_id, sleep_interval]
75
+ [job_id, sleep_interval]
79
76
  sleep(sleep_interval)
80
-
81
- # Repeatedly check the report status until it is finished.
82
- # 'Pending' and 'InProgress' statuses indicate the job is still being run.
83
-
84
- status = adwords.getReportJobStatus(job_id).getReportJobStatusReturn
85
- while status != 'Completed' && status != 'Failed'
86
- puts 'Report status is %s. Now sleeping another %d seconds.' %
87
- [status, sleep_interval]
88
- sleep(sleep_interval)
89
- status = adwords.getReportJobStatus(job_id).getReportJobStatusReturn
90
- end
91
-
92
- if status == 'Completed'
93
- report_url = adwords.getReportDownloadUrl(job_id).
94
- getReportDownloadUrlReturn
95
- puts 'Report is completed. Downloading report from %s' % report_url
96
-
97
- # Download the report via the HTTPClient library and write it to disk.
98
- # The report is an XML document; the actual element names vary depending
99
- # on what type of report run and columns requested.
100
77
 
101
- client = HTTPClient.new
102
- report_data = client.get_content(report_url)
78
+ puts 'Waiting for report to become available for download...'
79
+ begin
80
+ # Invoke client-side method that handles waiting and downloading the
81
+ # report. This method is blocking for the calling thread.
82
+ report_data = report_srv.downloadXmlReport(job_id)
103
83
  file_name = '%s.xml' % report_name # Add path to write report elsewhere.
104
- begin
105
- open(file_name, 'w') {|file| file.puts(report_data)}
106
- puts 'Report has been written to %s' % file_name
107
-
108
- rescue Errno::ENOENT, Errno::EACCES => e
109
- puts 'Unable to write file: %s' % e
110
- end
111
- else
112
- # Reports that pass validation will normally not fail, but if there is
113
- # an error in the report generation service it can sometimes happen.
114
-
115
- puts 'Report generation failed.'
84
+ open(file_name, 'w') {|file| file.puts(report_data)}
85
+ puts 'Report has been written to %s' % file_name
86
+ rescue AdWords::Error::Error => e
87
+ puts 'Error downloading report: %s' % e
88
+ rescue Errno::ENOENT, Errno::EACCES => e
89
+ puts 'Unable to write file: %s' % e
116
90
  end
117
-
118
- rescue Errno::ECONNRESET, SOAP::HTTPStreamError, SocketError => e
119
- # This exception indicates a connection-level error.
120
- # In general, it is likely to be transitory.
121
91
 
122
- puts 'Connection Error: %s' % e
123
- puts 'Source: %s' % e.backtrace.first
124
-
125
92
  rescue AdWords::Error::UnknownAPICall => e
126
93
  # This exception is thrown when an unknown SOAP method is invoked.
127
-
128
94
  puts e
129
95
  puts 'Source: %s' % e.backtrace.first
130
-
96
+
131
97
  rescue AdWords::Error::ApiError => e
132
98
  # This exception maps to receiving a SOAP Fault back from the service.
133
99
  # The e.soap_faultstring_ex, e.code_ex, and potentially e.trigger_ex
@@ -140,21 +106,18 @@ def main()
140
106
  # puts '%s => %s' % [var, value]
141
107
  # end
142
108
  # end
143
-
144
109
  puts 'SOAP Error: %s (code: %d)' % [e.soap_faultstring_ex, e.code_ex]
145
110
  puts 'Trigger: %s' % e.trigger_ex unless e.trigger_ex.nil?
146
111
  puts 'Source: %s' % e.backtrace.first
147
112
 
148
113
  ensure
149
- # Display API unit usage information. This data is stored as a class
150
- # variable in the AdWords::API class and accessed via static methods.
151
- # AdWords::API.get_total_units() returns a running total of units used in
152
- # the scope of the current program.
153
- # AdWords::API.get_last_units() returns the number used in the last call.
154
-
114
+ # Display API unit usage info. This data is stored as a class variable
115
+ # in the AdWords::API class and accessed via static methods.
116
+ # total_units() returns a running total of units used in the scope of the
117
+ # current program. last_units() returns the number used in the last call.
155
118
  puts
156
119
  puts '%d API units consumed total (%d in last call).' %
157
- [AdWords::API.get_total_units(), AdWords::API.get_last_units()]
120
+ [adwords.total_units, adwords.last_units]
158
121
  end
159
122
  end
160
123
 
@@ -165,7 +128,6 @@ if __FILE__ == $0
165
128
  # To enable this, set the ADWORDS4R_DEBUG environement varaible to 'true'.
166
129
  # This can be done either from your operating system environment or via
167
130
  # code, as done below.
168
-
169
131
  ENV['ADWORDS4R_DEBUG'] = 'false'
170
132
 
171
133
  main()
@@ -1,129 +1,107 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Copyright 2009, Google Inc. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # Contains the main classes for the client library.
18
+
1
19
  require 'rubygems'
2
20
  begin
3
- gem 'soap4r'
21
+ gem 'soap4r', '=1.5.8'
4
22
  rescue
5
- require_gem 'soap4r'
23
+ require_gem 'soap4r', '=1.5.8'
6
24
  end
7
- require 'soap/soap'
8
- require 'soap/mapping'
9
- require 'soap/rpc/driver'
25
+ require 'thread'
26
+ require 'uri'
27
+ require 'adwords4r/soap4rpatches'
10
28
  require 'adwords4r/credentials'
11
29
  require 'adwords4r/services'
12
-
13
- # Fix an issue with SOAPDate. Google complains if the dates have any timezone
14
- # info in them. There are probably better ways to fix this.
15
- module SOAP
16
- class SOAPDate
17
- def of2tz(offset)
18
- diffmin = offset * 24 * 60
19
- if diffmin.zero?
20
- ''
21
- else
22
- ((diffmin < 0) ? '-' : '+') << format('%02d:%02d',
23
- (diffmin.abs / 60.0).to_i, (diffmin.abs % 60.0).to_i)
24
- end
25
- end
26
- end
27
- end
30
+ require 'adwords4r/adwordslogger'
31
+ require 'adwords4r/apiextensions'
28
32
 
29
33
  module AdWords
30
-
34
+
35
+ # Wrapper class that serves as the main point of access for all the API usage
31
36
  class API
32
37
 
33
- @@total_units = 0
34
- @@last_units = 0
38
+ attr_reader :credentials, :drivers, :xml_logger, :unit_logger, :mutex
39
+ attr_accessor :last_units, :total_units
35
40
 
36
- def API.add_total_units(increment)
37
- @@total_units += increment
38
- end
39
-
40
- def API.get_total_units()
41
- return @@total_units
42
- end
43
-
44
- def API.set_last_units(value)
45
- @@last_units = value
46
- end
47
-
48
- def API.get_last_units()
49
- return @@last_units
50
- end
51
-
52
- attr_reader :credentials, :drivers, :version
53
- @methodMap = Hash.new
54
-
55
- def initialize(credentials = AdWordsCredentials.new,
56
- version = Service.getVersions.sort.last)
57
- @credentials, @version = credentials, version
58
- @drivers = Hash.new
59
- prepareDrivers
60
- end
41
+ public
61
42
 
62
- def method_missing(m, *args)
63
- methodName = m.id2name
64
- requestName = AdWords::fix_case_up(m.id2name) # upper first character
65
- if valid_call?(methodName)
66
- driver = getDriver(methodName)
67
- moduleName = driver.class.name.split("::")[0..-2].join("::")
68
- constructor = eval("#{moduleName}::#{requestName}.method('new')")
69
- req = constructor.call(*args)
70
- return driver.send(methodName, req)
71
- else
72
- raise(Error::UnknownAPICall, "Unknown API Call: #{requestName}", caller)
43
+ def initialize(credentials = AdWordsCredentials.new)
44
+ @credentials = credentials
45
+ @drivers = Hash.new
46
+ @wrappers = Hash.new
47
+ @total_units = 0
48
+ @last_units = 0
49
+ log_to_console = !ENV['ADWORDS4R_DEBUG'].nil? &&
50
+ ENV['ADWORDS4R_DEBUG'].upcase == 'TRUE'
51
+ @xml_logger = AdWordsLogger.new('soap_xml', log_to_console)
52
+ @unit_logger = AdWordsLogger.new('request_info')
53
+ @mutex = Mutex.new
54
+ prepare_drivers
55
+ end
56
+
57
+ # Returns a service, given a version and its name. nil if not found.
58
+ def get_service(version, name)
59
+ return @wrappers[[version, name]]
60
+ end
61
+
62
+ private
63
+
64
+ # Load all drivers and place them in a Hash, with version and name as key
65
+ def prepare_drivers()
66
+ Service.get_versions().each do |v|
67
+ Service.do_require(v)
68
+ Service.get_services(v).each do |s|
69
+ @drivers[[v, s]], @wrappers[[v, s]] = prepare_driver(v, s)
70
+ end
73
71
  end
74
- # Handle AdWords Application-level error
75
- rescue SOAP::FaultError => fault
76
- raise(Error::ApiError.new(fault),
77
- "#{methodName} Call Failed: #{fault.faultstring.to_s}", caller)
78
- end
79
-
80
- def prepareDrivers()
81
- Service.doRequire(@version)
82
- Service.getServices(@version).each {|s| @drivers[s] = prepareDriver(s)}
83
- @methodMap = Service.getMethodMap(@drivers)
84
72
  end
85
73
 
86
- #pass in call name, get the driver back
87
- def getDriver(call)
88
- return @methodMap[call]
89
- end
90
-
91
- def prepareDriver(s)
92
- # Include the module for this service
93
- AdWords.class_eval("include #{s}Service")
94
-
95
- #set alternateurl if it has been set in credentials
96
- if (@credentials.alternateUrl) then
74
+ def prepare_driver(v, s)
75
+ # Set alternateurl if it has been set in credentials
76
+ if (@credentials.alternateUrl and v <= 13) then
97
77
  endpointUrl = @credentials.alternateUrl + s + 'Service'
98
- driver = eval("AdWords::#{getServiceName(s)}.new(\"#{endpointUrl}\")")
78
+ driver =
79
+ eval("#{Service.get_interface_name(v, s)}.new(\"#{endpointUrl}\")")
99
80
  elsif
100
- driver = eval("AdWords::#{getServiceName(s)}.new")
81
+ driver = eval("#{Service.get_interface_name(v, s)}.new")
101
82
  end
102
- @credentials.handlers.each {|h| driver.headerhandler << h}
103
-
104
- # Add response filter to this driver for API unit usage processing.
105
- driver.filterchain << ResponseFilter.new
106
-
107
- if !ENV['ADWORDS4R_DEBUG'].nil? && ENV['ADWORDS4R_DEBUG'].upcase == 'TRUE'
108
- driver.wiredump_file_base = "SOAP_#{$$}"
83
+ @credentials.get_handlers(v).each do |handler|
84
+ driver.headerhandler << handler
109
85
  end
110
86
 
87
+ # Add response handler to this driver for API unit usage processing.
88
+ driver.callbackhandler = ResponseHandler.new(self)
89
+ # Plug the wiredump to our XML logger
90
+ driver.wiredump_dev = @xml_logger
111
91
  driver.options['protocol.http.ssl_config.verify_mode'] = nil
112
- #set driver.proxy if you are behing a proxy
113
- return driver
114
- end
92
+ # NOTE: Set driver.proxy if you are behing a proxy
115
93
 
116
- def getServiceName(s)
117
- s + "Interface"
94
+ # Generate wrapper class for this driver
95
+ Service.generate_wrapper_class(v, s)
96
+ # and create an instance of it
97
+ wrapper = eval("#{Service.get_wrapper_name(v, s)}.new(driver)")
98
+ return driver, wrapper
118
99
  end
119
-
120
- def valid_call?(call)
121
- return @methodMap.has_key?(call)
122
- end
123
-
124
100
  end
125
101
 
102
+ # Error class to wrap several error types in Ruby objects
126
103
  class Error
104
+
127
105
  class Error < StandardError; end
128
106
 
129
107
  # Raised if a call is made to a method that does not exist
@@ -134,9 +112,14 @@ module AdWords
134
112
  # in the AdWords SOAP API
135
113
  class UnknownType < Error; end
136
114
 
115
+ # Raised if an attempt is made to authenticate in >= v200902 with missing or
116
+ # wrong information
117
+ class AuthError < Error; end
118
+
137
119
  # Raised if a call returns with a SOAP error,
138
120
  # gives you easy access to adwords error fields
139
121
  class ApiError < Error
122
+
140
123
  attr_accessor :soap_faultcode
141
124
  attr_accessor :soap_faultstring
142
125
  attr_accessor :top_code
@@ -150,7 +133,7 @@ module AdWords
150
133
  attr_accessor :textIndex
151
134
  attr_accessor :textLength
152
135
  attr_accessor :trigger
153
-
136
+
154
137
  # These *_ex attributes have been added to correct deficiencies with the
155
138
  # initial implementation.
156
139
  # They should expose more useful information (i.e. text of errors instead
@@ -189,6 +172,7 @@ module AdWords
189
172
  end
190
173
 
191
174
  private
175
+
192
176
  def protect(&block)
193
177
  begin
194
178
  block.call
@@ -199,33 +183,49 @@ module AdWords
199
183
  end
200
184
  end
201
185
 
202
- # SOAP filter to process response messages for API unit usage information.
203
- class ResponseFilter < SOAP::Filter::Handler
204
- def on_inbound(xml, opt)
205
- # Parse the response XML string for the <operations> header value.
206
- if xml =~ %r{<units.+?>(\d+)</units>}
207
- units = $1.to_i
208
- # Since we don't really have an instance of a useful class here,
209
- # we're stuck sticking the value in a class variable for AdWords::API.
210
- AdWords::API.set_last_units(units)
211
- AdWords::API.add_total_units(units)
212
- end
186
+ # Handler class to process response messages for API unit usage and statistics
187
+ # information.
188
+ class ResponseHandler < SOAP::RPC::CallbackHandler
213
189
 
214
- return xml
190
+ def initialize(parent)
191
+ @parent = parent
215
192
  end
216
- end
217
193
 
218
- # These class module methods are helper functions
219
- class <<self
194
+ def on_callback(method_name, endpoint, envelope)
195
+ units = nil
196
+ operations = nil
197
+ response_time = nil
198
+ request_id = nil
220
199
 
221
- def fix_case_up(name)
222
- name[0] = name[0, 1].upcase # upper first character
223
- name
224
- end
200
+ header = envelope.header
225
201
 
226
- def fix_case_down(name)
227
- name[0] = name[0, 1].downcase
228
- name
202
+ @parent.mutex.synchronize do
203
+ unless header['units'].nil?
204
+ units = header['units'].element.text.to_i
205
+ @parent.last_units = units
206
+ @parent.total_units = @parent.total_units + units
207
+ end
208
+
209
+ unless header['operations'].nil?
210
+ operations = header['operations'].element.text.to_i
211
+ end
212
+
213
+ unless header['responseTime'].nil?
214
+ response_time = header['responseTime'].element.text.to_i
215
+ end
216
+
217
+ unless header['requestId'].nil?
218
+ request_id = header['requestId'].element.text.to_s
219
+ end
220
+
221
+ host = URI.parse(endpoint).host
222
+
223
+ data = "host=#{host} method=#{method_name} " +
224
+ "responseTime=#{response_time} operations=#{operations} " +
225
+ "units=#{units} requestId=#{request_id}"
226
+
227
+ @parent.unit_logger << data
228
+ end
229
229
  end
230
230
  end
231
231
  end