sem4r 0.1.1

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 (187) hide show
  1. data/LICENSE +22 -0
  2. data/README.rdoc +74 -0
  3. data/Rakefile +126 -0
  4. data/VERSION.yml +5 -0
  5. data/bin/sem +34 -0
  6. data/config/sem4r.example.yml +51 -0
  7. data/examples_blog/2009-11-29-hello-world.rb +12 -0
  8. data/examples_blog/2009-12-12-create-campaign.rb +29 -0
  9. data/examples_blog/2010-02-06-constants-scope.rb +8 -0
  10. data/examples_blog/2010-02-07-ad-parameters.rb +47 -0
  11. data/examples_sem4r/01_get_account.rb +37 -0
  12. data/examples_sem4r/02_get_info.rb +32 -0
  13. data/examples_sem4r/03_list_ad.rb +47 -0
  14. data/examples_sem4r/04_list_keywords.rb +54 -0
  15. data/examples_sem4r/05_request_report.rb +51 -0
  16. data/examples_sem4r/05_request_report_2010.rb +40 -0
  17. data/examples_sem4r/06_create_campaigns.rb +86 -0
  18. data/examples_sem4r/07_create_campaigns_block.rb +99 -0
  19. data/examples_sem4r/07_create_campaigns_simple.rb +65 -0
  20. data/examples_sem4r/08_ad_params.rb +70 -0
  21. data/examples_sem4r/09_targeting_idea.rb +59 -0
  22. data/examples_sem4r/10_get_location.rb +28 -0
  23. data/examples_sem4r/11_submit_bulk_job.rb +82 -0
  24. data/examples_sem4r/12_list_bulk_job.rb +29 -0
  25. data/examples_sem4r/30_prune_empty_adgroup.rb +50 -0
  26. data/examples_sem4r/31_empty_accounts.rb +40 -0
  27. data/examples_sem4r/example_helper.rb +115 -0
  28. data/lib/sem4r/account.rb +349 -0
  29. data/lib/sem4r/ad_extension_override/ad_extension_override_service.rb +30 -0
  30. data/lib/sem4r/ad_group/ad_group.rb +340 -0
  31. data/lib/sem4r/ad_group/ad_group_bids.rb +170 -0
  32. data/lib/sem4r/ad_group/ad_group_service.rb +75 -0
  33. data/lib/sem4r/ad_group/mobile_ad_image.rb +33 -0
  34. data/lib/sem4r/ad_group_ad/ad_group_ad.rb +98 -0
  35. data/lib/sem4r/ad_group_ad/ad_group_ad_operations.rb +38 -0
  36. data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +56 -0
  37. data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +137 -0
  38. data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +98 -0
  39. data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +144 -0
  40. data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +115 -0
  41. data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +35 -0
  42. data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +58 -0
  43. data/lib/sem4r/ad_group_criterion/criterion.rb +67 -0
  44. data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +80 -0
  45. data/lib/sem4r/ad_group_criterion/criterion_placement.rb +66 -0
  46. data/lib/sem4r/ad_param/ad_param.rb +96 -0
  47. data/lib/sem4r/ad_param/ad_param_operation.rb +34 -0
  48. data/lib/sem4r/ad_param/ad_param_service.rb +59 -0
  49. data/lib/sem4r/adwords.rb +242 -0
  50. data/lib/sem4r/api_counters.rb +7 -0
  51. data/lib/sem4r/base.rb +43 -0
  52. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +108 -0
  53. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_selector.rb +56 -0
  54. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +57 -0
  55. data/lib/sem4r/bulk_mutate_job/job_operations.rb +35 -0
  56. data/lib/sem4r/campaign/campaign.rb +193 -0
  57. data/lib/sem4r/campaign/campaign_service.rb +91 -0
  58. data/lib/sem4r/campaign_criterion/campaign_criterion_service.rb +30 -0
  59. data/lib/sem4r/campaign_target/campaign_target_service.rb +30 -0
  60. data/lib/sem4r/cli/cli_command.rb +101 -0
  61. data/lib/sem4r/cli/cli_commands.rb +60 -0
  62. data/lib/sem4r/cli/cli_common_args.rb +293 -0
  63. data/lib/sem4r/cli/cli_download_report.rb +81 -0
  64. data/lib/sem4r/cli/cli_helpers.rb +57 -0
  65. data/lib/sem4r/cli/cli_ideas.rb +100 -0
  66. data/lib/sem4r/cli/cli_list_ads.rb +74 -0
  67. data/lib/sem4r/cli/cli_list_keywords.rb +76 -0
  68. data/lib/sem4r/cli/cli_request_report.rb +104 -0
  69. data/lib/sem4r/cli/cli_sem.rb +64 -0
  70. data/lib/sem4r/common/operation.rb +78 -0
  71. data/lib/sem4r/credentials.rb +86 -0
  72. data/lib/sem4r/extensions.rb +62 -0
  73. data/lib/sem4r/geo_location/geo_location_service.rb +59 -0
  74. data/lib/sem4r/info/info_service.rb +115 -0
  75. data/lib/sem4r/report_definition/report_definition.rb +104 -0
  76. data/lib/sem4r/report_definition/report_definition_operation.rb +34 -0
  77. data/lib/sem4r/report_definition/report_definition_selector.rb +31 -0
  78. data/lib/sem4r/report_definition/report_definition_service.rb +55 -0
  79. data/lib/sem4r/sem4r_error.rb +28 -0
  80. data/lib/sem4r/services/service.rb +74 -0
  81. data/lib/sem4r/services/soap_call.rb +100 -0
  82. data/lib/sem4r/services/soap_connector.rb +284 -0
  83. data/lib/sem4r/services/soap_error.rb +38 -0
  84. data/lib/sem4r/services/soap_message_v13.rb +129 -0
  85. data/lib/sem4r/services/soap_message_v2009.rb +170 -0
  86. data/lib/sem4r/soap_attributes.rb +141 -0
  87. data/lib/sem4r/targeting_idea/targeting_idea.rb +158 -0
  88. data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +200 -0
  89. data/lib/sem4r/targeting_idea/targeting_idea_service.rb +51 -0
  90. data/lib/sem4r/v13_account/account_service.rb +54 -0
  91. data/lib/sem4r/v13_account/billing_address.rb +67 -0
  92. data/lib/sem4r/v13_report/report.rb +185 -0
  93. data/lib/sem4r/v13_report/report_job.rb +51 -0
  94. data/lib/sem4r/v13_report/report_service.rb +89 -0
  95. data/lib/sem4r/v13_traffic_estimator/traffic_estimator_service.rb +30 -0
  96. data/lib/sem4r.rb +142 -0
  97. data/lib/sem4r_cli.rb +40 -0
  98. data/sem4r.gemspec +247 -0
  99. data/spec/aggregates_spec_helper.rb +59 -0
  100. data/spec/fixtures/sem4r.example.yml +26 -0
  101. data/spec/fixtures/services/ad_group/get-first-req.xml +28 -0
  102. data/spec/fixtures/services/ad_group/get-first-res.xml +91 -0
  103. data/spec/fixtures/services/ad_group/get-manual-cpm-bids-req.xml +106 -0
  104. data/spec/fixtures/services/ad_group/get-manual-cpm-bids-res.xml +75 -0
  105. data/spec/fixtures/services/ad_group/mutate_add-req.xml +52 -0
  106. data/spec/fixtures/services/ad_group/mutate_add-res.xml +33 -0
  107. data/spec/fixtures/services/ad_group_ad/get_mobile_ad-req.xml +28 -0
  108. data/spec/fixtures/services/ad_group_ad/get_mobile_ad-res.xml +194 -0
  109. data/spec/fixtures/services/ad_group_ad/get_text_ad-req.xml +29 -0
  110. data/spec/fixtures/services/ad_group_ad/get_text_ad-res.xml +55 -0
  111. data/spec/fixtures/services/ad_group_ad/mutate_add_mobile_ad-req.xml +50 -0
  112. data/spec/fixtures/services/ad_group_ad/mutate_add_mobile_ad-res.xml +42 -0
  113. data/spec/fixtures/services/ad_group_ad/mutate_add_text_ad-req.xml +37 -0
  114. data/spec/fixtures/services/ad_group_ad/mutate_add_text_ad-res.xml +32 -0
  115. data/spec/fixtures/services/ad_group_ad/mutate_add_two_criterions-req.xml +83 -0
  116. data/spec/fixtures/services/ad_group_ad/mutate_add_two_criterions-res.xml +95 -0
  117. data/spec/fixtures/services/ad_group_criterion/get-req.xml +28 -0
  118. data/spec/fixtures/services/ad_group_criterion/get-res.xml +242 -0
  119. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_keyword-req.xml +48 -0
  120. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_keyword-res.xml +47 -0
  121. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_placement-req.xml +35 -0
  122. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_placement-res.xml +32 -0
  123. data/spec/fixtures/services/ad_group_criterion/mutate_add_negative_keyword-req.xml +37 -0
  124. data/spec/fixtures/services/ad_group_criterion/mutate_add_negative_keyword-res.xml +51 -0
  125. data/spec/fixtures/services/ad_param/mutate_set-req.xml +43 -0
  126. data/spec/fixtures/services/ad_param/mutate_set-res.xml +29 -0
  127. data/spec/fixtures/services/bulk_mutate_job/get-req.xml +36 -0
  128. data/spec/fixtures/services/bulk_mutate_job/get-res.xml +54 -0
  129. data/spec/fixtures/services/bulk_mutate_job/mutate-req.xml +69 -0
  130. data/spec/fixtures/services/bulk_mutate_job/mutate-res.xml +48 -0
  131. data/spec/fixtures/services/campaign/get-req.xml +37 -0
  132. data/spec/fixtures/services/campaign/get-res.xml +1986 -0
  133. data/spec/fixtures/services/campaign/mutate_add-req.xml +37 -0
  134. data/spec/fixtures/services/campaign/mutate_add-res.xml +42 -0
  135. data/spec/fixtures/services/error.xml +28 -0
  136. data/spec/fixtures/services/info/get_unit_count-req.xml +30 -0
  137. data/spec/fixtures/services/info/get_unit_count-res.xml +29 -0
  138. data/spec/fixtures/services/report_definition/mutate_add-req.xml +24 -0
  139. data/spec/fixtures/services/report_definition/mutate_add-req_orig.xml +45 -0
  140. data/spec/fixtures/services/targeting_idea/get-req-all-options.xml +57 -0
  141. data/spec/fixtures/services/targeting_idea/get-req.xml +60 -0
  142. data/spec/fixtures/services/targeting_idea/get-res.xml +3601 -0
  143. data/spec/fixtures/services/v13_account/get_account_info-req.xml +23 -0
  144. data/spec/fixtures/services/v13_account/get_account_info-res.xml +54 -0
  145. data/spec/fixtures/services/v13_account/get_client_accounts-req.xml +22 -0
  146. data/spec/fixtures/services/v13_account/get_client_accounts-res.xml +37 -0
  147. data/spec/fixtures/services/v13_report/get_all_jobs-req.xml +21 -0
  148. data/spec/fixtures/services/v13_report/get_all_jobs-res.xml +109 -0
  149. data/spec/fixtures/services/v13_report/schedule_report_job-req.xml +56 -0
  150. data/spec/fixtures/services/v13_report/schedule_report_job-res.xml +24 -0
  151. data/spec/sem4r/account_spec.rb +86 -0
  152. data/spec/sem4r/ad_group/ad_group_bids_spec.rb +67 -0
  153. data/spec/sem4r/ad_group/ad_group_service_spec.rb +66 -0
  154. data/spec/sem4r/ad_group/ad_group_spec.rb +212 -0
  155. data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +88 -0
  156. data/spec/sem4r/ad_group_ad/ad_group_ad_service_spec.rb +55 -0
  157. data/spec/sem4r/ad_group_ad/ad_group_ad_spec.rb +173 -0
  158. data/spec/sem4r/ad_group_criterion/ad_group_criterion_bids_spec.rb +60 -0
  159. data/spec/sem4r/ad_group_criterion/ad_group_criterion_service_spec.rb +55 -0
  160. data/spec/sem4r/ad_group_criterion/ad_group_criterion_spec.rb +103 -0
  161. data/spec/sem4r/ad_group_criterion/criterion_spec.rb +85 -0
  162. data/spec/sem4r/ad_param/ad_param_service_spec.rb +55 -0
  163. data/spec/sem4r/ad_param/ad_param_spec.rb +59 -0
  164. data/spec/sem4r/adwords_spec.rb +110 -0
  165. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +63 -0
  166. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +69 -0
  167. data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +48 -0
  168. data/spec/sem4r/campaign/campaign_service_spec.rb +66 -0
  169. data/spec/sem4r/campaign/campaign_spec.rb +105 -0
  170. data/spec/sem4r/cli/cli_spec.rb +71 -0
  171. data/spec/sem4r/credentials_spec.rb +65 -0
  172. data/spec/sem4r/report_definition/report_definition_service_spec.rb +44 -0
  173. data/spec/sem4r/report_definition/report_definition_spec.rb +105 -0
  174. data/spec/sem4r/rexml_parsing_spec.rb +103 -0
  175. data/spec/sem4r/services/service_spec.rb +36 -0
  176. data/spec/sem4r/services/soap_call_spec.rb +115 -0
  177. data/spec/sem4r/services/soap_message_v13_spec.rb +54 -0
  178. data/spec/sem4r/soap_attributes_spec.rb +116 -0
  179. data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +120 -0
  180. data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +44 -0
  181. data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +53 -0
  182. data/spec/sem4r/v13_account/account_service_spec.rb +60 -0
  183. data/spec/sem4r/v13_report/report_service_spec.rb +104 -0
  184. data/spec/sem4r/v13_report/report_spec.rb +79 -0
  185. data/spec/sem4r_spec_helper.rb +353 -0
  186. data/spec/spec_helper.rb +12 -0
  187. metadata +375 -0
