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.
Files changed (175) hide show
  1. data/Gemfile +13 -2
  2. data/Gemfile.lock +13 -7
  3. data/README.rdoc +44 -7
  4. data/Rakefile +2 -122
  5. data/VERSION.yml +1 -1
  6. data/bin/sem +1 -0
  7. data/examples_sem4r/01_get_account.rb +1 -0
  8. data/examples_sem4r/02_get_info.rb +1 -0
  9. data/examples_sem4r/03_list_ad.rb +1 -0
  10. data/examples_sem4r/04_list_keywords.rb +1 -0
  11. data/examples_sem4r/05_request_report.rb +25 -14
  12. data/examples_sem4r/{05_request_report_2010.rb → 06_request_report_definition.rb} +2 -4
  13. data/examples_sem4r/{06_create_campaigns.rb → 07_create_campaigns.rb} +1 -0
  14. data/examples_sem4r/{07_create_campaigns_block.rb → 08_create_campaigns_block.rb} +1 -0
  15. data/examples_sem4r/{07_create_campaigns_simple.rb → 09_create_campaigns_simple.rb} +1 -0
  16. data/examples_sem4r/{08_ad_params.rb → 10_ad_params.rb} +1 -0
  17. data/examples_sem4r/{09_targeting_idea.rb → 11_targeting_idea.rb} +1 -0
  18. data/examples_sem4r/{10_get_location.rb → 12_get_location.rb} +1 -0
  19. data/examples_sem4r/{11_submit_bulk_job.rb → 13_submit_bulk_job.rb} +1 -1
  20. data/examples_sem4r/{12_list_bulk_job.rb → 14_list_bulk_job.rb} +3 -0
  21. data/examples_sem4r/30_prune_empty_adgroup.rb +1 -0
  22. data/examples_sem4r/31_empty_accounts.rb +1 -0
  23. data/examples_sem4r/example_helper.rb +2 -1
  24. data/lib/sem4r/ad_group/ad_group.rb +22 -7
  25. data/lib/sem4r/ad_group/ad_group_bids.rb +1 -1
  26. data/lib/sem4r/ad_group/ad_group_service.rb +12 -5
  27. data/lib/sem4r/ad_group_ad/ad_group_ad.rb +1 -0
  28. data/lib/sem4r/ad_group_ad/ad_group_ad_operations.rb +1 -0
  29. data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +14 -9
  30. data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +16 -25
  31. data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +18 -14
  32. data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +27 -19
  33. data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +2 -1
  34. data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +1 -0
  35. data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +9 -4
  36. data/lib/sem4r/ad_group_criterion/criterion.rb +1 -0
  37. data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +1 -0
  38. data/lib/sem4r/ad_group_criterion/criterion_placement.rb +1 -0
  39. data/lib/sem4r/ad_param/ad_param.rb +24 -8
  40. data/lib/sem4r/ad_param/ad_param_service.rb +8 -5
  41. data/lib/sem4r/adwords.rb +232 -76
  42. data/lib/sem4r/base.rb +1 -1
  43. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +41 -35
  44. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_account_extension.rb +49 -15
  45. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_selector.rb +29 -20
  46. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +13 -14
  47. data/lib/sem4r/bulk_mutate_job/job_operations.rb +1 -1
  48. data/lib/sem4r/campaign/campaign.rb +1 -0
  49. data/lib/sem4r/campaign/campaign_account_extension.rb +2 -1
  50. data/lib/sem4r/campaign/campaign_service.rb +9 -5
  51. data/lib/sem4r/credentials.rb +11 -5
  52. data/lib/sem4r/geo_location/address.rb +56 -0
  53. data/lib/sem4r/geo_location/geo_location_account_extension.rb +27 -6
  54. data/lib/sem4r/geo_location/geo_location_selector.rb +57 -0
  55. data/lib/sem4r/geo_location/geo_location_service.rb +9 -16
  56. data/lib/sem4r/info/info_account_extension.rb +3 -2
  57. data/lib/sem4r/info/info_selector.rb +2 -1
  58. data/lib/sem4r/info/info_service.rb +10 -3
  59. data/lib/sem4r/operation.rb +39 -20
  60. data/lib/sem4r/report_definition/report_definition.rb +37 -19
  61. data/lib/sem4r/report_definition/report_definition_account_extension.rb +66 -16
  62. data/lib/sem4r/report_definition/report_definition_operation.rb +2 -2
  63. data/lib/sem4r/report_definition/report_definition_selector.rb +1 -1
  64. data/lib/sem4r/report_definition/report_definition_service.rb +11 -7
  65. data/lib/sem4r/report_definition/report_field.rb +3 -2
  66. data/lib/sem4r/sem4r_templates.rb +77 -0
  67. data/lib/sem4r/{services/service.rb → service.rb} +23 -23
  68. data/lib/sem4r/targeting_idea/targeting_idea.rb +4 -4
  69. data/lib/sem4r/targeting_idea/targeting_idea_account_extension.rb +1 -1
  70. data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +6 -6
  71. data/lib/sem4r/targeting_idea/targeting_idea_service.rb +7 -5
  72. data/lib/sem4r/v13_account/account_account_extension.rb +7 -10
  73. data/lib/sem4r/v13_account/account_service.rb +10 -4
  74. data/lib/sem4r/v13_account/billing_address.rb +2 -2
  75. data/lib/sem4r/v13_report/report_service.rb +11 -9
  76. data/lib/sem4r.rb +46 -31
  77. data/lib/{sem4r/cli → sem4r_cli}/cli_helpers.rb +3 -2
  78. data/lib/{sem4r/cli/cli_command.rb → sem4r_cli/cli_mini_framework.rb} +77 -32
  79. data/lib/{sem4r/cli/cli_common_args.rb → sem4r_cli/cli_sem.rb} +177 -157
  80. data/lib/{sem4r/cli/commands/cli_list_ads.rb → sem4r_cli/commands/cli_ads.rb} +7 -9
  81. data/lib/sem4r_cli/commands/cli_campaign.rb +69 -0
  82. data/lib/{sem4r/cli/commands/cli_list_client.rb → sem4r_cli/commands/cli_clients.rb} +2 -2
  83. data/lib/{sem4r/cli → sem4r_cli}/commands/cli_ideas.rb +35 -27
  84. data/lib/{sem4r/cli → sem4r_cli}/commands/cli_info.rb +3 -4
  85. data/lib/{sem4r/cli/commands/cli_repdef.rb → sem4r_cli/commands/cli_job.rb} +57 -55
  86. data/lib/{sem4r/cli/commands/cli_list_keywords.rb → sem4r_cli/commands/cli_keywords.rb} +14 -13
  87. data/lib/sem4r_cli/commands/cli_profile.rb +138 -0
  88. data/lib/{sem4r/cli/commands/cli_report.rb → sem4r_cli/commands/cli_repdef.rb} +67 -20
  89. data/lib/{sem4r/cli/commands/cli_request_report.rb → sem4r_cli/commands/cli_report.rb} +82 -19
  90. data/lib/sem4r_cli.rb +5 -7
  91. data/lib/sem4r_soap/http_connector.rb +206 -0
  92. data/lib/{soap_helpers → sem4r_soap}/soap_attributes.rb +8 -3
  93. data/lib/{sem4r/services → sem4r_soap}/soap_dumper.rb +36 -20
  94. data/lib/{sem4r/services → sem4r_soap}/soap_error.rb +5 -2
  95. data/lib/sem4r_soap/soap_response.rb +75 -0
  96. data/lib/sem4r_soap/soap_service.rb +137 -0
  97. data/lib/{sem4r/cli/cli_sem.rb → sem4r_soap/soap_service_v13.rb} +27 -28
  98. data/lib/sem4r_soap/soap_service_v2010.rb +80 -0
  99. data/lib/sem4r_soap.rb +17 -0
  100. data/sem4r.gemspec +93 -58
  101. data/spec/build_fixtures.rb +49 -42
  102. data/spec/fixtures/password.example.yml +3 -0
  103. data/spec/fixtures/sem4r.example.yml +6 -0
  104. data/spec/fixtures/{services/error.xml → soap_error.xml} +0 -0
  105. data/spec/fixtures/soap_error2.xml +29 -0
  106. data/spec/helpers/dump_interceptor.rb +90 -0
  107. data/spec/helpers/fixtures_bulk_mutate_job.rb +48 -0
  108. data/spec/helpers/fixtures_geo_location.rb +45 -0
  109. data/{lib/sem4r/campaign_criterion/campaign_criterion_service.rb → spec/helpers/fixtures_info.rb} +10 -6
  110. data/spec/helpers/fixtures_report_definition.rb +65 -0
  111. data/spec/{rspec_hash.rb → helpers/rspec_hash.rb} +1 -0
  112. data/spec/{rspec_matchers.rb → helpers/rspec_matchers.rb} +46 -19
  113. data/spec/{rspec_sem4r_helper.rb → helpers/rspec_sem4r_helper.rb} +19 -16
  114. data/spec/{sem4r_stubs.rb → helpers/sem4r_stubs.rb} +5 -4
  115. data/spec/rspec_helper.rb +4 -4
  116. data/spec/sem4r/account_spec.rb +2 -3
  117. data/spec/sem4r/ad_group/ad_group_service_spec.rb +1 -1
  118. data/spec/sem4r/ad_group/ad_group_spec.rb +1 -1
  119. data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +3 -3
  120. data/spec/sem4r/adwords_spec.rb +62 -39
  121. data/{lib/sem4r/cli/commands/cli_list_campaign.rb → spec/sem4r/bulk_mutate_job/bulk_mutate_job_selector_spec.rb} +14 -11
  122. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +2 -3
  123. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +23 -17
  124. data/spec/sem4r/bulk_mutate_job/fixtures/get-list_job-req.xml +35 -0
  125. data/spec/sem4r/bulk_mutate_job/fixtures/get-list_job-res.xml +417 -0
  126. data/spec/sem4r/bulk_mutate_job/fixtures/mutate-add_job-req.xml +106 -0
  127. data/spec/sem4r/bulk_mutate_job/fixtures/mutate-add_job-res.xml +48 -0
  128. data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +5 -7
  129. data/spec/sem4r/campaign/campaign_service_spec.rb +2 -2
  130. data/spec/sem4r/credentials_spec.rb +10 -8
  131. data/spec/sem4r/geo_location/address_spec.rb +62 -0
  132. data/spec/sem4r/geo_location/fixtures/get-req.xml +42 -0
  133. data/spec/sem4r/geo_location/fixtures/get-res.xml +60 -0
  134. data/spec/sem4r/info/fixtures/get-req.xml +34 -0
  135. data/spec/sem4r/info/fixtures/get-res.xml +27 -0
  136. data/spec/sem4r/nokogiri_parsing_spec.rb +1 -0
  137. data/spec/sem4r/operation_spec.rb +72 -0
  138. data/spec/sem4r/report_definition/fixtures/get-list-repdef-req.xml +22 -0
  139. data/spec/sem4r/report_definition/fixtures/get-list-repdef-res.xml +73 -0
  140. data/spec/sem4r/report_definition/fixtures/getReportFields-req.xml +24 -0
  141. data/spec/sem4r/report_definition/fixtures/getReportFields-res.xml +1199 -0
  142. data/spec/sem4r/report_definition/fixtures/mutate-add-report-req.xml +63 -0
  143. data/spec/sem4r/report_definition/fixtures/mutate-add-report-res.xml +68 -0
  144. data/spec/sem4r/report_definition/report_definition_service_spec.rb +5 -5
  145. data/spec/sem4r/report_definition/report_definition_spec.rb +28 -43
  146. data/{lib/sem4r/cli/commands/cli_list_report.rb → spec/sem4r/report_definition/report_field_spec.rb} +12 -10
  147. data/spec/sem4r/rexml_parsing_spec.rb +1 -0
  148. data/spec/sem4r/{services/service_spec.rb → service_spec.rb} +1 -1
  149. data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +1 -1
  150. data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +1 -1
  151. data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +1 -1
  152. data/spec/sem4r/v13_account/account_service_spec.rb +2 -2
  153. data/spec/sem4r/v13_report/report_service_spec.rb +2 -2
  154. data/spec/{sem4r/cli → sem4r_cli}/cli_spec.rb +22 -27
  155. data/spec/{soap_helpers → sem4r_soap}/soap_attributes_spec.rb +3 -3
  156. data/spec/{sem4r/services/soap_message_v13_spec.rb → sem4r_soap/soap_response_spec.rb} +10 -15
  157. data/spec/{sem4r/services/soap_call_spec.rb → sem4r_soap/soap_service_spec.rb} +35 -54
  158. data/tasks/jeweler.rake +66 -0
  159. data/tasks/rspec.rake +21 -0
  160. data/tasks/sem4r.rake +25 -0
  161. data/tasks/yard.rake +31 -0
  162. metadata +173 -76
  163. data/lib/sem4r/ad_extension_override/ad_extension_override_service.rb +0 -30
  164. data/lib/sem4r/api_counters.rb +0 -8
  165. data/lib/sem4r/campaign_target/campaign_target_service.rb +0 -30
  166. data/lib/sem4r/cli/commands/cli_download_report.rb +0 -82
  167. data/lib/sem4r/services/http_connector.rb +0 -93
  168. data/lib/sem4r/services/soap_call.rb +0 -122
  169. data/lib/sem4r/services/soap_connector.rb +0 -139
  170. data/lib/sem4r/services/soap_message_v13.rb +0 -135
  171. data/lib/sem4r/services/soap_message_v2010.rb +0 -184
  172. data/lib/sem4r/v13_traffic_estimator/traffic_estimator_service.rb +0 -30
  173. data/spec/aggregates_rspec_helper.rb +0 -59
  174. data/spec/sem4r/report_definition/fixtures/mutate_add-req.xml +0 -24
  175. 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 Sem4r
