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
@@ -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,63 +20,181 @@
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
- # -------------------------------------------------------------------------
25
-
26
- module Sem4r
23
+ # -------------------------------------------------------------------
24
+
25
+ module Sem4rCli
26
+
27
+ #
28
+ # Macro helper for define new sem4r command
29
+ #
30
+ def self.define_command_sem4r(command_name, description, &block)
31
+ CliCommand.define_command(command_name, description) do |cli|
32
+ account = cli.account
33
+ unless account
34
+ puts "please select a valid account!"
35
+ false
36
+ else
37
+ block.call(account)
38
+ end
39
+ end
40
+ end
27
41
 
28
- class CliCommonArgs
42
+ #
43
+ # CliSem Driver
44
+ # parses common options
45
+ # finds command and instantiate command
46
+ # passes the unparsed parameter to command
47
+ # leaves control to command
48
+ #
49
+ class CliSem < Cli
29
50
 
30
51
  def initialize
31
52
  # defaults
32
53
  @options = OpenStruct.new({
33
- :verbose => true,
34
- :force => false,
35
- :default_logging => true,
36
- # :dump_soap_to_file => true,
37
- # :dump_soap_to_directory => true,
38
- :profile => 'sandbox'
39
- })
54
+ :verbose => true,
55
+ :force => false,
56
+ :default_logging => true,
57
+ # :dump_soap_to_file => true,
58
+ # :dump_soap_to_directory => true,
59
+ :profile => 'sandbox',
60
+ :ask_password => false
61
+ })
40
62
  end
41
63
 
42
- def parse_and_run(argv)
43
- parse(argv)
44
- end
45
-
46
- def parse(argv)
64
+ def parse_and_run(all_args)
47
65
 
48
66
  begin
49
- rest = opt_parser(@options).parse(argv)
67
+ command_args = opt_parser(@options).order(all_args)
50
68
  rescue OptionParser::AmbiguousOption => e
51
69
  puts e.message
52
70
  return false
53
71
  end
72
+ return true if @options.exit
73
+
74
+ if command_args.empty?
75
+ puts "missing command try sem -h for help"
76
+ return false
77
+ end
78
+
79
+ command = command_args[0]
80
+ command_args = command_args[1..-1]
54
81
 
55
- if rest.length > 0
56
- # cannot happen
57
- puts "unknow options #{rest.join}"
82
+ # find command
83
+ if CliCommand.commands[command].nil?
84
+ puts "unknow command #{command}"
58
85
  return false
59
86
  end
60
87
 
61
- if @options.list_profiles
62
- puts "Profiles:"
63
- profiles = Adwords.profiles( @options.config_name )
64
- names = profiles.keys.map &:to_s
65
- names.sort.each do |s|
66
- puts " #{s} (#{profiles[s]['email']})"
88
+ begin
89
+ cmd = CliCommand.commands[command].new(self)
90
+ return cmd.parse_and_run(command_args)
91
+ rescue Sem4rError
92
+ puts "I am so sorry! Something went wrong! (exception #{$!.to_s})"
93
+ return false
94
+ end
95
+ end
96
+
97
+ #
98
+ # initialize adwords according to command line options
99
+ # return [Sem4r::Adwords]
100
+ #
101
+ def adwords
102
+ return @adwords if @adwords
103
+
104
+ #
105
+ # select profile
106
+ #
107
+ options = {}
108
+ if @options.config_name
109
+ options[:config_file] = @options.config_name
110
+ end
111
+ @adwords = Adwords.new(@options.profile, options)
112
+ if @options.verbose
113
+ puts "using #{@adwords.profile} profile"
114
+ puts "config file is #{@adwords.config_file}"
115
+ end
116
+ #
117
+ # Extracts dump soap options
118
+ #
119
+ if @options.default_logging
120
+ configdir = File.join(ENV['HOME'], ".sem4r")
121
+ unless File.exists?(configdir)
122
+ puts "Directory #{configdir} not exists"
123
+ FileUtils.mkdir(configdir)
67
124
  end
