sklik-api 0.0.16 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@ class SklikApi
4
4
 
5
5
  NAME = "group"
6
6
 
7
- include Object
7
+ include SklikObject
8
8
  =begin
9
9
  Example of input hash
10
10
  {
@@ -30,47 +30,121 @@ Example of input hash
30
30
 
31
31
  =end
32
32
 
33
- def initialize campaign, args
33
+ def initialize args, deprecated_args = {}
34
+
35
+ #deprecated way to set up new adgroup!
36
+ if args.is_a?(SklikApi::Campaign)
37
+ puts "DEPRECATION WARNING: Please update your code for SklikApi::Adgroup.new(campaign, args) to SklikApi::Adgroup.new(args = {}) possible to add parent camapign by adding :campaign => your campaign"
38
+ #set adgroup owner campaign
39
+ @campaign = args
40
+ args = deprecated_args
41
+
42
+ #new way to set adgroups!
43
+ else
44
+ #set adgroup owner campaign
45
+ #if in input args there is pointer to parent campaign!
46
+ if @campaign = args.delete(:campaign)
47
+ # if no cpc was given - try to use campaign cpc
48
+ if !args[:cpc] && @campaign.args[:cpc]
49
+ args[:cpc] = @campaign.args[:cpc]
50
+ end
51
+ end
52
+ end
53
+ @args = args
54
+
34
55
  @adgroup_data = nil
35
- #set adgroup owner campaign
36
- @campaign = campaign
37
56
 
38
57
  #initialize adgroups
39
58
  @adtexts = []
40
59
  if args[:ads] && args[:ads].size > 0
41
60
  args[:ads].each do |adtext|
42
- @adtexts << SklikApi::Adtext.new(self, adtext)
61
+ @adtexts << SklikApi::Adtext.new(adtext.merge(:adgroup => self))
43
62
  end
44
63
  end
64
+
45
65
  #initialize adgroups
46
66
  @keywords = []
47
67
  if args[:keywords] && args[:keywords].size > 0
48
68
  args[:keywords].each do |keyword|
49
- @keywords << SklikApi::Keyword.new(self, :keyword => keyword)
69
+ if keyword.is_a?(Hash)
70
+ @keywords << SklikApi::Keyword.new(keyword.merge(:adgroup => self))
71
+ else
72
+ @keywords << SklikApi::Keyword.new(:keyword => keyword, :adgroup => self)
73
+ end
50
74
  end
51
75
  end
52
76
 
53
77
  super args
54
78
  end
55
79
 
56
- def self.find campaign, args = {}
80
+ def self.get id
81
+ if adgroup = super(NAME, id)
82
+ SklikApi::Adgroup.new(
83
+ process_sklik_data adgroup
84
+ )
85
+ else
86
+ nil
87
+ end
88
+ end
89
+ #
90
+ # Find adgroups in campaign!
91
+ # !Deprecated! by campaign and args
92
+ #
93
+ def self.find args, deprecated_args = {}
57
94
  out = []
58
- super(NAME, campaign.args[:campaign_id]).each do |adgroup|
59
- if args[:adgroup_id].nil? || (args[:adgroup_id] && args[:adgroup_id].to_i == adgroup[:id].to_i)
60
- out << SklikApi::Adgroup.new( campaign,
61
- :adgroup_id => adgroup[:id],
62
- :cpc => adgroup[:cpc].to_f/100.0,
63
- :name => adgroup[:name],
64
- :status => fix_status(adgroup)
95
+ #asking fo adgroup by ID
96
+ if args.is_a?(Integer)
97
+ return get args
98
+
99
+ #asking for adgroup deprecated way!
100
+ elsif args.is_a?(SklikApi::Campaign)
101
+ puts "DEPRECATION WARNING: Please update your code for SklikApi::Adgroup.find(campaign, args) to SklikApi::Adgroup.find(campaign_id: 1234) possible to add parent camapign by adding :campaign => your campaign"
102
+ campaign_id = args.args[:campaign_id]
103
+ args = deprecated_args
104
+
105
+ #asking for adgroup by hash with adgroup_id
106
+ elsif args.is_a?(Hash) && args[:adgroup_id]
107
+ if adgroup = get(args[:adgroup_id])
108
+ return [adgroup]
109
+ else
110
+ return []
111
+ end
112
+
113
+ #asking for adgroup by hash
114
+ else
115
+ campaign_id = args[:campaign_id]
116
+ end
117
+
118
+ raise ArgumentError, "Please provide campaign_id in params" unless campaign_id
119
+
120
+ super(NAME, campaign_id).each do |adgroup|
121
+
122
+ if (args[:status].nil? || (args[:status] == fix_status(adgroup))) && # find by status
123
+ (args[:name].nil? || (args[:name] == adgroup[:name]))
124
+
125
+ out << SklikApi::Adgroup.new(
126
+ process_sklik_data adgroup
65
127
  )
66
128
  end
67
129
  end
68
130
  out
69
131
  end
70
132
 
133
+ def self.process_sklik_data adgroup = {}
134
+ {
135
+ :adgroup_id => adgroup[:id],
136
+ :cpc => adgroup[:cpc].to_f/100.0,
137
+ :name => adgroup[:name],
138
+ :status => fix_status(adgroup),
139
+ :campaign_id => adgroup[:campaignId],
140
+ }
141
+ end
142
+
71
143
  def self.fix_status adgroup
72
144
  if adgroup[:removed] == true
73
145
  return :stopped
146
+ elsif adgroup[:status] == "suspend"
147
+ return :paused
74
148
  else
75
149
  return :running
76
150
  end
@@ -78,7 +152,7 @@ Example of input hash
78
152
 
79
153
  def keywords_stats from, to
80
154
  output = []
81
- keywords = Keyword.find(self)
155
+ keywords = Keyword.find(adgroup_id: self.args[:adgroup_id])
82
156
  keywords.in_groups_of(100, false).each do |keywords_group|
83
157
  out = connection.call("keywords.stats", keywords_group.collect{|k| k.args[:keyword_id]}, from, to ) { |param|
84
158
  param[:keywordStats]
@@ -100,45 +174,80 @@ Example of input hash
100
174
  @adgroup_data
101
175
  else
102
176
  @adgroup_data = @args
103
- if @args[:status] != :stopped
104
- @adgroup_data[:ads] = Adtext.find(self).collect{|a| a.to_hash}
105
- @adgroup_data[:keywords] = Keyword.find(self).collect{|k| k.to_hash}
106
- else
107
- @adgroup_data[:ads] = []
108
- @adgroup_data[:keywords] = []
109
- end
177
+ @adgroup_data[:ads] = self.adtexts.collect{|a| a.to_hash}
178
+ @adgroup_data[:keywords] = self.keywords.collect{|k| k.to_hash}
110
179
  @adgroup_data
111
180
  end
112
181
  end
113
182
 
114
183
 
115
184
  def create_args
116
- raise ArgumentError, "Adgroup need's to know campaign_id" unless @campaign.args[:campaign_id]
117
- raise ArgumentError, "Adgroup need's to know campaigns CPC" unless @campaign.args[:cpc]
185
+ raise ArgumentError, "Adgroup need's to know campaign_id" unless args[:campaign_id]
186
+ raise ArgumentError, "Adgroup need's to know campaigns CPC" unless args[:cpc]
118
187
 
119
188
  out = []
120
189
  #add campaign id to know where to create adgroup
121
- out << @campaign.args[:campaign_id]
190
+ out << @args[:campaign_id] || @campaign.args[:campaign_id]
122
191
 
123
192
  #add adgroup struct
124
- args = {}
125
- args[:name] = @args[:name]
126
- args[:cpc] = (@campaign.args[:cpc] * 100).to_i if @campaign.args[:cpc]
127
- out << args
193
+ c_args = {}
194
+ c_args[:name] = @args[:name]
195
+ if @args[:cpc]
196
+ c_args[:cpc] = (@args[:cpc] * 100).to_i
197
+ elsif @campaign && @campaign.args[:cpc]
198
+ c_args[:cpc] = (@campaign.args[:cpc] * 100).to_i
199
+ else
200
+ raise ArgumentError, "Please provide adgroup or parent campaign with :cpc parameter in CZK"
201
+ end
202
+ c_args[:status] = status_for_update if status_for_update
203
+ out << c_args
128
204
 
129
205
  #return output
130
206
  out
131
207
  end
132
208
 
209
+ def update_args
210
+ out = []
211
+
212
+ #add campaign id on which will be performed update
213
+ out << @args[:adgroup_id]
214
+
215
+ #prepare campaign struct
216
+ u_args = {}
217
+ u_args[:name] = @args[:name] if @args[:name]
218
+ u_args[:status] = status_for_update if status_for_update
219
+ if @args[:cpc]
220
+ u_args[:cpc] = (@args[:cpc] * 100).to_i
221
+ elsif @campaign && @campaign.args[:cpc]
222
+ u_args[:cpc] = (@campaign.args[:cpc] * 100).to_i
223
+ end
224
+ out << u_args
225
+
226
+ out
227
+ end
228
+
133
229
  def adtexts
134
- Adtext.find(self)
230
+ if @args[:adgroup_id] && get_current_status == :stopped
231
+ SklikApi.log :error, "Adgroup: #{@args[:adgroup_id]} - Can't get adtexts for stopped Adgroup!"
232
+ []
233
+ else
234
+ Adtext.find(adgroup_id: self.args[:adgroup_id])
235
+ end
135
236
  end
136
237
 
137
238
  def keywords
138
- Keyword.find(self)
239
+ if @args[:adgroup_id] && get_current_status == :stopped
240
+ SklikApi.log :error, "Adgroup: #{@args[:adgroup_id]} - Can't get keywords for stopped Adgroup!"
241
+ []
242
+ else
243
+ Keyword.find(adgroup_id: self.args[:adgroup_id])
244
+ end
139
245
  end
140
246
 
141
247
  def update args = {}
248
+
249
+ @args.merge!(args)
250
+
142
251
  if args.is_a?(SklikApi::Adgroup)
143
252
  #get data from another adgroup
144
253
  @adtexts = args.instance_variable_get("@adtexts")
@@ -152,7 +261,7 @@ Example of input hash
152
261
  @adtexts = []
153
262
  if args[:ads] && args[:ads].size > 0
154
263
  args[:ads].each do |adtext|
155
- @adtexts << SklikApi::Adtext.new(self, adtext)
264
+ @adtexts << SklikApi::Adtext.new(adtext.merge(:adgroup => self))
156
265
  end
157
266
  end
158
267
 
@@ -160,7 +269,7 @@ Example of input hash
160
269
  @keywords = []
161
270
  if args[:keywords] && args[:keywords].size > 0
162
271
  args[:keywords].each do |keyword|
163
- @keywords << SklikApi::Keyword.new(self, :keyword => keyword)
272
+ @keywords << SklikApi::Keyword.new(:keyword => keyword, :adgroup => self)
164
273
  end
165
274
  end
166
275
  end
@@ -168,83 +277,124 @@ Example of input hash
168
277
  save
169
278
  end
170
279
 
280
+ def valid?
281
+ clear_errors
282
+ log_error "name is required" unless args[:name] && args[:name].size > 0
283
+ log_error "cpc is required and must be higher than 0 CZK" unless !@args[:adgroup_id] && args[:cpc] && args[:cpc] > 0
284
+ log_error "campaign_id is required" unless args[:campaign_id] || (@campaign && @campaign.args[:campaign_id])
285
+ !errors.any?
286
+ end
287
+
288
+
289
+ def self.get_current_status args = {}
290
+ raise ArgumentError, "Adgroup_id is required" unless args[:adgroup_id]
291
+ if adgroup = self.get(args[:adgroup_id])
292
+ adgroup.args[:status]
293
+ else
294
+ raise ArgumentError, "Adgroup by #{args.inspect} couldn't be found!"
295
+ end
296
+ end
297
+
298
+ def get_current_status
299
+ self.class.get_current_status :adgroup_id => @args[:adgroup_id], :customer_id => @customer_id
300
+ end
301
+
171
302
  def save
172
- if @args[:adgroup_id] #do update
303
+ clear_errors
304
+ @args[:campaign_id] = @campaign.args[:campaign_id] if !@args[:campaign_id] && @campaign.args[:campaign_id]
173
305
 
174
- ############
175
- ## KEYWORDS
176
- ############
306
+ if @args[:adgroup_id] #do update
177
307
 
178
- #update keywords
179
- keywords_error = []
180
- @new_keywords = @keywords.clone
181
- delete_first = true
182
- while @new_keywords && @new_keywords.size > 0 do
183
- begin
184
- connection.call('keywords.set', @args[:adgroup_id], @new_keywords[0..199].collect{|k| k.create_args.last }, delete_first) do |params|
185
- @campaign.errors << params[:statusMessage] if params[:statusMessage] != "OK"
308
+ #get current status of campaign
309
+ before_status = get_current_status
310
+
311
+ #restore campaign before update
312
+ restore if before_status == :stopped
313
+
314
+ #rescue from any error to ensure remove will be done when something went wrong
315
+ error = nil
316
+
317
+ begin
318
+ #update adgroup
319
+ update_object
320
+
321
+ ############
322
+ ## KEYWORDS
323
+ ############
324
+
325
+ #update keywords
326
+ keywords_error = []
327
+ @new_keywords = @keywords.clone
328
+ delete_first = true
329
+ while @new_keywords && @new_keywords.size > 0 do
330
+ begin
331
+ connection.call('keywords.set', @args[:adgroup_id], @new_keywords[0..199].collect{|k| k.create_args.last }, delete_first) do |params|
332
+ log_error params[:statusMessage] if params[:statusMessage] != "OK"
333
+ end
334
+ rescue Exception => e
335
+ log_error e.message
186
336
  end
187
- rescue Exception => e
188
- @campaign.errors << e.message
337
+ @new_keywords = @new_keywords[200..-1]
338
+ delete_first = false
189
339
  end
190
- @new_keywords = @new_keywords[200..-1]
191
- delete_first = false
192
- end
193
340
 
194
- ############
195
- ## ADTEXTS
196
- ############
341
+ ############
342
+ ## ADTEXTS
343
+ ############
197
344
 
198
- #create new adtexts and delete old
199
- @saved_adtexts = adtexts.inject({}){|o,a| o[a.uniq_identifier] = a ; o}
200
- @new_adtexts = @adtexts.inject({}){|o,a| o[a.uniq_identifier] = a ; o}
345
+ #create new adtexts and delete old
346
+ @saved_adtexts = adtexts.inject({}){|o,a| o[a.uniq_identifier] = a ; o}
347
+ @new_adtexts = @adtexts.inject({}){|o,a| o[a.uniq_identifier] = a ; o}
201
348
 
202
- #adtexts to be deleted
203
- (@saved_adtexts.keys - @new_adtexts.keys).each do |k|
204
- puts "deleting adtext #{@saved_adtexts[k]} in #{@args[:name]}"
205
- #don't try to remove already removed adtext
206
- @saved_adtexts[k].remove unless @saved_adtexts[k].args[:status] == :stopped
207
- end
349
+ #adtexts to be deleted
350
+ (@saved_adtexts.keys - @new_adtexts.keys).each do |k|
351
+ puts "deleting adtext #{@saved_adtexts[k]} in #{@args[:name]}"
352
+ #don't try to remove already removed adtext
353
+ @saved_adtexts[k].remove unless @saved_adtexts[k].args[:status] == :stopped
354
+ end
208
355
 
209
- #adtexts to be created
210
- (@new_adtexts.keys - @saved_adtexts.keys).each do |k|
211
- puts "creating new adtext #{k} in #{@args[:name]}"
212
- begin
213
- @new_adtexts[k].save
214
- rescue Exception => e
215
- #take care about error message -> do it nicer
216
- if /There is error from sklik ad.create: Invalid parameters/ =~ e.message
217
- @campaign.errors << "Problem with creating #{@new_adtexts[k].args} in adgroup #{@args[:name]}"
218
- else
219
- @campaign.errors << e.message
356
+ #adtexts to be created
357
+ (@new_adtexts.keys - @saved_adtexts.keys).each do |k|
358
+ puts "creating new adtext #{k} in #{@args[:name]}"
359
+ begin
360
+ @new_adtexts[k].save
361
+ rescue Exception => e
362
+ #take care about error message -> do it nicer
363
+ if /There is error from sklik ad.create: Invalid parameters/ =~ e.message
364
+ log_error "Problem with creating #{@new_adtexts[k].args} in adgroup #{@args[:name]}"
365
+ else
366
+ log_error e.message
367
+ end
220
368
  end
221
369
  end
222
- end
223
370
 
224
- #check status to be running
225
- (@new_adtexts.keys & @saved_adtexts.keys).each do |k|
226
- @saved_adtexts[k].restore if @saved_adtexts[k].args[:status] == :stopped
371
+ #check status to be running
372
+ (@new_adtexts.keys & @saved_adtexts.keys).each do |k|
373
+ @saved_adtexts[k].restore if @saved_adtexts[k].args[:status] == :stopped
374
+ end
375
+
376
+ rescue Exception => e
377
+ log_error e.message
227
378
  end
228
379
 
380
+ #remove it if new status is stopped or status doesn't changed and before it was stopped
381
+ remove if (@args[:status] == :stopped) || (@args[:status].nil? && before_status == :stopped)
229
382
 
230
- else #do save
231
- #create adgroup
232
- create
383
+ else #do create
233
384
 
234
- #create adtexts
235
- @adtexts.each do |adtext|
236
- begin
237
- adtext.save
238
- rescue Exception => e
239
- #take care about error message -> do it nicer
240
- if /There is error from sklik ad.create: Invalid parameters/ =~ e.message
241
- @campaign.errors << "Problem with creating #{adtext.args} in adgroup #{@args[:name]}"
242
- else
243
- @campaign.errors << e.message
244
- end
245
- end
385
+ begin
386
+ #create adgroup
387
+ create
388
+ rescue Exception => e
389
+ log_error e.message
390
+ #don't continue with creating campaign!
391
+ return false
246
392
  end
247
393
 
394
+ #create adtexts
395
+ unless @adtexts.all?{|adtext| adtext.save }
396
+ return rollback!
397
+ end
248
398
 
249
399
  #create keywords
250
400
  keywords_error = []
@@ -253,22 +403,49 @@ Example of input hash
253
403
  while @new_keywords && @new_keywords.size > 0 do
254
404
  begin
255
405
  connection.call('keywords.set', @args[:adgroup_id], @new_keywords[0..199].collect{|k| k.create_args.last }, delete_first) do |params|
256
- @campaign.errors << params[:statusMessage] if params[:statusMessage] != "OK"
406
+ keywords_error << params[:statusMessage] if params[:statusMessage] != "OK"
257
407
  end
258
408
  rescue Exception => e
259
- @campaign.errors << e.message
409
+ keywords_error << e.message
260
410
  end
261
411
  @new_keywords = @new_keywords[200..-1]
262
412
  delete_first = false
263
413
  end
264
414
 
265
415
  if keywords_error.size > 0
266
- @campaign.errors << "Problem with creating keywords: #{keywords_error.join(", ")} in adgroup #{@args[:name]}"
416
+ log_error "Problem with creating keywords: #{keywords_error.join(", ")}"
417
+ return rollback!
267
418
  end
268
419
 
420
+ #remove campaign when it was started with stopped status!
421
+ remove if @args[:status] && @args[:status].to_s.to_sym == :stopped
422
+
269
423
  end
424
+ !errors.any?
425
+ end
426
+
427
+ def log_error message
428
+ @campaign.log_error "Adgroup: #{@args[:name]} -> #{message}" if @campaign
429
+ errors << message
270
430
  end
271
431
 
432
+ def rollback!
433
+ #don't rollback if it is disabled!
434
+ return false unless SklikApi.use_rollback?
435
+
436
+ #remember errors!
437
+ old_errors = errors
438
+
439
+ SklikApi.log :info, "Adgroup: #{@args[:adgroup_id]} - ROLLBACK!"
440
+ update :name => "#{@args[:name]} FAILED ON CREATION - #{Time.now.strftime("%Y.%m.%d %H:%M:%S")}"
441
+ #remove adgroup
442
+ remove
443
+
444
+ #return remembered errors!
445
+ @errors = old_errors
446
+ #don't continue with creating adgroup!
447
+ return false
448
+ end
272
449
  end
273
450
  end
274
451