26
+ module Sem4rCli
27
27
 
28
- CliInfo = CliCommand.define_command("info", "account info") do |account|
28
+ CliInfo = define_command_sem4r("info", "show account info") do |account|
29
29
  account.p_info
30
- items = (Account::UsageTypes - [Account::METHOD_COST]).map do |usage_type|
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 Sem4r
27
- class CliRepDef < CliCommand
25
+ module Sem4rCli
26
+
27
+ #
28
+ # BulkMuteteJob
29
+ #
30
+ class CliJob < CliCommand
28
31
 
29
32
  def self.command
30
- "repdef"
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
- "report definition"
41
+ "manage bulk mutate job (subcommands: #{subcommands.join(', ')})"
35
42
  end
36
43
 
37
- def initialize(common_args)
38
- @common_args = common_args
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 = OptionParser.new
43
- opt_parser.banner = "Usage #{self.class.command} [command_options ] [fields|list|create]"
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 = command_opt_parser(options).parse( argv )
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 = @common_args.account
65
-
66
- case rest[0]
67
-
68
- when "fields"
69
- account.report_fields.each do |f|
70
- puts f.to_s
71
- end
72
-
73
- when "list"
74
- account.p_report_definitions
75
-
76
- when "delete"
77
- report_definition_id = rest[1]
78
- account.report_definition_delete(report_definition_id)
79
-
80
- when "create"
81
- rd = account.report_definition do
82
- name "Keywords performance report #1290336379254"
83
- type "KEYWORDS_PERFORMANCE_REPORT"
84
- date_range "CUSTOM_DATE"
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 Sem4r
25
+ module Sem4rCli
27
26
 
