google-adwords-api 1.5.0 → 1.6.0
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 +4 -4
- data/COPYING +0 -0
- data/ChangeLog +4 -0
- data/README.md +9 -236
- data/lib/adwords_api.rb +2 -234
- metadata +8 -134
- data/adwords_api.yml +0 -53
- data/lib/adwords_api/api_config.rb +0 -221
- data/lib/adwords_api/batch_job_utils.rb +0 -334
- data/lib/adwords_api/credential_handler.rb +0 -96
- data/lib/adwords_api/errors.rb +0 -110
- data/lib/adwords_api/incremental_upload_helper.rb +0 -75
- data/lib/adwords_api/query_utils/query_builder.rb +0 -41
- data/lib/adwords_api/query_utils/report_query.rb +0 -30
- data/lib/adwords_api/query_utils/report_query_builder.rb +0 -82
- data/lib/adwords_api/query_utils/service_query.rb +0 -62
- data/lib/adwords_api/query_utils/service_query_builder.rb +0 -83
- data/lib/adwords_api/query_utils/where_builder.rb +0 -97
- data/lib/adwords_api/report_header_handler.rb +0 -80
- data/lib/adwords_api/report_stream.rb +0 -70
- data/lib/adwords_api/report_utils.rb +0 -383
- data/lib/adwords_api/utils.rb +0 -56
- data/lib/adwords_api/utils_reporter.rb +0 -58
- data/lib/adwords_api/v201809/account_label_service.rb +0 -46
- data/lib/adwords_api/v201809/account_label_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/ad_customizer_feed_service.rb +0 -46
- data/lib/adwords_api/v201809/ad_customizer_feed_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/ad_group_ad_service.rb +0 -62
- data/lib/adwords_api/v201809/ad_group_ad_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/ad_group_bid_modifier_service.rb +0 -54
- data/lib/adwords_api/v201809/ad_group_bid_modifier_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/ad_group_criterion_service.rb +0 -62
- data/lib/adwords_api/v201809/ad_group_criterion_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/ad_group_extension_setting_service.rb +0 -54
- data/lib/adwords_api/v201809/ad_group_extension_setting_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/ad_group_feed_service.rb +0 -54
- data/lib/adwords_api/v201809/ad_group_feed_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/ad_group_service.rb +0 -62
- data/lib/adwords_api/v201809/ad_group_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/ad_param_service.rb +0 -46
- data/lib/adwords_api/v201809/ad_param_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/ad_service.rb +0 -46
- data/lib/adwords_api/v201809/ad_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/adwords_user_list_service.rb +0 -62
- data/lib/adwords_api/v201809/adwords_user_list_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/asset_service.rb +0 -46
- data/lib/adwords_api/v201809/asset_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/batch_job_service.rb +0 -54
- data/lib/adwords_api/v201809/batch_job_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/bidding_strategy_service.rb +0 -54
- data/lib/adwords_api/v201809/bidding_strategy_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/budget_order_service.rb +0 -54
- data/lib/adwords_api/v201809/budget_order_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/budget_service.rb +0 -54
- data/lib/adwords_api/v201809/budget_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/campaign_bid_modifier_service.rb +0 -54
- data/lib/adwords_api/v201809/campaign_bid_modifier_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/campaign_criterion_service.rb +0 -54
- data/lib/adwords_api/v201809/campaign_criterion_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/campaign_extension_setting_service.rb +0 -54
- data/lib/adwords_api/v201809/campaign_extension_setting_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/campaign_feed_service.rb +0 -54
- data/lib/adwords_api/v201809/campaign_feed_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/campaign_group_performance_target_service.rb +0 -46
- data/lib/adwords_api/v201809/campaign_group_performance_target_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/campaign_group_service.rb +0 -46
- data/lib/adwords_api/v201809/campaign_group_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/campaign_service.rb +0 -62
- data/lib/adwords_api/v201809/campaign_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/campaign_shared_set_service.rb +0 -54
- data/lib/adwords_api/v201809/campaign_shared_set_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/constant_data_service.rb +0 -110
- data/lib/adwords_api/v201809/constant_data_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/conversion_tracker_service.rb +0 -54
- data/lib/adwords_api/v201809/conversion_tracker_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/custom_affinity_service.rb +0 -62
- data/lib/adwords_api/v201809/custom_affinity_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/customer_extension_setting_service.rb +0 -54
- data/lib/adwords_api/v201809/customer_extension_setting_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/customer_feed_service.rb +0 -54
- data/lib/adwords_api/v201809/customer_feed_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/customer_negative_criterion_service.rb +0 -54
- data/lib/adwords_api/v201809/customer_negative_criterion_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/customer_service.rb +0 -62
- data/lib/adwords_api/v201809/customer_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/customer_sync_service.rb +0 -38
- data/lib/adwords_api/v201809/customer_sync_service_registry.rb +0 -47
- data/lib/adwords_api/v201809/data_service.rb +0 -94
- data/lib/adwords_api/v201809/data_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/draft_async_error_service.rb +0 -46
- data/lib/adwords_api/v201809/draft_async_error_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/draft_service.rb +0 -54
- data/lib/adwords_api/v201809/draft_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/feed_item_service.rb +0 -54
- data/lib/adwords_api/v201809/feed_item_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/feed_item_target_service.rb +0 -54
- data/lib/adwords_api/v201809/feed_item_target_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/feed_mapping_service.rb +0 -54
- data/lib/adwords_api/v201809/feed_mapping_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/feed_service.rb +0 -54
- data/lib/adwords_api/v201809/feed_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/label_service.rb +0 -54
- data/lib/adwords_api/v201809/label_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/location_criterion_service.rb +0 -46
- data/lib/adwords_api/v201809/location_criterion_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/managed_customer_service.rb +0 -78
- data/lib/adwords_api/v201809/managed_customer_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/media_service.rb +0 -54
- data/lib/adwords_api/v201809/media_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/offline_call_conversion_feed_service.rb +0 -38
- data/lib/adwords_api/v201809/offline_call_conversion_feed_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/offline_conversion_adjustment_feed_service.rb +0 -38
- data/lib/adwords_api/v201809/offline_conversion_adjustment_feed_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/offline_conversion_feed_service.rb +0 -38
- data/lib/adwords_api/v201809/offline_conversion_feed_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/offline_data_upload_service.rb +0 -46
- data/lib/adwords_api/v201809/offline_data_upload_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/report_definition_service.rb +0 -38
- data/lib/adwords_api/v201809/report_definition_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/shared_criterion_service.rb +0 -54
- data/lib/adwords_api/v201809/shared_criterion_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/shared_set_service.rb +0 -54
- data/lib/adwords_api/v201809/shared_set_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/targeting_idea_service.rb +0 -38
- data/lib/adwords_api/v201809/targeting_idea_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/traffic_estimator_service.rb +0 -38
- data/lib/adwords_api/v201809/traffic_estimator_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/trial_async_error_service.rb +0 -46
- data/lib/adwords_api/v201809/trial_async_error_service_registry.rb +0 -46
- data/lib/adwords_api/v201809/trial_service.rb +0 -54
- data/lib/adwords_api/v201809/trial_service_registry.rb +0 -46
- data/lib/adwords_api/version.rb +0 -24
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
# Encoding: utf-8
|
|
2
|
-
#
|
|
3
|
-
# Copyright:: Copyright 2015, Google Inc. All Rights Reserved.
|
|
4
|
-
#
|
|
5
|
-
# License:: 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
|
|
14
|
-
# implied.
|
|
15
|
-
# See the License for the specific language governing permissions and
|
|
16
|
-
# limitations under the License.
|
|
17
|
-
#
|
|
18
|
-
# Contains utility methods specific to using the BatchJobService.
|
|
19
|
-
|
|
20
|
-
require 'nokogiri'
|
|
21
|
-
require 'nori'
|
|
22
|
-
|
|
23
|
-
require 'ads_common/http'
|
|
24
|
-
require 'ads_common/savon_service'
|
|
25
|
-
require 'adwords_api/errors'
|
|
26
|
-
require 'adwords_api/incremental_upload_helper'
|
|
27
|
-
|
|
28
|
-
module AdwordsApi
|
|
29
|
-
class BatchJobUtils
|
|
30
|
-
# Default constructor.
|
|
31
|
-
#
|
|
32
|
-
# Args:
|
|
33
|
-
# - api: AdwordsApi object
|
|
34
|
-
# - version: API version to use
|
|
35
|
-
#
|
|
36
|
-
def initialize(api, version)
|
|
37
|
-
@api, @version = api, version
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Uploads the given operations for a batch job to the provided URL.
|
|
41
|
-
#
|
|
42
|
-
# Args:
|
|
43
|
-
# - hash_operations: An array of ruby has operations to execute by
|
|
44
|
-
# posting them to the provided URL
|
|
45
|
-
# - service_name: The name of the AdwordsApi service as a symbol that would
|
|
46
|
-
# normally make this request
|
|
47
|
-
# - batch_job_url: The UploadURL provided by BatchJobService
|
|
48
|
-
#
|
|
49
|
-
# Raises:
|
|
50
|
-
# - InvalidBatchJobOperationError: If there is a problem converting the
|
|
51
|
-
# given operations to SOAP.
|
|
52
|
-
#
|
|
53
|
-
def upload_operations(operations, batch_job_url)
|
|
54
|
-
helper = start_incremental_upload(batch_job_url)
|
|
55
|
-
helper.upload(operations, true)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Provides a helper to manage incremental uploads.
|
|
59
|
-
#
|
|
60
|
-
# Args:
|
|
61
|
-
# - batch_job_url: The UploadURL provided by BatchJobService for new jobs,
|
|
62
|
-
# or the upload_url from IncrementalUploadHelper for continued jobs.
|
|
63
|
-
# - uploaded_bytes: The number of bytes already uploaded for this
|
|
64
|
-
# incremental batch job. Can be retrieved from the IncrementalUploadHelper
|
|
65
|
-
# using uploaded_bytes.
|
|
66
|
-
#
|
|
67
|
-
# Returns:
|
|
68
|
-
# - an IncrementalUploadHelper that will accept operations and put them,
|
|
69
|
-
# keeping track of uploaded bytes automatically.
|
|
70
|
-
#
|
|
71
|
-
def start_incremental_upload(batch_job_url, uploaded_bytes = 0)
|
|
72
|
-
return AdwordsApi::IncrementalUploadHelper.new(
|
|
73
|
-
self, uploaded_bytes, batch_job_url)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Initializes an upload URL to get the actual URL to which to upload
|
|
77
|
-
# operations.
|
|
78
|
-
#
|
|
79
|
-
# Args:
|
|
80
|
-
# - batch_job_url: The UploadURL provided by BatchJobService
|
|
81
|
-
#
|
|
82
|
-
# Returns:
|
|
83
|
-
# - The URL that should actually be used to upload operations.
|
|
84
|
-
#
|
|
85
|
-
def initialize_url(batch_job_url)
|
|
86
|
-
headers = DEFAULT_HEADERS
|
|
87
|
-
headers['Content-Length'] = 0
|
|
88
|
-
headers['x-goog-resumable'] = 'start'
|
|
89
|
-
|
|
90
|
-
response = AdsCommon::Http.post_response(
|
|
91
|
-
batch_job_url, '', @api.config, headers)
|
|
92
|
-
|
|
93
|
-
return response.headers['Location']
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# Puts the provided operations to the provided URL, allowing
|
|
97
|
-
# for incremental followup puts.
|
|
98
|
-
#
|
|
99
|
-
# Args:
|
|
100
|
-
# - soap_operations: An array including SOAP operations provided by
|
|
101
|
-
# generate_soap_operations
|
|
102
|
-
# - batch_job_url: The UploadURL provided by BatchJobService
|
|
103
|
-
# - total_content_length: The total number of bytes already uploaded
|
|
104
|
-
# incrementally. Set this to 0 the first time you call the method.
|
|
105
|
-
# - is_last_request: Whether or not this set of uploads will conclude the
|
|
106
|
-
# full request.
|
|
107
|
-
#
|
|
108
|
-
# Returns:
|
|
109
|
-
# - total content length, including what was just uploaded. Pass this back
|
|
110
|
-
# into this method on subsequent calls.
|
|
111
|
-
def put_incremental_operations(
|
|
112
|
-
operations, batch_job_url, total_content_length = 0,
|
|
113
|
-
is_last_request = false)
|
|
114
|
-
@api.utils_reporter.batch_job_utils_used()
|
|
115
|
-
headers = DEFAULT_HEADERS
|
|
116
|
-
soap_operations = generate_soap_operations(operations)
|
|
117
|
-
request_body = soap_operations.join
|
|
118
|
-
is_first_request = (total_content_length == 0)
|
|
119
|
-
|
|
120
|
-
if is_first_request
|
|
121
|
-
request_body = (UPLOAD_XML_PREFIX % [@version]) + request_body
|
|
122
|
-
end
|
|
123
|
-
if is_last_request
|
|
124
|
-
request_body += UPLOAD_XML_SUFFIX
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
request_body = add_padding(request_body)
|
|
128
|
-
content_length = request_body.bytesize
|
|
129
|
-
|
|
130
|
-
headers['Content-Length'] = content_length
|
|
131
|
-
|
|
132
|
-
lower_bound = total_content_length
|
|
133
|
-
upper_bound = total_content_length + content_length - 1
|
|
134
|
-
total_bytes = is_last_request ? upper_bound + 1 : '*'
|
|
135
|
-
content_range =
|
|
136
|
-
"bytes %d-%d/%s" % [lower_bound, upper_bound, total_bytes]
|
|
137
|
-
|
|
138
|
-
headers['Content-Range'] = content_range
|
|
139
|
-
|
|
140
|
-
log_request(batch_job_url, headers, request_body)
|
|
141
|
-
|
|
142
|
-
# The HTTPI library fails to handle the response when uploading
|
|
143
|
-
# incremental requests. We're not interested in the response, so just
|
|
144
|
-
# ignore the error.
|
|
145
|
-
begin
|
|
146
|
-
AdsCommon::Http.put_response(
|
|
147
|
-
batch_job_url, request_body, @api.config, headers)
|
|
148
|
-
rescue ArgumentError
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
total_content_length += content_length
|
|
152
|
-
return total_content_length
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
# Downloads the results of a batch job from the specified URL.
|
|
156
|
-
#
|
|
157
|
-
# Args:
|
|
158
|
-
# - batch_job_url: The URL provided by BatchJobService to fetch the results
|
|
159
|
-
# from
|
|
160
|
-
#
|
|
161
|
-
# Returns:
|
|
162
|
-
# - the results of the batch job, as a ruby hash, or nil if none yet exist
|
|
163
|
-
#
|
|
164
|
-
def get_job_results(batch_job_url)
|
|
165
|
-
@api.utils_reporter.batch_job_utils_used()
|
|
166
|
-
xml_response = AdsCommon::Http.get_response(batch_job_url, @api.config)
|
|
167
|
-
begin
|
|
168
|
-
return sanitize_result(
|
|
169
|
-
get_nori().parse(xml_response.body)[:mutate_response][:rval])
|
|
170
|
-
rescue
|
|
171
|
-
return nil
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
private
|
|
176
|
-
|
|
177
|
-
# For incremental uploads, the size (in bytes) of the body of the request
|
|
178
|
-
# must be in multiples of 256k.
|
|
179
|
-
REQUIRED_CONTENT_LENGTH_INCREMENT = 256 * 1024
|
|
180
|
-
|
|
181
|
-
UPLOAD_XML_PREFIX = '<?xml version="1.0" encoding="UTF-8"?><ns1:mutate ' +
|
|
182
|
-
'xmlns:ns1="https://adwords.google.com/api/adwords/cm/%s">'
|
|
183
|
-
UPLOAD_XML_SUFFIX = '</ns1:mutate>'
|
|
184
|
-
DEFAULT_HEADERS = {"Content-Type" => "application/xml"}
|
|
185
|
-
|
|
186
|
-
SERVICES_BY_OPERATION_TYPE = {
|
|
187
|
-
'AdGroupAdOperation' => :AdGroupAdService,
|
|
188
|
-
'AdGroupAdLabelOperation' => :AdGroupAdService,
|
|
189
|
-
'AdGroupBidModifierOperation' => :AdGroupBidModifierService,
|
|
190
|
-
'AdGroupCriterionOperation' => :AdGroupCriterionService,
|
|
191
|
-
'AdGroupCriterionLabelOperation' => :AdGroupCriterionService,
|
|
192
|
-
'AdGroupExtensionSettingOperation' => :AdGroupExtensionSettingService,
|
|
193
|
-
'AdGroupOperation' => :AdGroupService,
|
|
194
|
-
'AdGroupLabelOperation' => :AdGroupService,
|
|
195
|
-
'BudgetOperation' => :BudgetService,
|
|
196
|
-
'CampaignCriterionOperation' => :CampaignCriterionService,
|
|
197
|
-
'CampaignExtensionSettingOperation' => :CampaignExtensionSettingService,
|
|
198
|
-
'CampaignLabelOperation' => :CampaignService,
|
|
199
|
-
'CampaignOperation' => :CampaignService,
|
|
200
|
-
'CampaignSharedSetOperation' => :CampaignSharedSetService,
|
|
201
|
-
'CustomerExtensionSettingOperation' => :CustomerExtensionSettingService,
|
|
202
|
-
'FeedItemOperation' => :FeedItemService,
|
|
203
|
-
'FeedItemTargetOperation' => :FeedItemTargetService,
|
|
204
|
-
'SharedCriterionOperation' => :SharedCriterionService,
|
|
205
|
-
'SharedSetOperation' => :SharedSetService
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
METHODS_BY_OPERATION_TYPE = {
|
|
209
|
-
'AdGroupAdOperation' => 'mutate_to_xml',
|
|
210
|
-
'AdGroupAdLabelOperation' => 'mutate_label_to_xml',
|
|
211
|
-
'AdGroupBidModifierOperation' => 'mutate_to_xml',
|
|
212
|
-
'AdGroupCriterionOperation' => 'mutate_to_xml',
|
|
213
|
-
'AdGroupCriterionLabelOperation' => 'mutate_label_to_xml',
|
|
214
|
-
'AdGroupExtensionSettingOperation' => 'mutate_to_xml',
|
|
215
|
-
'AdGroupOperation' => 'mutate_to_xml',
|
|
216
|
-
'AdGroupLabelOperation' => 'mutate_label_to_xml',
|
|
217
|
-
'BudgetOperation' => 'mutate_to_xml',
|
|
218
|
-
'CampaignCriterionOperation' => 'mutate_to_xml',
|
|
219
|
-
'CampaignExtensionSettingOperation' => 'mutate_to_xml',
|
|
220
|
-
'CampaignLabelOperation' => 'mutate_label_to_xml',
|
|
221
|
-
'CampaignOperation' => 'mutate_to_xml',
|
|
222
|
-
'CampaignSharedSetOperation' => 'mutate_to_xml',
|
|
223
|
-
'CustomerExtensionSettingOperation' => 'mutate_to_xml',
|
|
224
|
-
'FeedItemOperation' => 'mutate_to_xml',
|
|
225
|
-
'FeedItemTargetOperation' => 'mutate_to_xml',
|
|
226
|
-
'SharedCriterionOperation' => 'mutate_to_xml',
|
|
227
|
-
'SharedSetOperation' => 'mutate_to_xml'
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
def generate_soap_operations(hash_operations)
|
|
231
|
-
unless hash_operations.is_a?(Array)
|
|
232
|
-
raise AdwordsApi::Errors::InvalidBatchJobOperationError,
|
|
233
|
-
'Operations must be in an array.'
|
|
234
|
-
end
|
|
235
|
-
return hash_operations.map do |operation|
|
|
236
|
-
operation_type = operation[:xsi_type]
|
|
237
|
-
if operation_type.nil?
|
|
238
|
-
raise AdwordsApi::Errors::InvalidBatchJobOperationError,
|
|
239
|
-
':xsi_type for operations must be defined ' +
|
|
240
|
-
'explicitly for batch jobs.'
|
|
241
|
-
end
|
|
242
|
-
service_name = SERVICES_BY_OPERATION_TYPE[operation_type]
|
|
243
|
-
if service_name.nil?
|
|
244
|
-
raise AdwordsApi::Errors::InvalidBatchJobOperationError,
|
|
245
|
-
'Unknown operation type: %s' % operation_type
|
|
246
|
-
end
|
|
247
|
-
method_name = METHODS_BY_OPERATION_TYPE[operation_type]
|
|
248
|
-
service = @api.service(service_name, @version)
|
|
249
|
-
full_soap_xml = service.send(method_name, [operation])
|
|
250
|
-
operation_xml = extract_soap_operations(full_soap_xml)
|
|
251
|
-
operation_xml
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
# Given a full SOAP xml string, extract just the operations element
|
|
256
|
-
# from the SOAP body as a string.
|
|
257
|
-
def extract_soap_operations(full_soap_xml)
|
|
258
|
-
doc = Nokogiri::XML(full_soap_xml)
|
|
259
|
-
operations = doc.css('wsdl|operations')
|
|
260
|
-
operations.attr('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance')
|
|
261
|
-
operations.each do |element|
|
|
262
|
-
check_xsi_type(element)
|
|
263
|
-
end
|
|
264
|
-
return operations.to_s
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
def check_xsi_type(xml_node)
|
|
268
|
-
xsi_type = xml_node['xsi:type']
|
|
269
|
-
unless xsi_type.nil? or xsi_type.start_with?('ns1:')
|
|
270
|
-
xml_node['xsi:type'] = 'ns1:' + xsi_type
|
|
271
|
-
end
|
|
272
|
-
children = xml_node.children
|
|
273
|
-
unless children.empty?
|
|
274
|
-
children.each do |element|
|
|
275
|
-
check_xsi_type(element)
|
|
276
|
-
end
|
|
277
|
-
end
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
# Logs the request on debug level.
|
|
281
|
-
def log_request(url, headers, body)
|
|
282
|
-
logger = @api.logger
|
|
283
|
-
logger.debug("Report request to: '%s'" % url)
|
|
284
|
-
logger.debug('HTTP headers: [%s]' %
|
|
285
|
-
(headers.map { |k, v| [k, v].join(': ') }.join(', ')))
|
|
286
|
-
logger.debug(body)
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
# Removes extraneous XML information from return hash.
|
|
290
|
-
def sanitize_result(results)
|
|
291
|
-
if results.is_a?(Array)
|
|
292
|
-
ret = []
|
|
293
|
-
results.each do |result|
|
|
294
|
-
ret << sanitize_result(result)
|
|
295
|
-
end
|
|
296
|
-
return ret
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
if results.is_a?(Hash)
|
|
300
|
-
ret = {}
|
|
301
|
-
results.each do |k, v|
|
|
302
|
-
v = sanitize_result(v) if v.is_a?(Hash)
|
|
303
|
-
ret[k] = v unless k.to_s.start_with?('@')
|
|
304
|
-
end
|
|
305
|
-
return ret
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
return results
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
def add_padding(xml)
|
|
312
|
-
remainder = xml.bytesize % REQUIRED_CONTENT_LENGTH_INCREMENT
|
|
313
|
-
return xml if remainder == 0
|
|
314
|
-
bytes_to_add = REQUIRED_CONTENT_LENGTH_INCREMENT - remainder
|
|
315
|
-
padded_xml = xml + (' ' * bytes_to_add)
|
|
316
|
-
return padded_xml
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
def get_nori()
|
|
320
|
-
return @nori if @nori
|
|
321
|
-
|
|
322
|
-
nori_options = {
|
|
323
|
-
:strip_namespaces => true,
|
|
324
|
-
:convert_tags_to => lambda { |tag| tag.snakecase.to_sym },
|
|
325
|
-
:empty_tag_value => "",
|
|
326
|
-
:advanced_typecasting => false
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
@nori = Nori.new(nori_options)
|
|
330
|
-
|
|
331
|
-
return @nori
|
|
332
|
-
end
|
|
333
|
-
end
|
|
334
|
-
end
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# Encoding: utf-8
|
|
2
|
-
#
|
|
3
|
-
# Copyright:: Copyright 2010, Google Inc. All Rights Reserved.
|
|
4
|
-
#
|
|
5
|
-
# License:: 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
|
|
14
|
-
# implied.
|
|
15
|
-
# See the License for the specific language governing permissions and
|
|
16
|
-
# limitations under the License.
|
|
17
|
-
#
|
|
18
|
-
# AdWords-specific credential handler.
|
|
19
|
-
|
|
20
|
-
require 'ads_common/credential_handler'
|
|
21
|
-
require 'adwords_api/api_config'
|
|
22
|
-
|
|
23
|
-
module AdwordsApi
|
|
24
|
-
class CredentialHandler < AdsCommon::CredentialHandler
|
|
25
|
-
# Whether we're making validate-only requests.
|
|
26
|
-
attr_accessor :validate_only
|
|
27
|
-
# Whether we're making partial failure requests.
|
|
28
|
-
attr_accessor :partial_failure
|
|
29
|
-
|
|
30
|
-
def initialize(config)
|
|
31
|
-
super(config)
|
|
32
|
-
@validate_only = false
|
|
33
|
-
@partial_failure = false
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Create the list of credentials to be used by the auth handler for header
|
|
37
|
-
# generation.
|
|
38
|
-
def credentials(credentials_override = nil)
|
|
39
|
-
result = super(credentials_override)
|
|
40
|
-
validate_headers_for_server(result)
|
|
41
|
-
|
|
42
|
-
extra_headers = {
|
|
43
|
-
'userAgent' => generate_user_agent(),
|
|
44
|
-
'developerToken' => result[:developer_token]
|
|
45
|
-
}
|
|
46
|
-
extra_headers['clientCustomerId'] = result[:client_customer_id] if
|
|
47
|
-
result[:client_customer_id]
|
|
48
|
-
extra_headers['validateOnly'] = 'true' if @validate_only
|
|
49
|
-
extra_headers['partialFailure'] = 'true' if @partial_failure
|
|
50
|
-
result[:extra_headers] = extra_headers
|
|
51
|
-
return result
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Generates string to use as user agent in headers.
|
|
55
|
-
def generate_user_agent(extra_ids = [])
|
|
56
|
-
agent_app = @config.read('authentication.user_agent')
|
|
57
|
-
if !agent_app.nil? && !agent_app.ascii_only?
|
|
58
|
-
raise AdwordsApi::Errors::InvalidUserAgentError.new(
|
|
59
|
-
'User agent contains non-ASCII characters.', agent_app)
|
|
60
|
-
end
|
|
61
|
-
extra_ids << ['AwApi-Ruby/%s' % AdwordsApi::ApiConfig::CLIENT_LIB_VERSION]
|
|
62
|
-
super(extra_ids, agent_app)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Returns the client customer ID specified in the current credentials.
|
|
66
|
-
def identifier()
|
|
67
|
-
return credentials[:extra_headers]['clientCustomerId']
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
private
|
|
71
|
-
|
|
72
|
-
# Validates that the right credentials are being used for the chosen
|
|
73
|
-
# environment.
|
|
74
|
-
#
|
|
75
|
-
# Raises:
|
|
76
|
-
# - AdwordsApi::Errors:BadCredentialsError if supplied credentials are not
|
|
77
|
-
# valid.
|
|
78
|
-
#
|
|
79
|
-
def validate_headers_for_server(credentials)
|
|
80
|
-
client_customer_id = credentials[:client_customer_id]
|
|
81
|
-
|
|
82
|
-
if client_customer_id and (!(client_customer_id.is_a?(Integer) or
|
|
83
|
-
(client_customer_id =~ /^\d+(-\d+-\d+)?$/)))
|
|
84
|
-
raise AdwordsApi::Errors::BadCredentialsError,
|
|
85
|
-
'Invalid client customer ID: %s' % client_customer_id.to_s
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
token = credentials[:developer_token]
|
|
89
|
-
if token.nil? || token.empty?
|
|
90
|
-
raise AdwordsApi::Errors::BadCredentialsError,
|
|
91
|
-
'Developer token is missing, check credentials.'
|
|
92
|
-
end
|
|
93
|
-
return nil
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
end
|
data/lib/adwords_api/errors.rb
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# Encoding: utf-8
|
|
2
|
-
#
|
|
3
|
-
# Copyright:: Copyright 2010, Google Inc. All Rights Reserved.
|
|
4
|
-
#
|
|
5
|
-
# License:: 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
|
|
14
|
-
# implied.
|
|
15
|
-
# See the License for the specific language governing permissions and
|
|
16
|
-
# limitations under the License.
|
|
17
|
-
#
|
|
18
|
-
# Specific error handling for the AdWords API.
|
|
19
|
-
|
|
20
|
-
require 'ads_common/errors'
|
|
21
|
-
require 'ads_common/results_extractor'
|
|
22
|
-
|
|
23
|
-
module AdwordsApi
|
|
24
|
-
module Errors
|
|
25
|
-
|
|
26
|
-
# This class encapsulates base class for API exceptions. More specific
|
|
27
|
-
# exceptions are generated based on Service WSDL.
|
|
28
|
-
class ApiException < AdsCommon::Errors::ApiException
|
|
29
|
-
attr_reader :array_fields
|
|
30
|
-
|
|
31
|
-
def initialize(exception_fault, registry)
|
|
32
|
-
@array_fields ||= []
|
|
33
|
-
extractor = AdsCommon::ResultsExtractor.new(registry)
|
|
34
|
-
exception_type = exception_fault[:application_exception_type]
|
|
35
|
-
exception_data = (exception_type.nil?) ? exception_fault :
|
|
36
|
-
extractor.extract_exception_data(exception_fault, exception_type)
|
|
37
|
-
exception_data.each { |key, value| set_field(key, value) }
|
|
38
|
-
super(exception_data[:message])
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
# Sets instance's property to a value if it is defined
|
|
44
|
-
def set_field(field, value)
|
|
45
|
-
if respond_to?(field)
|
|
46
|
-
value = arrayize(value) if is_array_field(field)
|
|
47
|
-
instance_variable_set("@#{field}", value)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Makes sure object is an array
|
|
52
|
-
def arrayize(object)
|
|
53
|
-
return [] if object.nil?
|
|
54
|
-
return object.is_a?(Array) ? object : [object]
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Should a field be forced to be an array
|
|
58
|
-
def is_array_field(field)
|
|
59
|
-
return @array_fields.include?(field.to_s)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Error for invalid credentials sush as malformed ID.
|
|
64
|
-
class BadCredentialsError < AdsCommon::Errors::ApiException
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Error for malformed report definition.
|
|
68
|
-
class InvalidReportDefinitionError < AdsCommon::Errors::ApiException
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Error for server-side report error.
|
|
72
|
-
class ReportError < AdsCommon::Errors::ApiException
|
|
73
|
-
attr_reader :http_code
|
|
74
|
-
|
|
75
|
-
def initialize(http_code, message)
|
|
76
|
-
super(message)
|
|
77
|
-
@http_code = http_code
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# Error for server-side report XML error.
|
|
82
|
-
class ReportXmlError < ReportError
|
|
83
|
-
attr_reader :type, :trigger, :field_path
|
|
84
|
-
|
|
85
|
-
def initialize(http_code, error_type, error_trigger, error_field_path)
|
|
86
|
-
message =
|
|
87
|
-
"HTTP code: %d, error type: '%s', trigger: '%s', field path: '%s'" %
|
|
88
|
-
[http_code, error_type, error_trigger, error_field_path]
|
|
89
|
-
super(http_code, message)
|
|
90
|
-
@type = error_type
|
|
91
|
-
@trigger = error_trigger
|
|
92
|
-
@field_path = error_field_path
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# Error for use an unsupported operation in a batch job.
|
|
97
|
-
class InvalidBatchJobOperationError < AdsCommon::Errors::ApiException
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
# Error for using an invalid user agent string.
|
|
101
|
-
class InvalidUserAgentError < AdsCommon::Errors::Error
|
|
102
|
-
attr_reader :user_agent
|
|
103
|
-
|
|
104
|
-
def initialize(message, user_agent)
|
|
105
|
-
super(message)
|
|
106
|
-
@user_agent = user_agent
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# Encoding: utf-8
|
|
2
|
-
#
|
|
3
|
-
# Copyright:: Copyright 2015, Google Inc. All Rights Reserved.
|
|
4
|
-
#
|
|
5
|
-
# License:: 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
|
|
14
|
-
# implied.
|
|
15
|
-
# See the License for the specific language governing permissions and
|
|
16
|
-
# limitations under the License.
|
|
17
|
-
#
|
|
18
|
-
# Contains helper methods to allow incremental uploads with the
|
|
19
|
-
# BatchJobService.
|
|
20
|
-
|
|
21
|
-
module AdwordsApi
|
|
22
|
-
class IncrementalUploadHelper
|
|
23
|
-
attr_reader :upload_url, :uploaded_bytes
|
|
24
|
-
|
|
25
|
-
# Default constructor.
|
|
26
|
-
#
|
|
27
|
-
# Args:
|
|
28
|
-
# - batch_job_service: The instance of BatchJobService that is providing
|
|
29
|
-
# this helper
|
|
30
|
-
# - uploaded_bytes: The number of bytes that have already been uploaded
|
|
31
|
-
# as part of this incremental process.
|
|
32
|
-
# - upload_url: The URL that should be used to upload incremental
|
|
33
|
-
# operations for this job.
|
|
34
|
-
#
|
|
35
|
-
def initialize(batch_job_utils, uploaded_bytes, upload_url)
|
|
36
|
-
@batch_job_utils = batch_job_utils
|
|
37
|
-
@uploaded_bytes = uploaded_bytes
|
|
38
|
-
if @uploaded_bytes == 0
|
|
39
|
-
@upload_url = @batch_job_utils.initialize_url(upload_url)
|
|
40
|
-
else
|
|
41
|
-
@upload_url = upload_url
|
|
42
|
-
end
|
|
43
|
-
@finished = false
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# Takes an array of operations and puts it to the batch job incrementally.
|
|
47
|
-
#
|
|
48
|
-
# Args:
|
|
49
|
-
# - hash_operations: An array of operations to put, represented in hashes
|
|
50
|
-
# like you would normally pass to services.
|
|
51
|
-
# - is_last_request: Whether this request is the last request of the
|
|
52
|
-
# incremental job.
|
|
53
|
-
#
|
|
54
|
-
# Raises:
|
|
55
|
-
# - InvalidBatchJobOperationError: If this incremental upload is already
|
|
56
|
-
# finished or if there is an error converting the hash operations to
|
|
57
|
-
# soap operations.
|
|
58
|
-
#
|
|
59
|
-
def upload(operations, is_last_request = false)
|
|
60
|
-
check_status()
|
|
61
|
-
@uploaded_bytes = @batch_job_utils.put_incremental_operations(
|
|
62
|
-
operations, @upload_url, @uploaded_bytes, is_last_request)
|
|
63
|
-
@finished = true if is_last_request
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
private
|
|
67
|
-
|
|
68
|
-
def check_status()
|
|
69
|
-
if @finished
|
|
70
|
-
raise AdwordsApi::Errors::InvalidBatchJobOperationError,
|
|
71
|
-
'Cannot put new operations to completed incremental upload.'
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# Encoding: utf-8
|
|
2
|
-
#
|
|
3
|
-
# Copyright:: Copyright 2018, Google Inc. All Rights Reserved.
|
|
4
|
-
#
|
|
5
|
-
# License:: 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
|
|
14
|
-
# implied.
|
|
15
|
-
# See the License for the specific language governing permissions and
|
|
16
|
-
# limitations under the License.
|
|
17
|
-
#
|
|
18
|
-
# Base class with common methods used across both report and service queries.
|
|
19
|
-
|
|
20
|
-
require 'adwords_api/query_utils/where_builder'
|
|
21
|
-
|
|
22
|
-
module AdwordsApi
|
|
23
|
-
class QueryBuilder
|
|
24
|
-
def initialize(api)
|
|
25
|
-
@api = api
|
|
26
|
-
@where = []
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def where(field)
|
|
30
|
-
clause = WhereBuilder.new(field)
|
|
31
|
-
@where << clause
|
|
32
|
-
return clause
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def build_where()
|
|
36
|
-
return '' if @where.empty?
|
|
37
|
-
wheres = @where.map {|w| w.awql}
|
|
38
|
-
return sprintf(' WHERE %s', wheres.join(' AND '))
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# Encoding: utf-8
|
|
2
|
-
#
|
|
3
|
-
# Copyright:: Copyright 2018, Google Inc. All Rights Reserved.
|
|
4
|
-
#
|
|
5
|
-
# License:: 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
|
|
14
|
-
# implied.
|
|
15
|
-
# See the License for the specific language governing permissions and
|
|
16
|
-
# limitations under the License.
|
|
17
|
-
#
|
|
18
|
-
# Class to hold a generated AWQL query for reports.
|
|
19
|
-
|
|
20
|
-
module AdwordsApi
|
|
21
|
-
class ReportQuery
|
|
22
|
-
def initialize(query)
|
|
23
|
-
@query = query
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def to_s()
|
|
27
|
-
return @query
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|