@@ -0,0 +1,242 @@
1
+ # -------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # -------------------------------------------------------------------
23
+
24
+
25
+ module Sem4r
26
+ class Adwords
27
+
28
+ attr_reader :profile
29
+
30
+ class << self
31
+ def sandbox( config = nil )
32
+ new( "sandbox", config )
33
+ end
34
+
35
+ def production( config = nil )
36
+ new( "production", config )
37
+ end
38
+
39
+ def search_config_file
40
+ config_filename = "sem4r.yml"
41
+
42
+ #
43
+ # try current directory
44
+ #
45
+ return File.expand_path(config_filename) if File.exists?( config_filename)
46
+
47
+ #
48
+ # try ~/.sem4r/sem4r.yml
49
+ #
50
+ # require 'etc'
51
+ # homedir = Etc.getpwuid.dir
52
+ homedir = ENV['HOME']
53
+ config_filepath = File.join( homedir, ".sem4r", config_filename)
54
+ return config_filepath if File.exists?( config_filepath )
55
+
56
+ #
57
+ # try <home_sem4r>/config/sem4r
58
+ #
59
+ config_filepath = File.expand_path( File.join( File.dirname( __FILE__ ), "..", "..", "config", config_filename ) )
60
+ return config_filepath if File.exists?( config_filepath )
61
+
62
+ config_filepath = File.expand_path( File.join( File.dirname( __FILE__ ), "..", "..", "config", "sem4r.example.yml" ) )
63
+ return config_filepath if File.exists?( config_filepath )
64
+
65
+ nil
66
+ end
67
+
68
+ def profiles( profile_file = nil )
69
+ profile_file = search_config_file unless profile_file
70
+ unless profile_file
71
+ raise Sem4rError, "config file 'sem4r' not found"
72
+ end
73
+ # puts "Loaded profiles from #{profile_file}"
74
+ yaml = YAML::load( File.open( profile_file ) )
75
+ profiles = yaml['google_adwords']
76
+ profiles
77
+ end
78
+ end
79
+
80
+ # new( "sandbox", {:email=>"..."} )
81
+ # new( {:environment=>"...", email => "..." } )
82
+ # new( "sandbox" )
83
+ # new() sandbox default
84
+ def initialize( profile = "sandbox", options = nil )
85
+ @logger = nil
86
+ if not options.nil?
87
+ # new( "sandbox", {:email=>"..."} )
88
+ @profile = profile.to_s
89
+ options = options.stringify_keys
90
+ options.assert_valid_keys("environment", "email", "password", "developer_token", "mutable", "config_file")
91
+ f = options.delete("config_file")
92
+ self.config_file= f if f
93
+ @options = load_config(@profile)
94
+ @options = @options.merge(options)
95
+ elsif profile.respond_to?(:keys)
96
+ # new( {:environment=>"...", email => "..." } )
97
+ @options = profile.stringify_keys
98
+ @options.assert_valid_keys("environment", "email", "password", "developer_token", "mutable")
99
+ @profile = "anonymous_" + @options["environment"]
100
+ else
101
+ # new( "sandbox" )
102
+ @profile = profile.to_s
103
+ @options = load_config(@profile)
104
+ end
105
+ if ["sandbox", "production"].include?(profile)
106
+ if @options["environment"].nil?
107
+ @options["environment"] = profile
108
+ end
109
+ if @options["environment"] != profile
110
+ raise "you cannot use profile '#{profile}' with environment #{@options["environment"]}"
111
+ end
112
+ end
113
+ end
114
+
115
+ def to_s
116
+ "adwords profile: '#{profile}' config file: '#{config_file}'"
117
+ end
118
+
119
+ def config_file=(file_path)
120
+ config_filepath = File.expand_path(file_path)
121
+ if File.exists?( config_filepath)
122
+ @config_filepath = config_filepath
123
+ else
124
+ puts "#{config_filepath} not exists"
125
+ end
126
+ @config_filepath
127
+ end
128
+
129
+ # return the config file name
130
+ def config_file
131
+ return @config_filepath if @config_filepath
132
+ @config_file_path = Adwords.search_config_file
133
+ @config_file_path
134
+ end
135
+
136
+ def load_config(profile)
137
+ unless config_file
138
+ raise Sem4rError, "config file 'sem4r' not found"
139
+ end
140
+ # puts "Loaded profiles from #{config_file}"
141
+ yaml = YAML::load( File.open( config_file ) )
142
+ config = yaml['google_adwords'][profile]
143
+ config || {}
144
+ end
145
+
146
+ ##########################################################################
147
+ # logging
148
+
149
+ def dump_soap_options( dump_options )
150
+ @dump_soap_options = dump_options
151
+ @connector.dump_soap_options( dump_options ) if @connector
152
+ end
153
+
154
+ def dump_soap?
155
+ not @dump_soap_options.nil?
156
+ end
157
+
158
+ def dump_soap_where
159
+ if @dump_soap_options[:directory]
160
+ "directory:#{@dump_soap_options[:directory]}"
161
+ else
162
+ "file:#{@dump_soap_options[:file]}"
163
+ end
164
+ end
165
+
166
+ def logger= logger
167
+ unless logger.instance_of?(Logger)
168
+ file = File.open( logger, "a" )
169
+ file.sync = true
170
+ logger = Logger.new(file)
171
+ logger.formatter = proc { |severity, datetime, progname, msg|
172
+ "#{datetime.strftime("%H:%M:%S")}: #{msg}\n"
173
+ }
174
+ end
175
+ @logger= logger
176
+
177
+ @connector.logger= logger if @connector
178
+ end
179
+
180
+ def logger
181
+ @logger
182
+ end
183
+
184
+ def account
185
+ deferred_initialize unless @initialized
186
+ @account
187
+ end
188
+
189
+ def p_counters
190
+ operations = @counters[:operations]
191
+ units = @counters[:units]
192
+ response_time = @counters[:response_time]
193
+ puts "#{units} unit spent for #{operations} operations in #{response_time}ms"
194
+ end
195
+
196
+ ##########################################################################
197
+ # methods only for internal use
198
+
199
+ attr_reader :service
200
+
201
+ #
202
+ # TODO: credentials are necessary because you might use more then account/credentials
203
+ # at the same time
204
+ #
205
+ def add_counters( credentials, counters )
206
+ counters.each_pair { |k,v|
207
+ @counters[k] ||= 0
208
+ @counters[k] += v
209
+ }
210
+ end
211
+
212
+ private
213
+
214
+ def deferred_initialize
215
+ @initialized = true
216
+
217
+ @connector = SoapConnector.new
218
+ @connector.dump_soap_options(@dump_soap_options) if @dump_soap_options
219
+ @connector.logger=(@logger) if @logger
220
+
221
+ @credentials = Credentials.new(
222
+ :environment => @options["environment"],
223
+ :email => @options["email"],
224
+ :password => @options["password"],
225
+ :useragent => "Sem4r Adwords Ruby Client Library (http://github.com/sem4r/sem4r)",
226
+ :developer_token => @options["developer_token"],
227
+ :mutable => @options["mutable"]
228
+ )
229
+ @credentials.connector = @connector
230
+
231
+ @service = Service.new(@connector)
232
+ @account = Account.new( self, @credentials )
233
+ @counters = {
234
+ :operations => 0,
235
+ :response_time => 0,
236
+ :units => 0
237
+ }
238
+ end
239
+
240
+ end
241
+
242
+ end
@@ -0,0 +1,7 @@
1
+ module Sem4r
2
+ class ApiCounters
3
+ def initialize
4
+
5
+ end
6
+ end
7
+ end
data/lib/sem4r/base.rb ADDED
@@ -0,0 +1,43 @@
1
+ # -------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # -------------------------------------------------------------------
23
+
24
+ module Sem4r
25
+ class Base
26
+ include SoapAttributes
27
+
28
+ attr_reader :adwords
29
+ attr_reader :credentials
30
+ attr_reader :service
31
+
32
+ def initialize(adwords, credentials)
33
+ @adwords = adwords
34
+ @credentials = credentials
35
+ @service = adwords.service
36
+ end
37
+
38
+ def add_counters( counters )
39
+ @adwords.add_counters( @credentials, counters )
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,108 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ # -------------------------------------------------------------------------
24
+
25
+ module Sem4r
26
+ class BulkMutateJob
27
+ include SoapAttributes
28
+
29
+ attr_reader :id
30
+ attr_accessor :campaign_id
31
+ attr_reader :operations
32
+
33
+ g_accessor :status
34
+
35
+ def initialize(&block)
36
+ @operations = []
37
+ if block_given?
38
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
39
+ end
40
+ end
41
+
42
+ def add_operation(operation)
43
+ @operations << operation
44
+ self
45
+ end
46
+
47
+ def empty?
48
+ @operations.empty?
49
+ end
50
+
51
+ def add( something )
52
+ case something
53
+ when AdGroupTextAd
54
+ ad_operation = AdGroupAdOperation.new
55
+ ad_operation.add something
56
+ else
57
+ raise "how you suppose I must do when incounter a #{something.class}?"
58
+ end
59
+ self
60
+ end
61
+
62
+ def to_xml(tag)
63
+ xml =""
64
+
65
+ if tag
66
+ xml += "<operand xsi:type='BulkMutateJob'>"
67
+ end
68
+ xml += <<-EOS
69
+ <request>
70
+ <partIndex>0</partIndex>
71
+ <operationStreams>
72
+ <scopingEntityId>
73
+ <type>CAMPAIGN_ID</type>
74
+ <value>#{campaign_id}</value>
75
+ </scopingEntityId>
76
+ EOS
77
+
78
+ if @operations
79
+ @operations.each do |operation|
80
+ xml += operation.to_xml('operations')
81
+ end
82
+ end
83
+
84
+ xml +=<<-EOS
85
+ </operationStreams>
86
+ </request>
87
+ <numRequestParts>1</numRequestParts>
88
+ EOS
89
+
90
+ if tag
91
+ xml += "</operand>"
92
+ end
93
+ end
94
+
95
+ def self.from_element(el)
96
+ new do
97
+ @id = el.elements["id"].text.strip.to_i
98
+ status el.elements["status"].text
99
+ end
100
+ end
101
+
102
+ def to_s
103
+ "#{@id} #{status}"
104
+ end
105
+
106
+ end
107
+
108
+ end
@@ -0,0 +1,56 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ # -------------------------------------------------------------------------
24
+
25
+ module Sem4r
26
+ class BulkMutateJobSelector
27
+ include SoapAttributes
28
+
29
+ def initialize(&block)
30
+ if block_given?
31
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
32
+ end
33
+ end
34
+
35
+ enum :JobStatuses, [
36
+ :COMPLETED,
37
+ :PROCESSING,
38
+ :FAILED,
39
+ :PENDING]
40
+
41
+ def to_xml
42
+ <<-EOFS
43
+ <selector>
44
+ <customerJobKeys></customerJobKeys>
45
+ <jobStatuses>COMPLETED</jobStatuses>
46
+ <jobStatuses>PROCESSING</jobStatuses>
47
+ <jobStatuses>FAILED</jobStatuses>
48
+ <jobStatuses>PENDING</jobStatuses>
49
+ </selector>
50
+ EOFS
51
+ end
52
+
53
+ ##########################################################################
54
+
55
+ end
56
+ end
@@ -0,0 +1,57 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ # -------------------------------------------------------------------------
24
+
25
+ module Sem4r
26
+ class BulkMutateJobService
27
+ include SoapCall
28
+
29
+ def initialize(connector)
30
+ @connector = connector
31
+
32
+ @service_namespace = "https://adwords.google.com/api/adwords/cm/v201003"
33
+ @header_namespace = @service_namespace
34
+
35
+ @sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/job/v201003/BulkMutateJobService"
36
+ @production_service_url = "https://adwords.google.com/api/adwords/job/v201003/BulkMutateJobService"
37
+ end
38
+
39
+ soap_call_v2009 :all, :mutate => false
40
+ soap_call_v2009 :mutate
41
+
42
+ private
43
+
44
+ def _all(selector)
45
+ "<get xmlns=\"#{@service_namespace}\">" + selector.to_xml + '</get>';
46
+ end
47
+
48
+ def _mutate(job_operation)
49
+ <<-EOFS
50
+ <mutate xmlns="#{@service_namespace}">
51
+ #{job_operation.to_xml('operation')}
52
+ </mutate>
53
+ EOFS
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,35 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ # -------------------------------------------------------------------------
24
+
25
+ module Sem4r
26
+
27
+ class JobOperation < Operation
28
+ def initialize(&block)
29
+ @operation_type = "JobOperation"
30
+ if block_given?
31
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
32
+ end
33
+ end
34
+ end
35
+ end