28
- CliListKeywords = CliCommand.define_command("keywords", "list keywords") do |account |
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 = OpenStruct.new
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
- when Criterion::Keyword
57
- row.text = criterion.text
58
- row.match = criterion.match
59
- when Criterion::Placement
60
- row.text = criterion.url
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 Sem4r
27
- class CliReport < CliCommand
25
+ module Sem4rCli
26
+
27
+ #
28
+ # Report Definition (v201008 api)
29
+ #
30
+ class CliRepDef < CliCommand
28
31
 
29
32
  def self.command
30
- "report"
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(common_args)
38
- @common_args = common_args
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 = OptionParser.new
43
- opt_parser.banner = "Usage #{self.class.command} [command_options ] [fields|list|create]"
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 = command_opt_parser(options).parse( argv )
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.length != 1
66
+ if rest.empty?
60
67
  puts "missing command"
61
68
  return false
62
69
  end
63
70
 
64
- account = @common_args.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
- case rest[0]
67
- when "list"
68
- Sem4r::report(account.reports, :id, :name, :status)
81
+ when "list"
82
+ Sem4rCli::report(account.report_definitions, :id, :name)
69
83
 
70
- else
71
- puts "unknow command"
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 Sem4r
25
+ module Sem4rCli
27
26
 
28
- class CliRequestReport < CliCommand
27
+ #
28
+ # report (v13 api)
29
+ #
30
+ class CliReport < CliCommand
29
31
 
30
32
  def self.command
31
- "request"
33
+ "report"
32
34
  end
33
35
 
34
36
  def self.description
35
- "schedule a report"
37
+ "manage v13 report"
36
38
  end
37
39
 
38
- def initialize(account)
39
- @account = account
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 = OptionParser.new
44
- opt_parser.banner = "Usage #{self.class.command} [command_options ] <report_id>"
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
- def parse_and_run(argv)
54
- options = OpenStruct.new
55
- rest = command_opt_parser(options).parse( argv )
56
- if options.exit
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(5) { |report, status| puts "status #{status}" }
162
+ job.wait(10) { |report, status| puts "status #{status}" }
100
163
  report.download("test_report.xml")
101
- account.adwords.p_counters
164
+ true
102
165
  end
103
166
 
104
167
  end