sem4r 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +13 -2
- data/Gemfile.lock +13 -7
- data/README.rdoc +44 -7
- data/Rakefile +2 -122
- data/VERSION.yml +1 -1
- data/bin/sem +1 -0
- data/examples_sem4r/01_get_account.rb +1 -0
- data/examples_sem4r/02_get_info.rb +1 -0
- data/examples_sem4r/03_list_ad.rb +1 -0
- data/examples_sem4r/04_list_keywords.rb +1 -0
- data/examples_sem4r/05_request_report.rb +25 -14
- data/examples_sem4r/{05_request_report_2010.rb → 06_request_report_definition.rb} +2 -4
- data/examples_sem4r/{06_create_campaigns.rb → 07_create_campaigns.rb} +1 -0
- data/examples_sem4r/{07_create_campaigns_block.rb → 08_create_campaigns_block.rb} +1 -0
- data/examples_sem4r/{07_create_campaigns_simple.rb → 09_create_campaigns_simple.rb} +1 -0
- data/examples_sem4r/{08_ad_params.rb → 10_ad_params.rb} +1 -0
- data/examples_sem4r/{09_targeting_idea.rb → 11_targeting_idea.rb} +1 -0
- data/examples_sem4r/{10_get_location.rb → 12_get_location.rb} +1 -0
- data/examples_sem4r/{11_submit_bulk_job.rb → 13_submit_bulk_job.rb} +1 -1
- data/examples_sem4r/{12_list_bulk_job.rb → 14_list_bulk_job.rb} +3 -0
- data/examples_sem4r/30_prune_empty_adgroup.rb +1 -0
- data/examples_sem4r/31_empty_accounts.rb +1 -0
- data/examples_sem4r/example_helper.rb +2 -1
- data/lib/sem4r/ad_group/ad_group.rb +22 -7
- data/lib/sem4r/ad_group/ad_group_bids.rb +1 -1
- data/lib/sem4r/ad_group/ad_group_service.rb +12 -5
- data/lib/sem4r/ad_group_ad/ad_group_ad.rb +1 -0
- data/lib/sem4r/ad_group_ad/ad_group_ad_operations.rb +1 -0
- data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +14 -9
- data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +16 -25
- data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +18 -14
- data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +27 -19
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +2 -1
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +1 -0
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +9 -4
- data/lib/sem4r/ad_group_criterion/criterion.rb +1 -0
- data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +1 -0
- data/lib/sem4r/ad_group_criterion/criterion_placement.rb +1 -0
- data/lib/sem4r/ad_param/ad_param.rb +24 -8
- data/lib/sem4r/ad_param/ad_param_service.rb +8 -5
- data/lib/sem4r/adwords.rb +232 -76
- data/lib/sem4r/base.rb +1 -1
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +41 -35
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_account_extension.rb +49 -15
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_selector.rb +29 -20
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +13 -14
- data/lib/sem4r/bulk_mutate_job/job_operations.rb +1 -1
- data/lib/sem4r/campaign/campaign.rb +1 -0
- data/lib/sem4r/campaign/campaign_account_extension.rb +2 -1
- data/lib/sem4r/campaign/campaign_service.rb +9 -5
- data/lib/sem4r/credentials.rb +11 -5
- data/lib/sem4r/geo_location/address.rb +56 -0
- data/lib/sem4r/geo_location/geo_location_account_extension.rb +27 -6
- data/lib/sem4r/geo_location/geo_location_selector.rb +57 -0
- data/lib/sem4r/geo_location/geo_location_service.rb +9 -16
- data/lib/sem4r/info/info_account_extension.rb +3 -2
- data/lib/sem4r/info/info_selector.rb +2 -1
- data/lib/sem4r/info/info_service.rb +10 -3
- data/lib/sem4r/operation.rb +39 -20
- data/lib/sem4r/report_definition/report_definition.rb +37 -19
- data/lib/sem4r/report_definition/report_definition_account_extension.rb +66 -16
- data/lib/sem4r/report_definition/report_definition_operation.rb +2 -2
- data/lib/sem4r/report_definition/report_definition_selector.rb +1 -1
- data/lib/sem4r/report_definition/report_definition_service.rb +11 -7
- data/lib/sem4r/report_definition/report_field.rb +3 -2
- data/lib/sem4r/sem4r_templates.rb +77 -0
- data/lib/sem4r/{services/service.rb → service.rb} +23 -23
- data/lib/sem4r/targeting_idea/targeting_idea.rb +4 -4
- data/lib/sem4r/targeting_idea/targeting_idea_account_extension.rb +1 -1
- data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +6 -6
- data/lib/sem4r/targeting_idea/targeting_idea_service.rb +7 -5
- data/lib/sem4r/v13_account/account_account_extension.rb +7 -10
- data/lib/sem4r/v13_account/account_service.rb +10 -4
- data/lib/sem4r/v13_account/billing_address.rb +2 -2
- data/lib/sem4r/v13_report/report_service.rb +11 -9
- data/lib/sem4r.rb +46 -31
- data/lib/{sem4r/cli → sem4r_cli}/cli_helpers.rb +3 -2
- data/lib/{sem4r/cli/cli_command.rb → sem4r_cli/cli_mini_framework.rb} +77 -32
- data/lib/{sem4r/cli/cli_common_args.rb → sem4r_cli/cli_sem.rb} +177 -157
- data/lib/{sem4r/cli/commands/cli_list_ads.rb → sem4r_cli/commands/cli_ads.rb} +7 -9
- data/lib/sem4r_cli/commands/cli_campaign.rb +69 -0
- data/lib/{sem4r/cli/commands/cli_list_client.rb → sem4r_cli/commands/cli_clients.rb} +2 -2
- data/lib/{sem4r/cli → sem4r_cli}/commands/cli_ideas.rb +35 -27
- data/lib/{sem4r/cli → sem4r_cli}/commands/cli_info.rb +3 -4
- data/lib/{sem4r/cli/commands/cli_repdef.rb → sem4r_cli/commands/cli_job.rb} +57 -55
- data/lib/{sem4r/cli/commands/cli_list_keywords.rb → sem4r_cli/commands/cli_keywords.rb} +14 -13
- data/lib/sem4r_cli/commands/cli_profile.rb +138 -0
- data/lib/{sem4r/cli/commands/cli_report.rb → sem4r_cli/commands/cli_repdef.rb} +67 -20
- data/lib/{sem4r/cli/commands/cli_request_report.rb → sem4r_cli/commands/cli_report.rb} +82 -19
- data/lib/sem4r_cli.rb +5 -7
- data/lib/sem4r_soap/http_connector.rb +206 -0
- data/lib/{soap_helpers → sem4r_soap}/soap_attributes.rb +8 -3
- data/lib/{sem4r/services → sem4r_soap}/soap_dumper.rb +36 -20
- data/lib/{sem4r/services → sem4r_soap}/soap_error.rb +5 -2
- data/lib/sem4r_soap/soap_response.rb +75 -0
- data/lib/sem4r_soap/soap_service.rb +137 -0
- data/lib/{sem4r/cli/cli_sem.rb → sem4r_soap/soap_service_v13.rb} +27 -28
- data/lib/sem4r_soap/soap_service_v2010.rb +80 -0
- data/lib/sem4r_soap.rb +17 -0
- data/sem4r.gemspec +93 -58
- data/spec/build_fixtures.rb +49 -42
- data/spec/fixtures/password.example.yml +3 -0
- data/spec/fixtures/sem4r.example.yml +6 -0
- data/spec/fixtures/{services/error.xml → soap_error.xml} +0 -0
- data/spec/fixtures/soap_error2.xml +29 -0
- data/spec/helpers/dump_interceptor.rb +90 -0
- data/spec/helpers/fixtures_bulk_mutate_job.rb +48 -0
- data/spec/helpers/fixtures_geo_location.rb +45 -0
- data/{lib/sem4r/campaign_criterion/campaign_criterion_service.rb → spec/helpers/fixtures_info.rb} +10 -6
- data/spec/helpers/fixtures_report_definition.rb +65 -0
- data/spec/{rspec_hash.rb → helpers/rspec_hash.rb} +1 -0
- data/spec/{rspec_matchers.rb → helpers/rspec_matchers.rb} +46 -19
- data/spec/{rspec_sem4r_helper.rb → helpers/rspec_sem4r_helper.rb} +19 -16
- data/spec/{sem4r_stubs.rb → helpers/sem4r_stubs.rb} +5 -4
- data/spec/rspec_helper.rb +4 -4
- data/spec/sem4r/account_spec.rb +2 -3
- data/spec/sem4r/ad_group/ad_group_service_spec.rb +1 -1
- data/spec/sem4r/ad_group/ad_group_spec.rb +1 -1
- data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +3 -3
- data/spec/sem4r/adwords_spec.rb +62 -39
- data/{lib/sem4r/cli/commands/cli_list_campaign.rb → spec/sem4r/bulk_mutate_job/bulk_mutate_job_selector_spec.rb} +14 -11
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +2 -3
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +23 -17
- data/spec/sem4r/bulk_mutate_job/fixtures/get-list_job-req.xml +35 -0
- data/spec/sem4r/bulk_mutate_job/fixtures/get-list_job-res.xml +417 -0
- data/spec/sem4r/bulk_mutate_job/fixtures/mutate-add_job-req.xml +106 -0
- data/spec/sem4r/bulk_mutate_job/fixtures/mutate-add_job-res.xml +48 -0
- data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +5 -7
- data/spec/sem4r/campaign/campaign_service_spec.rb +2 -2
- data/spec/sem4r/credentials_spec.rb +10 -8
- data/spec/sem4r/geo_location/address_spec.rb +62 -0
- data/spec/sem4r/geo_location/fixtures/get-req.xml +42 -0
- data/spec/sem4r/geo_location/fixtures/get-res.xml +60 -0
- data/spec/sem4r/info/fixtures/get-req.xml +34 -0
- data/spec/sem4r/info/fixtures/get-res.xml +27 -0
- data/spec/sem4r/nokogiri_parsing_spec.rb +1 -0
- data/spec/sem4r/operation_spec.rb +72 -0
- data/spec/sem4r/report_definition/fixtures/get-list-repdef-req.xml +22 -0
- data/spec/sem4r/report_definition/fixtures/get-list-repdef-res.xml +73 -0
- data/spec/sem4r/report_definition/fixtures/getReportFields-req.xml +24 -0
- data/spec/sem4r/report_definition/fixtures/getReportFields-res.xml +1199 -0
- data/spec/sem4r/report_definition/fixtures/mutate-add-report-req.xml +63 -0
- data/spec/sem4r/report_definition/fixtures/mutate-add-report-res.xml +68 -0
- data/spec/sem4r/report_definition/report_definition_service_spec.rb +5 -5
- data/spec/sem4r/report_definition/report_definition_spec.rb +28 -43
- data/{lib/sem4r/cli/commands/cli_list_report.rb → spec/sem4r/report_definition/report_field_spec.rb} +12 -10
- data/spec/sem4r/rexml_parsing_spec.rb +1 -0
- data/spec/sem4r/{services/service_spec.rb → service_spec.rb} +1 -1
- data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +1 -1
- data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +1 -1
- data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +1 -1
- data/spec/sem4r/v13_account/account_service_spec.rb +2 -2
- data/spec/sem4r/v13_report/report_service_spec.rb +2 -2
- data/spec/{sem4r/cli → sem4r_cli}/cli_spec.rb +22 -27
- data/spec/{soap_helpers → sem4r_soap}/soap_attributes_spec.rb +3 -3
- data/spec/{sem4r/services/soap_message_v13_spec.rb → sem4r_soap/soap_response_spec.rb} +10 -15
- data/spec/{sem4r/services/soap_call_spec.rb → sem4r_soap/soap_service_spec.rb} +35 -54
- data/tasks/jeweler.rake +66 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/sem4r.rake +25 -0
- data/tasks/yard.rake +31 -0
- metadata +173 -76
- data/lib/sem4r/ad_extension_override/ad_extension_override_service.rb +0 -30
- data/lib/sem4r/api_counters.rb +0 -8
- data/lib/sem4r/campaign_target/campaign_target_service.rb +0 -30
- data/lib/sem4r/cli/commands/cli_download_report.rb +0 -82
- data/lib/sem4r/services/http_connector.rb +0 -93
- data/lib/sem4r/services/soap_call.rb +0 -122
- data/lib/sem4r/services/soap_connector.rb +0 -139
- data/lib/sem4r/services/soap_message_v13.rb +0 -135
- data/lib/sem4r/services/soap_message_v2010.rb +0 -184
- data/lib/sem4r/v13_traffic_estimator/traffic_estimator_service.rb +0 -30
- data/spec/aggregates_rspec_helper.rb +0 -59
- data/spec/sem4r/report_definition/fixtures/mutate_add-req.xml +0 -24
- data/spec/sem4r/report_definition/fixtures/mutate_add-req_orig.xml +0 -45
|
@@ -23,13 +23,12 @@
|
|
|
23
23
|
#
|
|
24
24
|
# -------------------------------------------------------------------------
|
|
25
25
|
|
|
26
|
-
module
|
|
26
|
+
module Sem4rCli
|
|
27
27
|
|
|
28
|
-
CliInfo =
|
|
28
|
+
CliInfo = define_command_sem4r("info", "show account info") do |account|
|
|
29
29
|
account.p_info
|
|
30
|
-
items = (
|
|
30
|
+
items = (InfoSelector::UsageTypes - [InfoSelector::METHOD_COST]).map do |usage_type|
|
|
31
31
|
n = account.year_unit_cost(usage_type)
|
|
32
|
-
# puts "#{usage_type} -> #{n}"
|
|
33
32
|
OpenStruct.new(:usage_type => usage_type, :n => n)
|
|
34
33
|
end
|
|
35
34
|
report(items, :usage_type, :n)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# -------------------------------------------------------------------------
|
|
3
3
|
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
6
|
# a copy of this software and associated documentation files (the
|
|
7
7
|
# "Software"), to deal in the Software without restriction, including
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
10
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
11
|
# the following conditions:
|
|
12
|
-
#
|
|
12
|
+
#
|
|
13
13
|
# The above copyright notice and this permission notice shall be
|
|
14
14
|
# included in all copies or substantial portions of the Software.
|
|
15
|
-
#
|
|
15
|
+
#
|
|
16
16
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
17
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
18
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
@@ -20,27 +20,34 @@
|
|
|
20
20
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
-
#
|
|
24
23
|
# -------------------------------------------------------------------------
|
|
25
24
|
|
|
26
|
-
module
|
|
27
|
-
|
|
25
|
+
module Sem4rCli
|
|
26
|
+
|
|
27
|
+
#
|
|
28
|
+
# BulkMuteteJob
|
|
29
|
+
#
|
|
30
|
+
class CliJob < CliCommand
|
|
28
31
|
|
|
29
32
|
def self.command
|
|
30
|
-
"
|
|
33
|
+
"job"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.subcommands
|
|
37
|
+
%w{list submit submit_pending delete}
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
def self.description
|
|
34
|
-
"
|
|
41
|
+
"manage bulk mutate job (subcommands: #{subcommands.join(', ')})"
|
|
35
42
|
end
|
|
36
43
|
|
|
37
|
-
def initialize(
|
|
38
|
-
@
|
|
44
|
+
def initialize(sem4r_cli)
|
|
45
|
+
@sem4r_cli = sem4r_cli
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
def command_opt_parser(options)
|
|
42
|
-
opt_parser
|
|
43
|
-
opt_parser.banner = "Usage #{self.class.command} [command_options ] [
|
|
49
|
+
opt_parser = OptionParser.new
|
|
50
|
+
opt_parser.banner = "Usage #{self.class.command} [command_options ] [#{self.class.subcommands.join("|")}]"
|
|
44
51
|
opt_parser.separator ""
|
|
45
52
|
opt_parser.separator "#{self.class.description}"
|
|
46
53
|
opt_parser.on("-h", "--help", "show this message") do
|
|
@@ -51,57 +58,52 @@ module Sem4r
|
|
|
51
58
|
|
|
52
59
|
def parse_and_run(argv)
|
|
53
60
|
options = OpenStruct.new
|
|
54
|
-
rest
|
|
55
|
-
if options.exit
|
|
56
|
-
return false
|
|
57
|
-
end
|
|
61
|
+
rest = command_opt_parser(options).parse(argv)
|
|
62
|
+
return false if options.exit
|
|
58
63
|
|
|
59
64
|
if rest.empty?
|
|
60
65
|
puts "missing command"
|
|
61
66
|
return false
|
|
62
67
|
end
|
|
63
68
|
|
|
64
|
-
account
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
from "20100101"
|
|
86
|
-
to "20100110"
|
|
87
|
-
format "CSV"
|
|
88
|
-
|
|
89
|
-
field "AdGroupId"
|
|
90
|
-
field "Id"
|
|
91
|
-
field "KeywordText"
|
|
92
|
-
field "KeywordMatchType"
|
|
93
|
-
field "Impressions"
|
|
94
|
-
field "Clicks"
|
|
95
|
-
field "Cost"
|
|
96
|
-
end
|
|
97
|
-
rd.save
|
|
98
|
-
puts rd.id
|
|
99
|
-
puts rd.to_s
|
|
100
|
-
account.p_report_definitions
|
|
101
|
-
else
|
|
102
|
-
puts "unknow command"
|
|
69
|
+
account = @sem4r_cli.account
|
|
70
|
+
ret = true
|
|
71
|
+
subcommand = rest[0]
|
|
72
|
+
subcommand_args = rest[1..-1]
|
|
73
|
+
case subcommand
|
|
74
|
+
|
|
75
|
+
when "list"
|
|
76
|
+
Sem4rCli::report(account.jobs, :id, :status)
|
|
77
|
+
|
|
78
|
+
when "delete"
|
|
79
|
+
job_id = rest[1]
|
|
80
|
+
account.job_delete(job_id)
|
|
81
|
+
|
|
82
|
+
when "submit"
|
|
83
|
+
ret = create(account)
|
|
84
|
+
|
|
85
|
+
when "submit_pending"
|
|
86
|
+
ret = create(account, true)
|
|
87
|
+
else
|
|
88
|
+
puts "unknow subcommand '#{subcommand}'; must be one of #{self.class.subcommands.join(", ")}"
|
|
89
|
+
return false
|
|
103
90
|
end
|
|
104
91
|
account.adwords.p_counters
|
|
92
|
+
ret
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
def create(account, pending = false)
|
|
98
|
+
puts "creating example job"
|
|
99
|
+
campaign, ad_group = template_campaign_and_ad_group(account)
|
|
100
|
+
job = template_bulk_mutate_job(campaign, ad_group)
|
|
101
|
+
if pending
|
|
102
|
+
job.num_parts = 3
|
|
103
|
+
end
|
|
104
|
+
result_job = account.job_mutate(JobOperation.add(job))
|
|
105
|
+
puts result_job.to_s
|
|
106
|
+
account.p_jobs
|
|
105
107
|
true
|
|
106
108
|
end
|
|
107
109
|
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
-
#
|
|
24
23
|
# -------------------------------------------------------------------------
|
|
25
24
|
|
|
26
|
-
module
|
|
25
|
+
module Sem4rCli
|
|
27
26
|
|
|
28
|
-
CliListKeywords =
|
|
27
|
+
CliListKeywords = define_command_sem4r("keywords", "list keywords") do |account|
|
|
28
|
+
puts "Collecting keywords from account(s) - please wait"
|
|
29
29
|
|
|
30
30
|
# if the account have client_accounts it is a master
|
|
31
31
|
client_accounts = account.client_accounts
|
|
@@ -33,11 +33,11 @@ module Sem4r
|
|
|
33
33
|
client_accounts = [account]
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
items
|
|
36
|
+
items = []
|
|
37
37
|
need_newline = false
|
|
38
38
|
client_accounts.each do |client_account|
|
|
39
39
|
if need_newline
|
|
40
|
-
puts
|
|
40
|
+
puts
|
|
41
41
|
need_newline = false
|
|
42
42
|
end
|
|
43
43
|
puts "examinate account '#{client_account.credentials.client_email}'"
|
|
@@ -45,19 +45,19 @@ module Sem4r
|
|
|
45
45
|
# puts "examinate campaign '#{campaign}'"
|
|
46
46
|
campaign.ad_groups.each do |ad_group|
|
|
47
47
|
ad_group.criterions.each do |criterion|
|
|
48
|
-
|
|
49
|
-
row
|
|
48
|
+
|
|
49
|
+
row = OpenStruct.new
|
|
50
50
|
row.client = client_account.credentials.client_email
|
|
51
51
|
row.campaign = campaign.name
|
|
52
52
|
row.ad_group = ad_group.name
|
|
53
53
|
|
|
54
54
|
row.type = criterion.type
|
|
55
55
|
case criterion.type
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
when Criterion::Keyword
|
|
57
|
+
row.text = criterion.text
|
|
58
|
+
row.match = criterion.match
|
|
59
|
+
when Criterion::Placement
|
|
60
|
+
row.text = criterion.url
|
|
61
61
|
end
|
|
62
62
|
items << row
|
|
63
63
|
print "."
|
|
@@ -72,6 +72,7 @@ module Sem4r
|
|
|
72
72
|
end
|
|
73
73
|
report(items, :client, :campaign, :ad_group, :type, :text, :match)
|
|
74
74
|
account.adwords.p_counters
|
|
75
|
+
true
|
|
75
76
|
end
|
|
76
77
|
|
|
77
|
-
end
|
|
78
|
+
end # module Sem4rCli
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -------------------------------------------------------------------------
|
|
3
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
# a copy of this software and associated documentation files (the
|
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
# the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be
|
|
14
|
+
# included in all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
# -------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
module Sem4rCli
|
|
26
|
+
|
|
27
|
+
#
|
|
28
|
+
# Manage Sem4r profiles
|
|
29
|
+
#
|
|
30
|
+
class CliProfile < CliCommand
|
|
31
|
+
|
|
32
|
+
def self.command
|
|
33
|
+
"profile"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.subcommands
|
|
37
|
+
%w{list create}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.description
|
|
41
|
+
"manage sem4r profiles (subcommands: #{subcommands.join(', ')})"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def initialize(sem4r_cli)
|
|
45
|
+
@sem4r_cli = sem4r_cli
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def command_opt_parser(options)
|
|
49
|
+
opt_parser = OptionParser.new
|
|
50
|
+
opt_parser.banner = "Usage #{self.class.command} [command_options] [#{self.class.subcommands.join("|")}]"
|
|
51
|
+
opt_parser.separator ""
|
|
52
|
+
opt_parser.separator "#{self.class.description}"
|
|
53
|
+
opt_parser.on("-h", "--help", "show this message") do
|
|
54
|
+
puts opt_parser
|
|
55
|
+
options.exit = true
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def parse_and_run(argv)
|
|
60
|
+
options = OpenStruct.new
|
|
61
|
+
rest = command_opt_parser(options).parse(argv)
|
|
62
|
+
return false if options.exit
|
|
63
|
+
if rest.empty?
|
|
64
|
+
puts "missing command"
|
|
65
|
+
return false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
ret = true
|
|
69
|
+
subcommand = rest[0]
|
|
70
|
+
subcommand_args = rest[1..-1]
|
|
71
|
+
adwords = @sem4r_cli.adwords
|
|
72
|
+
case subcommand
|
|
73
|
+
when "list"
|
|
74
|
+
puts "Profiles:"
|
|
75
|
+
|
|
76
|
+
items = []
|
|
77
|
+
profiles = adwords.profiles
|
|
78
|
+
names = profiles.keys.map &:to_s
|
|
79
|
+
names.sort.each do |s|
|
|
80
|
+
o = OpenStruct.new
|
|
81
|
+
o.name = s
|
|
82
|
+
o.email = profiles[s]['email']
|
|
83
|
+
o.mutable = profiles[s]['mutable']
|
|
84
|
+
o.environment = profiles[s]['environment']
|
|
85
|
+
items << o
|
|
86
|
+
end
|
|
87
|
+
Sem4rCli::report(items, :name, :environment, :email, :mutable)
|
|
88
|
+
when "create"
|
|
89
|
+
puts "Tobe done :-)"
|
|
90
|
+
|
|
91
|
+
else
|
|
92
|
+
puts "unknow subcommand '#{subcommand}'; must be one of #{self.class.subcommands.join(", ")}"
|
|
93
|
+
return false
|
|
94
|
+
end
|
|
95
|
+
ret
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
#
|
|
101
|
+
# read credentials from console (create profile?)
|
|
102
|
+
#
|
|
103
|
+
def read_credentials_from_console
|
|
104
|
+
unless @options.environment
|
|
105
|
+
# The new and improved choose()...
|
|
106
|
+
say("\nThis is the new mode (default)...")
|
|
107
|
+
choose do |menu|
|
|
108
|
+
menu.prompt = "Please choose your favorite programming language? "
|
|
109
|
+
|
|
110
|
+
menu.choice :ruby do
|
|
111
|
+
say("Good choice!")
|
|
112
|
+
end
|
|
113
|
+
menu.choices(:python, :perl) do
|
|
114
|
+
say("Not from around here, are you?")
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
@options.email ||= ask("Enter adwords email: ")
|
|
120
|
+
@options.password ||= ask("Enter adwords password: ") { |q| q.echo = "x" }
|
|
121
|
+
@options.developer_token ||= ask("Enter adwords developer_token: ")
|
|
122
|
+
|
|
123
|
+
config = {
|
|
124
|
+
:environment => @options.environment,
|
|
125
|
+
:email => @options.email,
|
|
126
|
+
:password => @options.password,
|
|
127
|
+
:developer_token => @options.developer_token
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
pp config
|
|
131
|
+
unless agree("credentials are correct?")
|
|
132
|
+
exit
|
|
133
|
+
end
|
|
134
|
+
config
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# -------------------------------------------------------------------------
|
|
3
3
|
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
6
|
# a copy of this software and associated documentation files (the
|
|
7
7
|
# "Software"), to deal in the Software without restriction, including
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
10
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
11
|
# the following conditions:
|
|
12
|
-
#
|
|
12
|
+
#
|
|
13
13
|
# The above copyright notice and this permission notice shall be
|
|
14
14
|
# included in all copies or substantial portions of the Software.
|
|
15
|
-
#
|
|
15
|
+
#
|
|
16
16
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
17
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
18
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
@@ -20,27 +20,34 @@
|
|
|
20
20
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
-
#
|
|
24
23
|
# -------------------------------------------------------------------------
|
|
25
24
|
|
|
26
|
-
module
|
|
27
|
-
|
|
25
|
+
module Sem4rCli
|
|
26
|
+
|
|
27
|
+
#
|
|
28
|
+
# Report Definition (v201008 api)
|
|
29
|
+
#
|
|
30
|
+
class CliRepDef < CliCommand
|
|
28
31
|
|
|
29
32
|
def self.command
|
|
30
|
-
"
|
|
33
|
+
"repdef"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.subcommands
|
|
37
|
+
%w{fields list create}
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
def self.description
|
|
34
|
-
"manage report"
|
|
41
|
+
"manage report definition (subcommands: #{subcommands.join(", ")})"
|
|
35
42
|
end
|
|
36
43
|
|
|
37
|
-
def initialize(
|
|
38
|
-
@
|
|
44
|
+
def initialize(sem4r_cli)
|
|
45
|
+
@sem4r_cli = sem4r_cli
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
def command_opt_parser(options)
|
|
42
|
-
opt_parser
|
|
43
|
-
opt_parser.banner = "Usage #{self.class.command} [command_options ] [
|
|
49
|
+
opt_parser = OptionParser.new
|
|
50
|
+
opt_parser.banner = "Usage #{self.class.command} [command_options ] [#{self.class.subcommands.join("|")}]"
|
|
44
51
|
opt_parser.separator ""
|
|
45
52
|
opt_parser.separator "#{self.class.description}"
|
|
46
53
|
opt_parser.on("-h", "--help", "show this message") do
|
|
@@ -51,26 +58,66 @@ module Sem4r
|
|
|
51
58
|
|
|
52
59
|
def parse_and_run(argv)
|
|
53
60
|
options = OpenStruct.new
|
|
54
|
-
rest
|
|
61
|
+
rest = command_opt_parser(options).parse(argv)
|
|
55
62
|
if options.exit
|
|
56
63
|
return false
|
|
57
64
|
end
|
|
58
65
|
|
|
59
|
-
if rest.
|
|
66
|
+
if rest.empty?
|
|
60
67
|
puts "missing command"
|
|
61
68
|
return false
|
|
62
69
|
end
|
|
63
70
|
|
|
64
|
-
account
|
|
71
|
+
account = @sem4r_cli.account
|
|
72
|
+
ret = true
|
|
73
|
+
subcommand = rest[0]
|
|
74
|
+
subcommand_args = rest[1..-1]
|
|
75
|
+
case subcommand
|
|
76
|
+
when "fields"
|
|
77
|
+
report_type = ReportDefinition::AD_PERFORMANCE_REPORT
|
|
78
|
+
puts "Fields for #{report_type}"
|
|
79
|
+
Sem4rCli::report(account.report_fields(report_type), :field_name, :field_type)
|
|
65
80
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
Sem4r::report(account.reports, :id, :name, :status)
|
|
81
|
+
when "list"
|
|
82
|
+
Sem4rCli::report(account.report_definitions, :id, :name)
|
|
69
83
|
|
|
70
|
-
|
|
71
|
-
|
|
84
|
+
when "delete"
|
|
85
|
+
report_definition_id = rest[1]
|
|
86
|
+
account.report_definition_delete(report_definition_id)
|
|
87
|
+
|
|
88
|
+
when "create"
|
|
89
|
+
ret = create(account)
|
|
90
|
+
else
|
|
91
|
+
puts "unknow subcommand '#{subcommand}'; must be one of #{subcommands.join(", ")}"
|
|
92
|
+
return false
|
|
72
93
|
end
|
|
73
94
|
account.adwords.p_counters
|
|
95
|
+
ret
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def create(account)
|
|
101
|
+
rd = account.report_definition do
|
|
102
|
+
name "Keywords performance report #1290336379254"
|
|
103
|
+
type "KEYWORDS_PERFORMANCE_REPORT"
|
|
104
|
+
date_range "CUSTOM_DATE"
|
|
105
|
+
from "20100101"
|
|
106
|
+
to "20100110"
|
|
107
|
+
format "CSV"
|
|
108
|
+
|
|
109
|
+
field "AdGroupId"
|
|
110
|
+
field "Id"
|
|
111
|
+
field "KeywordText"
|
|
112
|
+
field "KeywordMatchType"
|
|
113
|
+
field "Impressions"
|
|
114
|
+
field "Clicks"
|
|
115
|
+
field "Cost"
|
|
116
|
+
end
|
|
117
|
+
rd.save
|
|
118
|
+
puts rd.id
|
|
119
|
+
puts rd.to_s
|
|
120
|
+
account.p_report_definitions
|
|
74
121
|
true
|
|
75
122
|
end
|
|
76
123
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# -------------------------------------------------------------------------
|
|
3
3
|
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
6
|
# a copy of this software and associated documentation files (the
|
|
7
7
|
# "Software"), to deal in the Software without restriction, including
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
10
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
11
|
# the following conditions:
|
|
12
|
-
#
|
|
12
|
+
#
|
|
13
13
|
# The above copyright notice and this permission notice shall be
|
|
14
14
|
# included in all copies or substantial portions of the Software.
|
|
15
|
-
#
|
|
15
|
+
#
|
|
16
16
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
17
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
18
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
@@ -20,45 +20,108 @@
|
|
|
20
20
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
-
#
|
|
24
23
|
# -------------------------------------------------------------------------
|
|
25
24
|
|
|
26
|
-
module
|
|
25
|
+
module Sem4rCli
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
#
|
|
28
|
+
# report (v13 api)
|
|
29
|
+
#
|
|
30
|
+
class CliReport < CliCommand
|
|
29
31
|
|
|
30
32
|
def self.command
|
|
31
|
-
"
|
|
33
|
+
"report"
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
def self.description
|
|
35
|
-
"
|
|
37
|
+
"manage v13 report"
|
|
36
38
|
end
|
|
37
39
|
|
|
38
|
-
def initialize(
|
|
39
|
-
@
|
|
40
|
+
def initialize(common_args)
|
|
41
|
+
@common_args = common_args
|
|
42
|
+
@subcomands = %w{list download schedule}
|
|
40
43
|
end
|
|
41
44
|
|
|
45
|
+
def parse_and_run(argv)
|
|
46
|
+
options = OpenStruct.new
|
|
47
|
+
rest = command_opt_parser(options).parse(argv)
|
|
48
|
+
return false if options.exit
|
|
49
|
+
|
|
50
|
+
if rest.length == 0
|
|
51
|
+
puts "missing sub command"
|
|
52
|
+
return false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
ret = true
|
|
56
|
+
subcommand = rest[0]
|
|
57
|
+
subcommand_args = rest[1..-1]
|
|
58
|
+
case subcommand
|
|
59
|
+
when "list"
|
|
60
|
+
Sem4rCli::report(@common_args.account.reports, :id, :name, :status)
|
|
61
|
+
|
|
62
|
+
when "download"
|
|
63
|
+
ret = download(subcommand_args)
|
|
64
|
+
|
|
65
|
+
when "schedule"
|
|
66
|
+
ret = schedule(subcommand_args)
|
|
67
|
+
|
|
68
|
+
else
|
|
69
|
+
puts "unknow subcommand '#{subcommand}'; must be one of #{@subcomands.join(", ")}"
|
|
70
|
+
return false
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
@common_args.account.adwords.p_counters
|
|
74
|
+
ret
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
42
79
|
def command_opt_parser(options)
|
|
43
|
-
opt_parser
|
|
44
|
-
opt_parser.banner = "Usage #{self.class.command} [command_options ]
|
|
80
|
+
opt_parser = OptionParser.new
|
|
81
|
+
opt_parser.banner = "Usage #{self.class.command} [command_options ] [#{@subcomands.join("|")}]"
|
|
45
82
|
opt_parser.separator ""
|
|
46
83
|
opt_parser.separator "#{self.class.description}"
|
|
84
|
+
|
|
47
85
|
opt_parser.on("-h", "--help", "show this message") do
|
|
48
86
|
puts opt_parser
|
|
49
87
|
options.exit = true
|
|
50
88
|
end
|
|
51
89
|
end
|
|
52
90
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
91
|
+
#
|
|
92
|
+
# download a v13 report
|
|
93
|
+
#
|
|
94
|
+
def download(args)
|
|
95
|
+
if args.length != 1
|
|
96
|
+
puts "missing report id for 'donwload' subcommand"
|
|
97
|
+
return false
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
report_id = args[0].to_i
|
|
101
|
+
report = @common_args.account.reports.find { |r| r.id == report_id }
|
|
102
|
+
if report.nil?
|
|
103
|
+
puts "report '#{report_id}' not found"
|
|
57
104
|
return false
|
|
58
105
|
end
|
|
59
106
|
|
|
107
|
+
if report.status != 'Completed'
|
|
108
|
+
puts "cannot donwload report with status '#{report.status}'"
|
|
109
|
+
return false
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
path_name = "test_report.xml"
|
|
113
|
+
puts "Download report #{report.id} in #{path_name}"
|
|
114
|
+
report.download(path_name)
|
|
115
|
+
true
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
#
|
|
119
|
+
# schedule and download a v13 report
|
|
120
|
+
#
|
|
121
|
+
def schedule(argv)
|
|
122
|
+
|
|
60
123
|
report = @account.report do
|
|
61
|
-
name 'boh'
|
|
124
|
+
name 'boh'
|
|
62
125
|
type 'Url'
|
|
63
126
|
aggregation 'Daily'
|
|
64
127
|
cross_client true
|
|
@@ -96,9 +159,9 @@ module Sem4r
|
|
|
96
159
|
end
|
|
97
160
|
puts "scheduled job"
|
|
98
161
|
job = report.schedule
|
|
99
|
-
job.wait(
|
|
162
|
+
job.wait(10) { |report, status| puts "status #{status}" }
|
|
100
163
|
report.download("test_report.xml")
|
|
101
|
-
|
|
164
|
+
true
|
|
102
165
|
end
|
|
103
166
|
|
|
104
167
|
end
|