sem4r 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +11 -0
- data/Gemfile.lock +36 -0
- data/README.rdoc +30 -0
- data/Rakefile +15 -12
- data/VERSION.yml +1 -1
- data/examples_blog/2009-11-29-hello-world.rb +0 -1
- data/examples_sem4r/01_get_account.rb +1 -1
- data/examples_sem4r/02_get_info.rb +6 -2
- data/examples_sem4r/03_list_ad.rb +1 -1
- data/examples_sem4r/04_list_keywords.rb +1 -1
- data/examples_sem4r/05_request_report.rb +1 -2
- data/examples_sem4r/05_request_report_2010.rb +19 -4
- data/examples_sem4r/06_create_campaigns.rb +1 -1
- data/examples_sem4r/07_create_campaigns_block.rb +1 -1
- data/examples_sem4r/07_create_campaigns_simple.rb +1 -1
- data/examples_sem4r/08_ad_params.rb +1 -1
- data/examples_sem4r/09_targeting_idea.rb +1 -1
- data/examples_sem4r/10_get_location.rb +1 -1
- data/examples_sem4r/11_submit_bulk_job.rb +1 -1
- data/examples_sem4r/12_list_bulk_job.rb +1 -1
- data/examples_sem4r/30_prune_empty_adgroup.rb +1 -1
- data/examples_sem4r/31_empty_accounts.rb +1 -1
- data/examples_sem4r/example_helper.rb +5 -10
- data/lib/sem4r/account.rb +3 -306
- data/lib/sem4r/ad_group/ad_group.rb +16 -14
- data/lib/sem4r/ad_group/ad_group_bids.rb +11 -10
- data/lib/sem4r/ad_group/ad_group_service.rb +5 -5
- data/lib/sem4r/ad_group_ad/ad_group_ad.rb +1 -1
- data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +5 -5
- data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +9 -9
- data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +9 -9
- data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +6 -6
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +5 -6
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +0 -1
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +4 -4
- data/lib/sem4r/ad_group_criterion/criterion.rb +3 -3
- data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +3 -3
- data/lib/sem4r/ad_group_criterion/criterion_placement.rb +2 -2
- data/lib/sem4r/ad_param/ad_param.rb +3 -3
- data/lib/sem4r/ad_param/ad_param_service.rb +5 -5
- data/lib/sem4r/adwords.rb +1 -0
- data/lib/sem4r/api_counters.rb +1 -0
- data/lib/sem4r/base.rb +1 -0
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +2 -2
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_account_extension.rb +59 -0
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +5 -5
- data/lib/sem4r/campaign/campaign.rb +10 -10
- data/lib/sem4r/campaign/campaign_account_extension.rb +87 -0
- data/lib/sem4r/campaign/campaign_service.rb +6 -6
- data/lib/sem4r/campaign_target/campaign_target_service.rb +22 -22
- data/lib/sem4r/cli/cli_command.rb +1 -0
- data/lib/sem4r/cli/cli_common_args.rb +10 -3
- data/lib/sem4r/cli/cli_helpers.rb +1 -0
- data/lib/sem4r/cli/cli_sem.rb +1 -0
- data/lib/sem4r/cli/{cli_download_report.rb → commands/cli_download_report.rb} +2 -1
- data/lib/sem4r/cli/{cli_ideas.rb → commands/cli_ideas.rb} +1 -0
- data/lib/sem4r/cli/{cli_commands.rb → commands/cli_info.rb} +3 -23
- data/lib/sem4r/cli/{cli_list_ads.rb → commands/cli_list_ads.rb} +1 -0
- data/lib/sem4r/cli/commands/cli_list_campaign.rb +35 -0
- data/lib/sem4r/cli/commands/cli_list_client.rb +36 -0
- data/lib/sem4r/cli/{cli_list_keywords.rb → commands/cli_list_keywords.rb} +1 -0
- data/lib/sem4r/cli/commands/cli_list_report.rb +34 -0
- data/lib/sem4r/cli/commands/cli_repdef.rb +109 -0
- data/lib/sem4r/cli/commands/cli_report.rb +78 -0
- data/lib/sem4r/cli/{cli_request_report.rb → commands/cli_request_report.rb} +1 -0
- data/lib/sem4r/credentials.rb +1 -0
- data/lib/sem4r/extensions.rb +22 -1
- data/lib/sem4r/geo_location/geo_location_account_extension.rb +43 -0
- data/lib/sem4r/geo_location/geo_location_service.rb +4 -4
- data/lib/sem4r/info/info_account_extension.rb +48 -0
- data/lib/sem4r/info/info_selector.rb +108 -0
- data/lib/sem4r/info/info_service.rb +11 -66
- data/lib/sem4r/{common/operation.rb → operation.rb} +3 -1
- data/lib/sem4r/report_definition/report_definition.rb +75 -15
- data/lib/sem4r/report_definition/report_definition_account_extension.rb +79 -0
- data/lib/sem4r/report_definition/report_definition_operation.rb +3 -1
- data/lib/sem4r/report_definition/report_definition_service.rb +7 -7
- data/lib/sem4r/report_definition/report_field.rb +57 -0
- data/lib/sem4r/sem4r_error.rb +1 -0
- data/lib/sem4r/services/http_connector.rb +93 -0
- data/lib/sem4r/services/service.rb +1 -1
- data/lib/sem4r/services/soap_call.rb +27 -5
- data/lib/sem4r/services/soap_connector.rb +2 -147
- data/lib/sem4r/services/soap_dumper.rb +105 -0
- data/lib/sem4r/services/soap_message_v13.rb +15 -9
- data/lib/sem4r/services/{soap_message_v2009.rb → soap_message_v2010.rb} +26 -12
- data/lib/sem4r/targeting_idea/targeting_idea.rb +16 -11
- data/lib/sem4r/targeting_idea/targeting_idea_account_extension.rb +52 -0
- data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +36 -10
- data/lib/sem4r/targeting_idea/targeting_idea_service.rb +5 -5
- data/lib/sem4r/v13_account/account_account_extension.rb +103 -0
- data/lib/sem4r/v13_account/billing_address.rb +10 -21
- data/lib/sem4r/v13_report/report.rb +8 -8
- data/lib/sem4r/v13_report/report_account_extension.rb +63 -0
- data/lib/sem4r/v13_report/report_job.rb +1 -1
- data/lib/sem4r.rb +27 -6
- data/lib/sem4r_cli.rb +4 -6
- data/lib/{sem4r → soap_helpers}/soap_attributes.rb +105 -13
- data/sem4r.gemspec +229 -190
- data/spec/{aggregates_spec_helper.rb → aggregates_rspec_helper.rb} +0 -0
- data/spec/build_fixtures.rb +84 -0
- data/spec/rspec_hash.rb +66 -0
- data/spec/{spec_helper.rb → rspec_helper.rb} +4 -2
- data/spec/rspec_matchers.rb +102 -0
- data/spec/rspec_sem4r_helper.rb +88 -0
- data/spec/sem4r/account_spec.rb +3 -4
- data/spec/sem4r/ad_group/ad_group_bids_spec.rb +4 -3
- data/spec/sem4r/ad_group/ad_group_service_spec.rb +8 -7
- data/spec/sem4r/ad_group/ad_group_spec.rb +5 -4
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-first-req.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-first-res.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-manual-cpm-bids-req.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-manual-cpm-bids-res.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/mutate_add-req.xml +0 -0
- data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/mutate_add-res.xml +0 -0
- data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +3 -3
- data/spec/sem4r/ad_group_ad/ad_group_ad_service_spec.rb +6 -5
- data/spec/sem4r/ad_group_ad/ad_group_ad_spec.rb +6 -5
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_mobile_ad-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_mobile_ad-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_text_ad-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_text_ad-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_mobile_ad-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_mobile_ad-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_text_ad-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_text_ad-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_two_criterions-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_two_criterions-res.xml +0 -0
- data/spec/sem4r/ad_group_criterion/ad_group_criterion_bids_spec.rb +5 -4
- data/spec/sem4r/ad_group_criterion/ad_group_criterion_service_spec.rb +6 -5
- data/spec/sem4r/ad_group_criterion/ad_group_criterion_spec.rb +6 -5
- data/spec/sem4r/ad_group_criterion/criterion_spec.rb +5 -4
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/get-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/get-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_keyword-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_keyword-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_placement-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_placement-res.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_negative_keyword-req.xml +0 -0
- data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_negative_keyword-res.xml +0 -0
- data/spec/sem4r/ad_param/ad_param_service_spec.rb +6 -5
- data/spec/sem4r/ad_param/ad_param_spec.rb +3 -2
- data/spec/{fixtures/services/ad_param → sem4r/ad_param/fixtures}/mutate_set-req.xml +0 -0
- data/spec/{fixtures/services/ad_param → sem4r/ad_param/fixtures}/mutate_set-res.xml +0 -0
- data/spec/sem4r/adwords_spec.rb +1 -1
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +6 -5
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +4 -3
- data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/get-req.xml +0 -0
- data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/get-res.xml +0 -0
- data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/mutate-req.xml +0 -0
- data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/mutate-res.xml +0 -0
- data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +3 -2
- data/spec/sem4r/campaign/campaign_service_spec.rb +8 -7
- data/spec/sem4r/campaign/campaign_spec.rb +3 -2
- data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/get-req.xml +0 -0
- data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/get-res.xml +0 -0
- data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/mutate_add-req.xml +0 -0
- data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/mutate_add-res.xml +0 -0
- data/spec/sem4r/cli/cli_spec.rb +2 -3
- data/spec/sem4r/credentials_spec.rb +1 -1
- data/spec/sem4r/info/account_info_extension_spec.rb +51 -0
- data/spec/sem4r/info/fixtures/get_unit_count-req.xml +34 -0
- data/spec/sem4r/info/fixtures/get_unit_count-res.xml +27 -0
- data/spec/sem4r/nokogiri_parsing_spec.rb +105 -0
- data/spec/{fixtures/services/report_definition → sem4r/report_definition/fixtures}/mutate_add-req.xml +0 -0
- data/spec/{fixtures/services/report_definition → sem4r/report_definition/fixtures}/mutate_add-req_orig.xml +0 -0
- data/spec/sem4r/report_definition/report_definition_service_spec.rb +5 -3
- data/spec/sem4r/report_definition/report_definition_spec.rb +6 -3
- data/spec/sem4r/rexml_parsing_spec.rb +22 -22
- data/spec/sem4r/services/service_spec.rb +2 -1
- data/spec/sem4r/services/soap_call_spec.rb +6 -5
- data/spec/sem4r/services/soap_message_v13_spec.rb +5 -11
- data/spec/{fixtures/services/targeting_idea → sem4r/targeting_idea/fixtures}/get-req-all-options.xml +0 -0
- data/spec/{fixtures/services/targeting_idea → sem4r/targeting_idea/fixtures}/get-req.xml +9 -11
- data/spec/sem4r/targeting_idea/fixtures/get-res.xml +2276 -0
- data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +30 -11
- data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +4 -3
- data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +5 -4
- data/spec/sem4r/v13_account/account_account_extension_spec.rb +47 -0
- data/spec/sem4r/v13_account/account_service_spec.rb +6 -5
- data/spec/sem4r/v13_account/billing_address_spec.rb +40 -0
- data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_account_info-req.xml +0 -0
- data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_account_info-res.xml +0 -0
- data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_client_accounts-req.xml +0 -0
- data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_client_accounts-res.xml +0 -0
- data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/get_all_jobs-req.xml +0 -0
- data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/get_all_jobs-res.xml +2 -2
- data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/schedule_report_job-req.xml +0 -0
- data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/schedule_report_job-res.xml +0 -0
- data/spec/sem4r/v13_report/report_service_spec.rb +13 -11
- data/spec/sem4r/v13_report/report_spec.rb +4 -3
- data/spec/sem4r_stubs.rb +182 -0
- data/spec/soap_helpers/soap_attributes_spec.rb +129 -0
- metadata +225 -125
- data/spec/fixtures/services/info/get_unit_count-req.xml +0 -30
- data/spec/fixtures/services/info/get_unit_count-res.xml +0 -29
- data/spec/fixtures/services/targeting_idea/get-res.xml +0 -3601
- data/spec/sem4r/soap_attributes_spec.rb +0 -116
- data/spec/sem4r_spec_helper.rb +0 -353
@@ -28,7 +28,52 @@ module Sem4r
|
|
28
28
|
|
29
29
|
attr_reader :id
|
30
30
|
|
31
|
-
|
31
|
+
enum :ReportTypes, [
|
32
|
+
:KEYWORDS_PERFORMANCE_REPORT,
|
33
|
+
:AD_PERFORMANCE_REPORT,
|
34
|
+
:URL_PERFORMANCE_REPORT,
|
35
|
+
:ADGROUP_PERFORMANCE_REPORT,
|
36
|
+
:CAMPAIGN_PERFORMANCE_REPORT,
|
37
|
+
:ACCOUNT_PERFORMANCE_REPORT,
|
38
|
+
:SEARCH_QUERY_PERFORMANCE_REPORT,
|
39
|
+
:MANAGED_PLACEMENTS_PERFORMANCE_REPORT,
|
40
|
+
:AUTOMATIC_PLACEMENTS_PERFORMANCE_REPORT,
|
41
|
+
:CAMPAIGN_NEGATIVE_KEYWORDS_PERFORMANCE_REPORT,
|
42
|
+
:CAMPAIGN_NEGATIVE_PLACEMENTS_PERFORMANCE_REPORT,
|
43
|
+
]
|
44
|
+
|
45
|
+
enum :DateRangeTypes, [
|
46
|
+
:TODAY,
|
47
|
+
:YESTERDAY,
|
48
|
+
:LAST_7_DAYS,
|
49
|
+
:LAST_WEEK,
|
50
|
+
:LAST_14_DAYS,
|
51
|
+
:LAST_30_DAYS,
|
52
|
+
:LAST_BUSINESS_WEEK,
|
53
|
+
:THIS_MONTH,
|
54
|
+
:LAST_MONTH,
|
55
|
+
:ALL_TIME,
|
56
|
+
:CUSTOM_DATE,
|
57
|
+
]
|
58
|
+
|
59
|
+
enum :DownloadFormatTypes, [
|
60
|
+
:CSVFOREXCEL,
|
61
|
+
:CSV,
|
62
|
+
:TSV,
|
63
|
+
:XML,
|
64
|
+
:GZIPPED_CSV,
|
65
|
+
:GZIPPED_XML
|
66
|
+
]
|
67
|
+
|
68
|
+
g_accessor :name, { :xpath => 'reportName' }
|
69
|
+
g_accessor :type, { :xpath => 'reportType', :values_in => :ReportTypes }
|
70
|
+
g_accessor :format, { :xpath => 'downloadFormat', :values_in => :DownloadFormatTypes }
|
71
|
+
|
72
|
+
g_accessor :date_range, { :values_in => :DateRangeTypes }
|
73
|
+
g_accessor :from
|
74
|
+
g_accessor :to
|
75
|
+
|
76
|
+
g_set_accessor :field
|
32
77
|
|
33
78
|
def initialize(account, name = nil, &block)
|
34
79
|
super( account.adwords, account.credentials )
|
@@ -46,27 +91,44 @@ module Sem4r
|
|
46
91
|
end
|
47
92
|
|
48
93
|
def to_s
|
49
|
-
"'#{@name}'"
|
94
|
+
"#{@id}: '#{@name}'"
|
50
95
|
end
|
51
96
|
|
52
97
|
def to_xml(tag)
|
53
98
|
builder = Builder::XmlMarkup.new
|
54
99
|
builder.tag!(tag) do |t|
|
55
|
-
|
100
|
+
|
101
|
+
t.id @id if @id
|
102
|
+
t.reportName @name if @name
|
103
|
+
t.reportType @type if @type
|
104
|
+
t.dateRangeType @date_range if @date_range
|
105
|
+
t.downloadFormat @format if @format
|
106
|
+
|
107
|
+
#TODO: non costruire selector se il contenuto e' vuoto utile per l'operazione di delete
|
108
|
+
t.selector do |t|
|
109
|
+
fields.each { |f| t.fields f}
|
110
|
+
if from and to
|
111
|
+
t.dateRange do |t|
|
112
|
+
t.min from
|
113
|
+
t.max to
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
56
118
|
end
|
57
119
|
end
|
58
120
|
|
59
|
-
|
60
121
|
###########################################################################
|
61
122
|
|
62
123
|
def self.from_element(account, el)
|
63
124
|
new(account) do
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
125
|
+
|
126
|
+
@id = el.at_xpath("id").text.strip.to_i
|
127
|
+
name el.at_xpath('reportName').text.strip
|
128
|
+
type el.at_xpath('reportType').text.strip
|
129
|
+
format el.at_xpath('downloadFormat').text.strip
|
130
|
+
# start_date el.at_xpath('startDate')
|
131
|
+
# end_date el.at_xpath('endDate')
|
70
132
|
end
|
71
133
|
end
|
72
134
|
|
@@ -76,13 +138,11 @@ module Sem4r
|
|
76
138
|
|
77
139
|
def save
|
78
140
|
unless @id
|
79
|
-
op = ReportDefinitionOperation.new
|
80
|
-
op.add(self)
|
81
|
-
puts op.to_xml "operations"
|
141
|
+
op = ReportDefinitionOperation.new.add(self)
|
82
142
|
soap_message = service.report_definition.mutate(credentials, op.to_xml("operations"))
|
83
143
|
add_counters( soap_message.counters )
|
84
|
-
rval =
|
85
|
-
id =
|
144
|
+
rval = soap_message.response.at_xpath("//mutateResponse/rval")
|
145
|
+
id = rval.at_xpath("id" )
|
86
146
|
@id = id.text.strip.to_i
|
87
147
|
end
|
88
148
|
self
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# -------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
# -------------------------------------------------------------------------
|
24
|
+
|
25
|
+
module Sem4r
|
26
|
+
|
27
|
+
module ReportDefinitionAccountExtension
|
28
|
+
|
29
|
+
def report_definition_delete(report_definition_id)
|
30
|
+
report_definition = ReportDefinition.new(self)
|
31
|
+
report_definition.instance_eval { @id = report_definition_id }
|
32
|
+
op = ReportDefinitionOperation.new
|
33
|
+
op.remove(report_definition)
|
34
|
+
soap_message = service.report_definition.mutate(credentials, op.to_xml("operations"))
|
35
|
+
add_counters( soap_message.counters )
|
36
|
+
end
|
37
|
+
|
38
|
+
def report_fields
|
39
|
+
soap_message = service.report_definition.report_fields(credentials)
|
40
|
+
add_counters( soap_message.counters )
|
41
|
+
els = soap_message.response.xpath("//getReportFieldsResponse/rval")
|
42
|
+
els.map do |el|
|
43
|
+
ReportField.from_element(el)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def report_definition(&block)
|
48
|
+
ReportDefinition.new(self, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def p_report_definitions(refresh = false)
|
52
|
+
report_definitions(refresh).each do |report_definition|
|
53
|
+
puts report_definition.to_s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def report_definitions(refresh = false)
|
58
|
+
_report_definitions unless @report_definitions and !refresh
|
59
|
+
@report_definitions
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def _report_definitions
|
65
|
+
soap_message = service.report_definition.get(credentials, ReportDefinitionSelector.new.to_xml)
|
66
|
+
add_counters( soap_message.counters )
|
67
|
+
els = soap_message.response.xpath("//entries")
|
68
|
+
@report_definitions = els.map do |el|
|
69
|
+
ReportDefinition.from_element(self, el)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
class Account
|
76
|
+
include ReportDefinitionAccountExtension
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -25,10 +25,12 @@
|
|
25
25
|
module Sem4r
|
26
26
|
class ReportDefinitionOperation < Operation
|
27
27
|
def initialize(&block)
|
28
|
-
@operation_type = "ReportDefinitionOperation"
|
28
|
+
@operation_type = "n1:ReportDefinitionOperation"
|
29
|
+
@namespace = 'xmlns:n1="https://adwords.google.com/api/adwords/cm/v201008"'
|
29
30
|
if block_given?
|
30
31
|
block.arity < 1 ? instance_eval(&block) : block.call(self)
|
31
32
|
end
|
33
|
+
self
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
@@ -28,15 +28,14 @@ module Sem4r
|
|
28
28
|
|
29
29
|
def initialize(connector)
|
30
30
|
@connector = connector
|
31
|
-
@
|
32
|
-
@header_namespace = @service_namespace
|
31
|
+
@header_namespace = "https://adwords.google.com/api/adwords/cm/v201008"
|
33
32
|
|
34
|
-
@sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/cm/
|
33
|
+
@sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/cm/v201008/ReportDefinitionService"
|
35
34
|
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
soap_call_v2010 :get, :mutate => false
|
37
|
+
soap_call_v2010 :report_fields, :mutate => false
|
38
|
+
soap_call_v2010 :mutate
|
40
39
|
|
41
40
|
private
|
42
41
|
|
@@ -44,7 +43,8 @@ module Sem4r
|
|
44
43
|
"<get>#{xml}</get>"
|
45
44
|
end
|
46
45
|
|
47
|
-
def
|
46
|
+
def _report_fields
|
47
|
+
"<getReportFields><reportType>URL_PERFORMANCE_REPORT</reportType></getReportFields>"
|
48
48
|
end
|
49
49
|
|
50
50
|
def _mutate(xml)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# -------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
# -------------------------------------------------------------------
|
23
|
+
|
24
|
+
module Sem4r
|
25
|
+
|
26
|
+
class ReportField
|
27
|
+
include SoapAttributes
|
28
|
+
|
29
|
+
attrs =[
|
30
|
+
:field_name,
|
31
|
+
:display_field_name,
|
32
|
+
:xml_attribute_name,
|
33
|
+
:field_type,
|
34
|
+
:can_select,
|
35
|
+
:can_filter,
|
36
|
+
]
|
37
|
+
|
38
|
+
attrs.each do |s|
|
39
|
+
g_accessor s
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize(&block)
|
43
|
+
if block_given?
|
44
|
+
block.arity < 1 ? instance_eval(&block) : block.call(self)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.from_element(*args)
|
49
|
+
_from_element(*args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s
|
53
|
+
"#{@field_name} #{@field_type} #{@address_line2} #{@city}"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/lib/sem4r/sem4r_error.rb
CHANGED
@@ -0,0 +1,93 @@
|
|
1
|
+
# -------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
# -------------------------------------------------------------------------
|
24
|
+
|
25
|
+
module Sem4r
|
26
|
+
|
27
|
+
class HttpConnector
|
28
|
+
begin
|
29
|
+
require 'patron'
|
30
|
+
UsePatron = false
|
31
|
+
# $stderr.puts "Using patron gems"
|
32
|
+
rescue LoadError
|
33
|
+
UsePatron = false
|
34
|
+
# $stderr.puts "Patron not found, degrade to net/https"
|
35
|
+
end
|
36
|
+
|
37
|
+
if !UsePatron
|
38
|
+
require 'net/https'
|
39
|
+
require 'uri'
|
40
|
+
# $stderr.puts "Using standard net/https"
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_sess_for_host(uri)
|
44
|
+
@sessions ||= {}
|
45
|
+
|
46
|
+
if UsePatron
|
47
|
+
url = uri.scheme + "://" + uri.host
|
48
|
+
sess = @sessions[url]
|
49
|
+
unless sess
|
50
|
+
sess = Patron::Session.new
|
51
|
+
# sess.connect_timeout = 3000 #millis
|
52
|
+
sess.timeout = 12
|
53
|
+
sess.base_url = url
|
54
|
+
sess.headers['User-Agent'] = 'ruby'
|
55
|
+
@sessions[url] = sess
|
56
|
+
end
|
57
|
+
sess
|
58
|
+
else
|
59
|
+
url = uri.scheme + "://" + uri.host
|
60
|
+
sess = @sessions[url]
|
61
|
+
unless sess
|
62
|
+
sess = Net::HTTP.new(uri.host, uri.port)
|
63
|
+
sess.use_ssl = (uri.scheme == "https")
|
64
|
+
@sessions[url] = sess
|
65
|
+
end
|
66
|
+
sess
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def invalidate_sess(uri)
|
71
|
+
sess = @sessions[uri.host]
|
72
|
+
if sess
|
73
|
+
# sess.close
|
74
|
+
@sessions[uri.host] = nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def download(url, path_name)
|
79
|
+
|
80
|
+
if UsePatron
|
81
|
+
uri = URI.parse(url)
|
82
|
+
sess = get_sess_for_host(uri)
|
83
|
+
sess.get_file(uri.path, path_name)
|
84
|
+
else
|
85
|
+
require 'open-uri'
|
86
|
+
data = open(url){ |f| f.read }
|
87
|
+
File.open(path_name, "w") { |f| f.write(data) }
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -48,8 +48,8 @@ module Sem4r
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
52
|
-
soap_message =
|
51
|
+
def helper_call_v2010(credentials, soap_body_content)
|
52
|
+
soap_message = SoapMessageV2010.new(@connector, credentials)
|
53
53
|
soap_message.init( @header_namespace, @service_namespace )
|
54
54
|
soap_message.body = soap_body_content
|
55
55
|
if credentials.sandbox?
|
@@ -59,6 +59,16 @@ module Sem4r
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
def helper_call_v2010_raw(credentials, xml_message)
|
63
|
+
soap_message = SoapMessageV2010.new(@connector, credentials)
|
64
|
+
soap_message.init( @header_namespace, @service_namespace )
|
65
|
+
if credentials.sandbox?
|
66
|
+
soap_message.send_raw(@sandbox_service_url, xml_message)
|
67
|
+
else
|
68
|
+
soap_message.send_raw(@production_service_url, xml_message)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
62
72
|
module ClassMethods
|
63
73
|
def soap_call(helper_version, method, options = {})
|
64
74
|
options.assert_valid_keys(:mutate)
|
@@ -72,7 +82,6 @@ module Sem4r
|
|
72
82
|
|
73
83
|
# private_method_pars = args.join(",")
|
74
84
|
# private_method_pars = ", #{private_method_pars}" unless private_method_pars.empty?
|
75
|
-
|
76
85
|
rubystr =<<-EOFS
|
77
86
|
define_method :#{method.to_sym} do |*args|
|
78
87
|
credentials = args.shift
|
@@ -85,14 +94,27 @@ module Sem4r
|
|
85
94
|
end
|
86
95
|
EOFS
|
87
96
|
eval rubystr
|
97
|
+
|
98
|
+
rubystr =<<-EOFS
|
99
|
+
define_method :#{(method.to_s + "_raw").to_sym} do |*args|
|
100
|
+
credentials = args.shift
|
101
|
+
soap_message = args.shift
|
102
|
+
if #{smutate}
|
103
|
+
#{helper_version}_raw(credentials, soap_message)
|
104
|
+
else
|
105
|
+
raise "mutate methods '#{method}' cannot be called on read_only profile"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
EOFS
|
109
|
+
eval rubystr
|
88
110
|
end
|
89
111
|
|
90
112
|
def soap_call_v13(method, options = {})
|
91
113
|
soap_call("helper_call_v13", method, options)
|
92
114
|
end
|
93
115
|
|
94
|
-
def
|
95
|
-
soap_call("
|
116
|
+
def soap_call_v2010(method, options = {})
|
117
|
+
soap_call("helper_call_v2010", method, options)
|
96
118
|
end
|
97
119
|
end
|
98
120
|
|
@@ -23,148 +23,6 @@
|
|
23
23
|
|
24
24
|
module Sem4r
|
25
25
|
|
26
|
-
class HttpConnector
|
27
|
-
begin
|
28
|
-
require 'patron'
|
29
|
-
UsePatron = false
|
30
|
-
# $stderr.puts "Using patron gems"
|
31
|
-
rescue LoadError
|
32
|
-
UsePatron = false
|
33
|
-
# $stderr.puts "Patron not found, degrade to net/https"
|
34
|
-
end
|
35
|
-
|
36
|
-
if !UsePatron
|
37
|
-
require 'net/https'
|
38
|
-
require 'uri'
|
39
|
-
# $stderr.puts "Using standard net/https"
|
40
|
-
end
|
41
|
-
|
42
|
-
def get_sess_for_host(uri)
|
43
|
-
@sessions ||= {}
|
44
|
-
|
45
|
-
if UsePatron
|
46
|
-
url = uri.scheme + "://" + uri.host
|
47
|
-
sess = @sessions[url]
|
48
|
-
unless sess
|
49
|
-
sess = Patron::Session.new
|
50
|
-
# sess.connect_timeout = 3000 #millis
|
51
|
-
sess.timeout = 12
|
52
|
-
sess.base_url = url
|
53
|
-
sess.headers['User-Agent'] = 'ruby'
|
54
|
-
@sessions[url] = sess
|
55
|
-
end
|
56
|
-
sess
|
57
|
-
else
|
58
|
-
url = uri.scheme + "://" + uri.host
|
59
|
-
sess = @sessions[url]
|
60
|
-
unless sess
|
61
|
-
sess = Net::HTTP.new(uri.host, uri.port)
|
62
|
-
sess.use_ssl = (uri.scheme == "https")
|
63
|
-
@sessions[url] = sess
|
64
|
-
end
|
65
|
-
sess
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def invalidate_sess(uri)
|
70
|
-
sess = @sessions[uri.host]
|
71
|
-
if sess
|
72
|
-
# sess.close
|
73
|
-
@sessions[uri.host] = nil
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def download(url, path_name)
|
78
|
-
|
79
|
-
if UsePatron
|
80
|
-
uri = URI.parse(url)
|
81
|
-
sess = get_sess_for_host(uri)
|
82
|
-
sess.get_file(uri.path, path_name)
|
83
|
-
else
|
84
|
-
require 'open-uri'
|
85
|
-
data = open(url){ |f| f.read }
|
86
|
-
File.open(path_name, "w") { |f| f.write(data) }
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
module SoapDumper
|
93
|
-
|
94
|
-
def initialize
|
95
|
-
@soap_dump = false
|
96
|
-
@soap_dump_log = nil
|
97
|
-
end
|
98
|
-
|
99
|
-
def dump_soap_options( dump_options )
|
100
|
-
@soap_dump = true
|
101
|
-
@soap_dump_log = nil
|
102
|
-
|
103
|
-
if dump_options[:directory]
|
104
|
-
@soap_dump_dir = dump_options[:directory]
|
105
|
-
else
|
106
|
-
@soap_dump_log = File.open( dump_options[:file], "w" )
|
107
|
-
end
|
108
|
-
@soap_dump_format = false || dump_options[:format]
|
109
|
-
end
|
110
|
-
|
111
|
-
def dump_soap(service_url, request_xml, response_xml)
|
112
|
-
return unless @soap_dump
|
113
|
-
|
114
|
-
%w{email password developerToken authToken clientEmail}.each do |tag|
|
115
|
-
request_xml = request_xml.gsub(/<#{tag}([^>]*)>.*<\/#{tag}>/, "<#{tag}\\1>***censured***</#{tag}>")
|
116
|
-
end
|
117
|
-
response_xml.gsub(/<email[^>]*>.+<\/email>/, "<email>**censured**</email>")
|
118
|
-
|
119
|
-
str =""
|
120
|
-
str << "<!-- Post to '#{service_url}' -->\n"
|
121
|
-
|
122
|
-
if !@soap_dump_format
|
123
|
-
str << request_xml
|
124
|
-
else
|
125
|
-
xml_document = REXML::Document.new(request_xml)
|
126
|
-
f = REXML::Formatters::Pretty.new
|
127
|
-
out = String.new
|
128
|
-
f.write(xml_document, out)
|
129
|
-
str << out
|
130
|
-
end
|
131
|
-
str << "\n"
|
132
|
-
|
133
|
-
str << "<!-- response -->\n"
|
134
|
-
if !@soap_dump_format
|
135
|
-
str << response_xml
|
136
|
-
else
|
137
|
-
xml_document = REXML::Document.new(response_xml)
|
138
|
-
f = REXML::Formatters::Pretty.new
|
139
|
-
out = String.new
|
140
|
-
f.write(xml_document, out)
|
141
|
-
str << out
|
142
|
-
end
|
143
|
-
str << "\n"
|
144
|
-
str << "<!-- end -->"
|
145
|
-
|
146
|
-
if @soap_dump_dir
|
147
|
-
service = service_url.match(/\/([^\/]*)$/)[1]
|
148
|
-
filename = Time.now.strftime "%Y%m%d-%H%M%S-%L-#{service}.log.xml"
|
149
|
-
|
150
|
-
if not File.directory?(@soap_dump_dir)
|
151
|
-
FileUtils.mkdir_p(@soap_dump_dir)
|
152
|
-
end
|
153
|
-
|
154
|
-
pathname = File.join(@soap_dump_dir, filename)
|
155
|
-
File.open(pathname, "w") {|f|
|
156
|
-
f.puts str
|
157
|
-
}
|
158
|
-
else
|
159
|
-
@soap_dump_log.puts str
|
160
|
-
@soap_dump_log.flush
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
end
|
165
|
-
|
166
|
-
#################
|
167
|
-
|
168
26
|
class SoapConnector < HttpConnector
|
169
27
|
include SoapDumper
|
170
28
|
|
@@ -272,13 +130,10 @@ module Sem4r
|
|
272
130
|
end
|
273
131
|
|
274
132
|
response_xml = response.body
|
275
|
-
|
133
|
+
dump_soap_request(service_url, soap_message)
|
134
|
+
dump_soap_response(service_url, response_xml)
|
276
135
|
response_xml
|
277
136
|
end
|
278
|
-
|
279
|
-
private
|
280
|
-
|
281
|
-
|
282
137
|
end
|
283
138
|
|
284
139
|
end
|