125
+ dir = File.join(configdir, Time.new.strftime("%Y%m%d-soap-dump"))
126
+ @options.dump_soap_to_directory = dir
127
+
128
+ file = File.join(configdir, Time.new.strftime("%Y%m%d-sem4r-log"))
129
+ @options.logger = file
130
+ end
131
+
132
+ if @options.dump_soap_to_file
133
+ filename = @options.dump_soap_to_file
134
+ o = {:file => filename}
135
+ @adwords.dump_soap_options(o)
136
+ end
137
+ if @options.dump_soap_to_directory
138
+ dir = @options.dump_soap_to_directory
139
+ o = {:directory => dir, :format => true}
140
+ @adwords.dump_soap_options(o)
141
+ end
142
+ if @options.verbose and adwords.dump_soap?
143
+ puts "Logging soap conversation to '#{adwords.dump_soap_where}'"
144
+ end
145
+ if !@adwords.dump_soap?
146
+ puts "it is highly recommended to activate the dump soap log"
68
147
  end
69
148
 
70
- if @options.ask_password
71
- puts "ask_password"
149
+ #
150
+ # Extracts log options
151
+ #
152
+ # filename = File.join( tmp_dirname, File.basename(example_file).sub(/\.rb$/, ".log") )
153
+ if @options.logger
154
+ # filename = "sem.log"
155
+ @adwords.logger = @options.logger
72
156
  end
157
+ if @adwords.logger
158
+ puts "Logger is active" if @options.verbose
159
+ end
160
+ @adwords
161
+ end
73
162
 
74
- !@options.exit
163
+ #
164
+ # select account according to the command line arguments
165
+ # return [Sem4r::Account]
166
+ #
167
+ def account
168
+ return @account if @account
169
+
170
+ adwords # initialize sem4r lib adwords
171
+ if @options.ask_password or !@adwords.has_password?
172
+ pwd = read_password_from_terminal
173
+ @adwords.password = pwd
174
+ @adwords.save_passwords
175
+ end
176
+
177
+ #
178
+ # select account for command
179
+ #
180
+ if @options.client_email
181
+ account = @adwords.account.client_accounts.find { |c| c.client_email =~ /#{@options.client_email}/ }
182
+ if account.nil?
183
+ puts "client account not found"
184
+ else
185
+ puts "using client #{account.client_email}"
186
+ end
187
+ else
188
+ account = @adwords.account
189
+ end
190
+ @account = account
75
191
  end
76
192
 
193
+ private
194
+
77
195
  def opt_parser(options)
78
- opt_parser = OptionParser.new
79
- opt_parser.banner = "Sem is a simple command line interface using the sem4r library."
196
+ opt_parser = OptionParser.new
197
+ opt_parser.banner = "Sem is a simple command line interface using the sem4r library."
80
198
  opt_parser.separator "It's alpha software, please don't use in production or use it at your risk!"
81
199
  opt_parser.separator "Further information: http://www.sem4r.com"
82
200
  opt_parser.separator ""
@@ -113,7 +231,7 @@ module Sem4r
113
231
 
114
232
  opt_parser.on("-l", "--list-commands", "list commands") do
115
233
  puts "SEM commands are:"
116
- commands = CliCommand.commands.values.sort {|a,b| a.command <=> b.command }
234
+ commands = CliCommand.commands.values.sort { |a, b| a.command <=> b.command }
117
235
  commands.each do |cmd|
118
236
  printf " %-20s %s\n", cmd.command, cmd.description
119
237
  end
@@ -122,6 +240,9 @@ module Sem4r
122
240
  options.exit = true
123
241
  end
124
242
 
243
+ #
244
+ # Logging
245
+ #
125
246
  opt_parser.separator ""
126
247
  opt_parser.separator "logging options: "
127
248
  opt_parser.separator ""
@@ -130,171 +251,70 @@ module Sem4r
130
251
  options.logger = v
131
252
  end
132
253
 
133
- opt_parser.on("-f", "--dump-file FILE", "dump soap conversation to file") do |v|
254
+ opt_parser.on("--dump-file FILE", "dump soap conversation to file") do |v|
134
255
  options.dump_soap_to_file = v
135
256
  end
136
257
 
137
258
  str = "dump soap conversation to directory: each \n"
138
259
  str << (" " * 37) + "request/response is in a single file"
139
- opt_parser.on("-d", "--dump-dir DIRECTORY", str) do |v|
260
+ opt_parser.on("--dump-dir DIRECTORY", str) do |v|
140
261
  options.dump_soap_to_directory = v
141
262
  end
142
263
 
264
+ #
265
+ # Profile - Configuration
266
+ #
143
267
  opt_parser.separator ""
144
268
  opt_parser.separator "profile and credentials options: "
145
269
  opt_parser.separator " credentials options overwrite profile attributes"
146
270
  opt_parser.separator ""
147
271
 
148
- str = "file where profiles are defined\n"
272
+ str = "file where profiles are defined\n"
149
273
  str << (" " * 37) + "(default $HOME/.sem4r/sem4r.yaml)"
150
274
  opt_parser.on("--config CONFIG", str) do |config|
151
275
  options.config_name = config
152
276
  end
153
277
 
154
- opt_parser.on("--list-profiles", "list profiles") do
155
- options.list_profiles = true
156
- options.exit = true
157
- end
158
-
159
278
  opt_parser.on("-p", "--profile PROFILE", "select profile (default is sandbox)") do |profile|
160
279
  options.profile = profile
161
280
  end
162
281
 
163
282
  # email
164
283
  opt_parser.on("--email EMAIL",
165
- "email of adwords account") do |email|
284
+ "email of adwords account") do |email|
166
285
  options.email = email
