sem4r 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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