167
286
  end
168
287
 
169
288
  # password
170
- opt_parser.on("--password [PASSWORD]",
171
- "password of adwords account",
172
- "If password is not given it's asked from the tty") do |password|
173
- options.ask_password = !password
289
+ opt_parser.on("-a", "--ask-password",
290
+ "ask password on terminal") do
291
+ options.ask_password = true
292
+ end
293
+
294
+ opt_parser.on("--password PASSWORD",
295
+ "password of adwords account") do |password|
174
296
  options.password = password if password
175
297
  end
176
298
 
177
299
  # developer token
178
300
  opt_parser.on("--token TOKEN",
179
- "developer token to access adwords api") do |token|
301
+ "developer token to access adwords api") do |token|
180
302
  options.developer_token = token
181
303
  end
182
304
 
183
305
  # client account
184
306
  opt_parser.on("-c", "--client EMAIL",
185
- "email for client account") do |email|
307
+ "email for client account") do |email|
186
308
  options.client_email = email
187
309
  end
188
310
  opt_parser.separator ""
189
311
  opt_parser
190
312
  end
191
313
 
192
- def read_credentials_from_console
193
- unless @options.environment
194
- # The new and improved choose()...
195
- say("\nThis is the new mode (default)...")
196
- choose do |menu|
197
- menu.prompt = "Please choose your favorite programming language? "
198
-
199
- menu.choice :ruby do say("Good choice!") end
200
- menu.choices(:python, :perl) do say("Not from around here, are you?") end
201
- end
202
- end
203
-
204
- @options.email ||= ask("Enter adwords email: ")
205
- @options.password ||= ask("Enter adwords password: ") { |q| q.echo = "x" }
206
- @options.developer_token ||= ask("Enter adwords developer_token: ")
207
-
208
- config = {
209
- :environment => @options.environment,
210
- :email => @options.email,
211
- :password => @options.password,
212
- :developer_token => @options.developer_token
213
- }
214
-
215
- pp config
216
- unless agree("credentials are correct?")
217
- exit
218
- end
219
- config
220
- end
221
-
222
- def account
223
- #
224
- # select profile
225
- #
226
- options = {}
227
- if @options.config_name
228
- options[:config_file] = @options.config_name
229
- end
230
- adwords = Adwords.new( @options.profile, options )
231
- if @options.verbose
232
- puts "using #{adwords.profile} profile"
233
- puts "config file is #{adwords.config_file}"
234
- end
235
-
236
- #
237
- # logging soap conversation
238
- #
239
- if @options.default_logging
240
- configdir = File.join( ENV['HOME'], ".sem4r" )
241
- unless File.exists?(configdir)
242
- puts "Directory #{configdir} not exists"
243
- FileUtils.mkdir(configdir)
244
- end
245
- dir = File.join(configdir, Time.new.strftime("%Y%m%d-soap-dump"))
246
- @options.dump_soap_to_directory = dir
247
-
248
- file = File.join(configdir, Time.new.strftime("%Y%m%d-sem4r-log"))
249
- @options.logger = file
250
- end
251
-
252
- if @options.dump_soap_to_file
253
- filename = @options.dump_soap_to_file
254
- o = { :file => filename }
255
- adwords.dump_soap_options( o )
256
- end
257
- if @options.dump_soap_to_directory
258
- dir = @options.dump_soap_to_directory
259
- o = { :directory => dir, :format => true }
260
- adwords.dump_soap_options( o )
261
- end
262
- if @options.verbose and adwords.dump_soap?
263
- puts "Logging soap conversation to '#{adwords.dump_soap_where}'"
264
- end
265
- if !adwords.dump_soap?
266
- puts "it is highly recommended to activate the dump soap log"
267
- end
268
-
269
- #
270
- # logging
271
- #
272
- # filename = File.join( tmp_dirname, File.basename(example_file).sub(/\.rb$/, ".log") )
273
- if @options.logger
274
- # filename = "sem.log"
275
- adwords.logger = @options.logger
276
- end
277
- if adwords.logger
278
- puts "Logger activated"
279
- end
280
- # adwords.logger = Logger.new(STDOUT)
281
-
282
- #
283
- # select account for command
284
- #
285
- if @options.client_email
286
- account = adwords.account.client_accounts.find{ |c| c.client_email =~ /^#{@options.client_email}/ }
287
- if account.nil?
288
- puts "client account not found"
289
- else
290
- puts "using client #{account.client_email}"
291
- end
292
- else
293
- account = adwords.account
294
- end
295
- return account
314
+ def read_password_from_terminal
315
+ ask("Enter your password: ") { |q| q.echo = "x" }
296
316
  end
297
317
 
298
318
  end
299
319
 
300
- end
320
+ end # module Sem4rCli
@@ -20,13 +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
- CliListAds = CliCommand.define_command("ads", "list ads") do |account|
29
- puts "List AdGroup Advertising"
27
+ CliListAds = define_command_sem4r("ads", "list ads") do |account|
28
+ puts "Collecting ads from account(s) - please wait"
30
29
 
31
30
  # if the accounts have client_accounts it is a master
32
31
  client_accounts = account.client_accounts
@@ -34,7 +33,7 @@ module Sem4r
34
33
  client_accounts = [account]
35
34
  end
36
35
 
37
- items = []
36
+ items = []
38
37
  need_newline = false
39
38
 
40
39
  client_accounts.each do |client_account|
@@ -43,14 +42,13 @@ module Sem4r
43
42
  need_newline = false
44
43
  end
45
44
 
46
- #--
47
- puts "examinate account '#{client_account.credentials.client_email}'"
45
+ puts "look in account '#{client_account.credentials.client_email}'"
48
46
  client_account.campaigns.each do |campaign|
49
47
  # puts "examinate campaign '#{campaign}'"
50
48
  campaign.ad_groups.each do |ad_group|
51
49
  # puts "examinate adgroup '#{ad_group}'"
52
50
  ad_group.ads.each do |ad|
53
- o = OpenStruct.new
51
+ o = OpenStruct.new
54
52
  o.client = client_account.credentials.client_email
55
53
  o.campaign = campaign.name
56
54
  o.ad_group = ad_group.name
@@ -62,7 +60,6 @@ module Sem4r
62
60
  need_newline = true
63
61
  end
64
62
  end
65
- #--
66
63
 
67
64
  end
68
65
  if need_newline
@@ -71,5 +68,6 @@ module Sem4r
71
68
  end
72
69
  report(items, :client, :campaign, :ad_group, :url, :display_url)
73
70
  account.adwords.p_counters
71
+ true
74
72
  end
75
73
  end
@@ -0,0 +1,69 @@
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
+ CliListCampaign = define_command_sem4r("campaigns", "list campaigns") do |account|
28
+ puts "Collecting campaign from account(s) - please wait"
29
+
30
+ # if the accounts have client_accounts it is a master
31
+ client_accounts = account.client_accounts
32
+ if client_accounts.empty?
33
+ client_accounts = [account]
34
+ end
35
+
36
+ items = []
37
+ need_newline = false
38
+
39
+ client_accounts.each do |client_account|
40
+ if need_newline
41
+ puts
42
+ need_newline = false
43
+ end
44
+
45
+ puts "look in account '#{client_account.credentials.client_email}'"
46
+ client_account.campaigns.each do |campaign|
47
+
48
+ o = OpenStruct.new
49
+ o.client = client_account.credentials.client_email
50
+ o.id = campaign.id
51
+ o.name = campaign.name
52
+ o.status = campaign.status
53
+ items << o
54
+
55
+ print "."
56
+ need_newline = true
57
+ end
58
+ end
59
+
60
+ if need_newline
61
+ puts
62
+ need_newline = false
63
+ end
64
+ report(items, :client, :id, :name, :status)
65
+ account.adwords.p_counters
66
+ true
67
+ end
68
+
69
+ end
@@ -23,9 +23,9 @@
23
23
  #
24
24
  # -------------------------------------------------------------------------
25
25
 
26
- module Sem4r
26
+ module Sem4rCli
27
27
 
28
- CliListClient = CliCommand.define_command("clients", "list clients account") do |account|
28
+ CliListClient = define_command_sem4r("clients", "list clients account") do |account|
29
29
  puts account.adwords.to_s
30
30
  puts account.to_s
31
31
  account.p_client_accounts
@@ -23,8 +23,11 @@
23
23
  #
24
24
  # -------------------------------------------------------------------------
25
25
 
26
- module Sem4r
26
+ module Sem4rCli
27
27
 
28
+ #
29
+ # idea
30
+ #
28
31
  class CliIdeas < CliCommand
29
32
 
30
33
  def self.command
@@ -39,8 +42,29 @@ module Sem4r
39
42
  @common_args = common_args
40
43
  end
41
44
 
45
+ def parse_and_run(argv)
46
+ options = OpenStruct.new
47
+ rest = opt_parser(options).parse(argv)
48
+ return false if options.exit
49
+
50
+ if rest.length < 1
51
+ puts "keyword missing; see help"
52
+ return false
53
+ end
54
+
55
+ keyword = rest[1]
56
+ account = @common_args.account
57
+ unless account
58
+ puts "select an account!"
59
+ return false
60
+ end
61
+ _run(account, keyword)
62
+ end
63
+
64
+ private
65
+
42
66
  def opt_parser(options)
43
- opt_parser = OptionParser.new
67
+ opt_parser = OptionParser.new
44
68
  opt_parser.banner= "#{self.class.description}"
45
69
  opt_parser.separator "Usage: sem [options] idea <keyword>"
46
70
 
@@ -53,31 +77,13 @@ module Sem4r
53
77
  end
54
78
  end
55
79
 
56
- def parse_and_run(argv)
57
- options = OpenStruct.new
58
- rest = opt_parser(options).parse( argv )
59
- return false if options.exit
60
- if rest.length < 1
61
- puts "keyword missing see help"
62
- return false
63
- end
64
-
65
- @keyword = rest[1]
66
- account = @common_args.account
67
- unless account
68
- puts "select an account!"
69
- else
70
- _run account
71
- end
72
- end
73
-
74
- def _run(account)
75
- ideas = account.targeting_idea do
76
- idea_type "KEYWORD"
80
+ def _run(account, keyword)
81
+ ideas = account.targeting_idea do
82
+ idea_type "KEYWORD"
77
83
  request_type "IDEAS"
78
84
 
79
85
  related_to_keyword_search_parameter do
80
- text @keyword
86
+ text keyword
81
87
  match_type 'EXACT'
82
88
  end
83
89
  end
@@ -86,16 +92,18 @@ module Sem4r
86
92
  ideas.each do |i|
87
93
  i.each do |a|
88
94
  next if a.class != TKeywordAttribute
89
- o = OpenStruct.new
95
+ o = OpenStruct.new
90
96
  o.text = a.text
91
97
  o.match = a.match_type
92
98
  items << o
93
99
  end
94
100
  end
95
101
 
96
- Sem4r::report(items, :text, :match)
102
+ Sem4rCli::report(items, :text, :match)
97
103
  account.adwords.p_counters
104
+ true
98
105
  end
99
106
 
100
107
  end
101
- end
108
+
109
+ end # module Sem4rCli