multistockphoto 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,13 @@
1
+ == 0.6.0 2008-06-10
2
+ * 4 enhancements
3
+ * Sendedauer fuer jedes Photo beim Senden auflisten
4
+ * Option --ordered fuer alphabetisches Senden der Files
5
+ * Option --no-tags erstellt (auch in Verbindung mit --ordered)
6
+ * neues Sender-Objekt fuer zentrale Upload-Funktionen
7
+ == 0.5.2 2008-05-30
8
+ * 1 bug fix
9
+ * Ja ja, Thomas. Erst eine dicke Lippe riskieren, von wegen "fehlerfrei" und dann noch nichtmal die Sprachelemente von Ruby beherrschen... skip -> next
10
+ * Keine weiteren Sendeversuche, wenn fuer eine Site bereits die maximale Upload-Anzahl / Tag erreicht ist und dieser Schalter in Konfigurationsdatei gesetzt
1
11
  == 0.5.1 2008-05-29
2
12
  * 1 bug fix
3
13
  * Fehlerbehandlung wenn Site keine Photos mehr annimmt
data/Manifest.txt CHANGED
@@ -6,11 +6,15 @@ README.txt
6
6
  Rakefile
7
7
  config.yaml
8
8
  bin/multistockphoto
9
+ bin/multistockphoto-gui
10
+ bin/mondrian.png
11
+ bin/mondrian.ico
9
12
  config/hoe.rb
10
13
  config/requirements.rb
11
14
  lib/multistockphoto.rb
12
15
  lib/multistockphoto/multistockphoto.rb
13
16
  lib/multistockphoto/version.rb
17
+ lib/multistockphoto/sender.rb
14
18
  lib/multistockphoto/generic_site.rb
15
19
  lib/multistockphoto/site_fotolia.rb
16
20
  lib/multistockphoto/site_zoonar.rb
@@ -31,6 +35,7 @@ test/test_helper.rb
31
35
  test/test_multistockphoto.rb
32
36
  website/index.html
33
37
  website/index.txt
38
+ website/face_boy.gif
34
39
  website/javascripts/rounded_corners_lite.inc.js
35
40
  website/stylesheets/screen.css
36
41
  website/template.html.erb
data/bin/mondrian.ico ADDED
Binary file
data/bin/mondrian.png ADDED
Binary file
data/bin/multistockphoto CHANGED
@@ -8,9 +8,12 @@ include Magick
8
8
  require 'exifr'
9
9
 
10
10
  SENDELISTE = 'sendeliste.dat'
11
+ MAX_ERRORS = 3
12
+ PICTURE_FILES = /.PNG|.JPG|.GIF|.JPEG/
11
13
 
14
+ # alle Sites komplett bearbeitet?
12
15
  def all_sites_done(sites,n)
13
- p sites
16
+ #p sites
14
17
  result = true
15
18
  sites.each {|entry|
16
19
  if entry[1] < n
@@ -21,17 +24,13 @@ def all_sites_done(sites,n)
21
24
  end
22
25
 
23
26
  version = Multistockphoto::VERSION::STRING
24
- SITES = ['fotolia',
25
- 'zoonar',
26
- 'photocase',
27
- ]
28
27
 
29
28
  Choice.options do
30
- header ''
31
- header 'Specific options:'
29
+ header 'Options:'
30
+ #header 'Specific options:'
32
31
  #...
33
- separator ''
34
- separator 'Common options: '
32
+ #separator ''
33
+ #separator 'Common options: '
35
34
 
36
35
  option :help do
37
36
  #short '-h'
@@ -105,7 +104,7 @@ Choice.options do
105
104
  end
106
105
 
107
106
  option :check_orientation do
108
- short '-o'
107
+ short '-c'
109
108
  long '--check-orientation'
110
109
  desc 'Displays the orientiation of photo files'
111
110
  action do
@@ -115,7 +114,7 @@ Choice.options do
115
114
 
116
115
  option :rotate do
117
116
  short '-r'
118
- long '--rotate'
117
+ long '--rotate file [file2 ...]'
119
118
  desc 'Rotate a photo file 90 degrees to the left'
120
119
  action do
121
120
  $rotate_photos = true
@@ -132,7 +131,7 @@ Choice.options do
132
131
  end
133
132
 
134
133
  option :list_done do
135
- short '-d'
134
+ short '-l'
136
135
  long '--list-done'
137
136
  desc 'List photos sent to all sites'
138
137
  action do
@@ -149,8 +148,55 @@ Choice.options do
149
148
  end
150
149
  end
151
150
 
151
+ option :ordered do
152
+ short '-o' #TODO: geht das?
153
+ long '--ordered'
154
+ desc 'Send/List files in alphabetical order'
155
+ action do
156
+ $ordered = true
157
+ end
158
+ end
159
+
160
+ option :no_tags do
161
+ short '-q'
162
+ long '--no-tags'
163
+ desc 'List photos without tags file' #TODO: eigentlich muss man auch auf vorhandene IPTC in Photo selbst testen
164
+ action do
165
+ $no_tags = true
166
+ end
167
+ end
168
+
169
+ option :dont_send do
170
+ long '--dont-send'
171
+ action do
172
+ $dont_send = true
173
+ end
174
+ end
175
+
176
+ option :dont_log do
177
+ long '--dont-log'
178
+ action do
179
+ $dont_log = true
180
+ end
181
+ end
152
182
  end
153
183
 
184
+ sender = Sender.new("egal")
185
+ $active_sites = sender.active_sites # [:fotolia,:zoonar,:photocase,...]
186
+ $upload_dir = sender.upload_dir
187
+ $done_dir = sender.done_dir
188
+
189
+ # konvertiert Sekundenanzahl in Format "MM:SS"
190
+ def formatted_minutes(d)
191
+ mm = (d / 60.0).floor
192
+ d = d-mm*60
193
+ ss = d.round
194
+ # return sprintf("%02d:%02d:%02d",hh,mm,ss)
195
+ return sprintf("%d:%02d",mm,ss)
196
+ end
197
+
198
+ # Senden aller noch nicht gesendeten Photos an alle Sites
199
+ # unter Berücksichtigung sonstiger Optionsparameter
154
200
  def send_all
155
201
  total_transfers = 0
156
202
  total = {}
@@ -160,79 +206,125 @@ def send_all
160
206
  total[site] = 0
161
207
  errors[site] = 0
162
208
  }
163
- p total
164
209
  puts 'sending all unsent photos'
165
210
 
166
- done = {:fotolia => false,
211
+ # rotate photos
212
+ # - true: we do the rotation
213
+ # - false: the site does the rotation automatically
214
+ # change to false if a photo site can automatically rotate photos
215
+ rotate_photos = {
216
+ :fotolia => true,
217
+ :zoonar => true,
218
+ :photocase => true,
219
+ }
220
+
221
+ done = {
222
+ :fotolia => false,
167
223
  :zoonar => false,
168
224
  :photocase => false,
169
225
  }
170
- remaining = {:fotolia => 999_999_999,
226
+ remaining = {
227
+ :fotolia => 999_999_999,
171
228
  :zoonar => 999_999_999,
172
229
  :photocase => 999_999_999,
173
230
  }
174
231
  sites.each {|site|
175
- # p "#{site.to_s.capitalize}"+".new(#{site.to_s.capitalize})"
232
+ # dynamisches Site.new("site")
176
233
  s = eval("#{site.to_s.capitalize}"+".new(#{site.to_s.capitalize})")
177
234
  if s.total_per_day
178
235
  remaining[site] = s.total_per_day - s.heute_schon_gesendet(site)
179
236
  end
180
237
  }
181
-
182
- Dir.glob('upload/*').each {|filename|
238
+ allfiles = Dir.glob($upload_dir+'/*')
239
+ if $ordered
240
+ allfiles.sort!
241
+ end
242
+ allfiles.each {|filename|
183
243
  next if File.basename(filename)[0,4] == 'rot_'
184
244
  #puts "rot_ uebersprungen"
185
- if filename.upcase =~ /.PNG|.JPG|.GIF|.JPEG/
245
+ if filename.upcase =~ PICTURE_FILES
186
246
  total_per_site_flag = $total_per_site
187
247
  photo = Photo.new(filename)
188
- [:fotolia, :zoonar, :photocase].each {|site_name|
189
- site = eval(site_name.to_s.capitalize+".new(#{site_name.to_s.capitalize})")
190
- skip if done[:sitename]
191
- # skip if !site.photos_fuer_heute_uebrig?
192
- if $send_all or
193
- # ($send_all and site.total_per_day and site.photos_fuer_heute_uebrig?) or
194
- (total_per_site_flag and total[site_name] < Choice.choices[:total_per_site])
195
- #photo = Photo.new(filename)
196
- begin
197
- if !site.already_sent?(photo)
198
- result = site.transfer(photo)
199
- if result != :duplicate
200
- total_transfers += 1
201
- total[site_name] += 1
202
- remaining[site_name] -= 1
203
- done[site_name] = true if remaining[site_name] <= 0
248
+ # [:fotolia, :zoonar, :photocase].each {|site_name|
249
+ $active_sites.each {|site_name|
250
+ begin
251
+ Timeout::timeout(10.0*60.0) do
252
+ t1 = Time.now
253
+ site = eval(site_name.to_s.capitalize+".new(#{site_name.to_s.capitalize})")
254
+ site.rotate_photos = rotate_photos[site_name]
255
+ done[site_name] = true if remaining[site_name] <= 0
256
+ next if done[site_name]
257
+ if $send_all or
258
+ (total_per_site_flag and
259
+ total[site_name] < Choice.choices[:total_per_site])
260
+ if !site.already_sent?(photo)
261
+ begin
262
+ result = site.transfer(photo,$dont_send,$dont_log)
263
+ if result != :duplicate
264
+ total_transfers += 1
265
+ total[site_name] += 1
266
+ remaining[site_name] -= 1
267
+ done[site_name] = true if remaining[site_name] <= 0
268
+ errors[site_name] = 0
269
+ if $verbose
270
+ t2 = Time.now
271
+ if $dont_send and $dont_log
272
+ puts "1:23"
273
+ else
274
+ puts formatted_minutes(t2-t1)
275
+ end
276
+ p total # Summenzeile ausgeben
277
+ end
278
+ end
279
+ rescue UploadException #Net::FTPTempError #TODO: gefaellt mir noch nicht so ganz
280
+ errors[site_name] += 1
281
+ if errors[site_name] >= MAX_ERRORS
282
+ done[site_name] = true # nichts mehr uploaden
283
+ puts "too many errors. giving up."
284
+ end
285
+ # puts "FTP-Fehler beim Senden an #{site_name} aufgetreten. Ggf. Konfiguration ueberpruefen oder spaeter erneut vesuchen"
286
+ puts "Upload error at sending to #{site_name} occurred. Check configuration or try again later!"
287
+ # rescue SocketError
288
+ # puts "SocketError: no net? waiting 60 secs"
289
+ # sleep 60
290
+ rescue Timeout::Error
291
+ puts "timeout error"
292
+ #timeout error
293
+ errors[site_name] += 1
294
+ if errors[site_name] >= MAX_ERRORS
295
+ done[site_name] = true
296
+ puts "too many errors. giving up."
297
+ end
298
+ end
204
299
  end
205
- if result != :duplicate
206
- errors[site_name] = 0
207
- end
208
- end
209
- break if result != :duplicate && total_transfers >= Choice.choices[:total_transfers]
210
- break if all_sites_done(total,Choice.choices[:total_per_site])
211
- rescue #UploadException #Net::FTPTempError #TODO: gefaellt mir noch nicht so ganz
212
- errors[site_name] += 1
213
- if errors[site_name] >= 3
214
- done[site_name] = true # nichts mehr uploaden
215
- puts "too many errors. giving up."
300
+ break if result != :duplicate && total_transfers >= Choice.choices[:total_transfers]
301
+ break if all_sites_done(total,Choice.choices[:total_per_site])
216
302
  end
217
- # puts "FTP-Fehler beim Senden an #{site_name} aufgetreten. Ggf. Konfiguration ueberpruefen oder spaeter erneut vesuchen"
218
- puts "Upload-Fehler beim Senden an #{site_name} aufgetreten. Ggf. Konfiguration ueberpruefen oder spaeter erneut vesuchen"
219
- end
220
- end
303
+ end # Timeout
304
+ end # timeout
221
305
  }
222
306
  end
223
307
  }
224
308
  puts "#{total_transfers} photos sent."
225
309
  end
226
310
 
227
- def check_orientation_loop
311
+ # gibt Orientation aller uebergebenen Bilddateien aus
312
+ def check_orientation_loop
228
313
  ARGV.each {|fn|
229
314
  if fn[0,1] != '-'
230
- pic = ImageList.new(fn)
231
- puts "#{fn}:\t#{pic.orientation}"
315
+ #pic = ImageList.new(fn)
316
+ #puts "#{fn}:\t#{pic.orientation}"
317
+ pic = Photo.new(fn)
318
+ if pic.portrait?
319
+ puts "#{fn}:\tportrait"
320
+ else
321
+ puts "#{fn}:\tlandscape"
322
+ end
232
323
  end
233
324
  }
234
325
  end
235
326
 
327
+ # rotiert alle uebergebenenen Bilddateien
236
328
  def rotate_photos
237
329
  ARGV.each {|fn|
238
330
  if fn[0,1] != '-'
@@ -245,19 +337,19 @@ def rotate_photos
245
337
  }
246
338
  end
247
339
 
340
+ # summiert noch nicht gesendete Bilder und listet pro Site auf
248
341
  def not_sent
249
342
  not_sent = {}
250
- SITES.each {|site|
343
+ $active_sites.each {|site|
251
344
  not_sent[site] = 0
252
345
  }
253
346
  puts "not sent photos:"
254
- Dir.glob('upload/*').each {|filename|
347
+ Dir.glob($upload_dir+'/*').each {|filename|
255
348
  next if File.basename(filename)[0,4] == 'rot_'
256
- #puts "rot_ uebersprungen"
257
- if filename.upcase =~ /.PNG|.JPG|.GIF|.JPEG/
258
- SITES.each {|site|
259
- print filename+"\t"+site+"\t" if $verbose
260
- g = grep("sendeliste.dat", /#{site}\t#{filename}/)
349
+ if filename.upcase =~ PICTURE_FILES
350
+ $active_sites.each {|site|
351
+ print filename+"\t"+site.to_s+"\t" if $verbose
352
+ g = grep(SENDELISTE, /#{site.to_s}\t#{filename}/)
261
353
  if g.size == 0
262
354
  puts "not sent" if $verbose
263
355
  not_sent[site] += 1
@@ -270,9 +362,11 @@ def not_sent
270
362
  p not_sent
271
363
  end
272
364
 
365
+ # listet Statistik ueber gesendete Bilder der letzten 10 Tage pro Site auf,
366
+ # sowie Summenzeile ueber alle gesendeten Bilder
273
367
  def stats
274
368
  count = {}
275
- File.open("sendeliste.dat") {|f|
369
+ File.open(SENDELISTE) {|f|
276
370
  f.each_line {|line|
277
371
  site,photo_file,time = line.chomp.split("\t")
278
372
  date = Date.parse(time)
@@ -285,8 +379,8 @@ def stats
285
379
  }
286
380
  }
287
381
  print " "*11+"| "
288
- SITES.each {|site|
289
- print "#{site}"
382
+ $active_sites.each {|site|
383
+ print "#{site.to_s}"
290
384
  print " | "
291
385
  }
292
386
  puts "total"
@@ -296,9 +390,9 @@ def stats
296
390
  chosen_date = today - i
297
391
  total = 0
298
392
  print chosen_date.to_s+" | "
299
- SITES.each {|site|
300
- key = [site, chosen_date]
301
- fmt = "%#{site.length}d | "
393
+ $active_sites.each {|site|
394
+ key = [site.to_s, chosen_date]
395
+ fmt = "%#{site.to_s.length}d | "
302
396
  printf(fmt, (count[key] || 0))
303
397
  total += (count[key] || 0)
304
398
  }
@@ -307,18 +401,17 @@ def stats
307
401
  puts
308
402
  totals = {}
309
403
  all = 0
310
- SITES.each {|site|
404
+ $active_sites.each {|site|
311
405
  totals[site] = 0
312
406
  }
313
407
  count.each_pair {|k,v|
314
408
  site = k[0]
315
- #date = k[1]
316
- totals[site] += v
409
+ totals[site.to_sym] += v
317
410
  all += v
318
411
  }
319
412
  print "total | "
320
- SITES.each {|site|
321
- fmt = "%#{site.length}d | "
413
+ $active_sites.each {|site|
414
+ fmt = "%#{site.to_s.length}d | "
322
415
  printf(fmt, (totals[site] || 0))
323
416
  }
324
417
  fmt = "%#{"total".length}d"
@@ -326,90 +419,121 @@ def stats
326
419
  puts
327
420
  end
328
421
 
329
- if $send_all or $total_per_site
330
- send_all
331
- end
332
-
333
- if $check_orientation_loop
334
- check_orientation_loop
335
- end
336
-
337
- if $rotate_photos
338
- rotate_photos
339
- end
340
-
341
- if $not_sent
342
- not_sent
343
- end
344
-
345
- if $stats
346
- puts "Statistics"
347
- stats
348
- end
349
-
350
- if $list_done
351
- #puts 'list_done'
352
- #not_sent = {}
353
- #SITES.each {|site|
354
- # not_sent[site] = 0
355
- #}
356
-
357
- Dir.glob('upload/*').each {|filename|
422
+ # listet Bilddateien auf, die an alle Sites gesendet wurden
423
+ def list_done
424
+ Dir.glob($upload_dir+'/*').each {|filename|
358
425
  photo_sent = {}
359
- SITES.each {|site|
426
+ $active_sites.each {|site|
360
427
  photo_sent[site] = false
361
428
  }
362
429
  next if File.basename(filename)[0,4] == 'rot_'
363
- #puts "rot_ uebersprungen"
364
- if filename.upcase =~ /.PNG|.JPG|.GIF|.JPEG/
365
- SITES.each {|site|
366
- print filename+"\t"+site+"\t" if $verbose
367
- g = grep(SENDELISTE, /#{site}\t#{filename}/)
368
- if g.size == 0
369
- #puts "not sent" if $verbose
370
- #not_sent[site] += 1
371
- else
372
- #puts 'already sent' if $verbose
430
+ if filename.upcase =~ PICTURE_FILES
431
+ $active_sites.each {|site|
432
+ print filename+"\t"+site.to_s+"\t" if $verbose
433
+ g = grep(SENDELISTE, /#{site.to_s}\t#{filename}/)
434
+ unless g.size == 0
373
435
  photo_sent[site] = true
374
436
  end
375
437
  }
376
438
  end
377
- # p photo_sent
378
- if photo_sent.has_value?(false)
379
- #puts "#{filename} nicht an alle gesendet"
380
- else
381
- puts "#{filename} an alle Sites gesendet"
439
+ unless photo_sent.has_value?(false)
440
+ puts "#{filename} sent to all sites"
382
441
  end
383
442
  }
384
- # p not_sent
385
443
  end
386
444
 
387
- if $purge_done
445
+ # erzeugt Dateiname einer tags Datei zu einer uebergebenen Photodatei,
446
+ # egal, ob tags-Datei wirlich existiert oder nicht
447
+ def tagsfilename(picturefilename)
448
+ ext = File.extname(picturefilename)
449
+ tagsfile = picturefilename.sub(ext,".tags")
450
+ return tagsfile
451
+ end
452
+
453
+ # Test, ob zu einer Photodatei eine tags-Datei existiert
454
+ def tagsfile?(picturefilename)
455
+ return File.exist?(tagsfilename(picturefilename))
456
+ end
457
+
458
+ # verschiebt Bilddateien, die an alle Sites gesendet wurden ins Directory 'done'
459
+ # dort koennen sie entweder geloescht oder archiviert werden
460
+ # Es schadet aber auch nicht, wenn dieser Schritt nie ausgefuehrt wird.
461
+ def purge_done
388
462
  puts 'purge_done'
389
- Dir.glob('upload/*').each {|filename|
463
+ Dir.glob($upload_dir+'/*').each {|filename|
390
464
  photo_sent = {}
391
- SITES.each {|site|
465
+ $active_sites.each {|site|
392
466
  photo_sent[site] = false
393
467
  }
394
468
  next if File.basename(filename)[0,4] == 'rot_'
395
- if filename.upcase =~ /.PNG|.JPG|.GIF|.JPEG/
396
- SITES.each {|site|
397
- print filename+"\t"+site+"\t" if $verbose
398
- g = grep(SENDELISTE, /#{site}\t#{filename}/)
469
+ if filename.upcase =~ PICTURE_FILES
470
+ $active_sites.each {|site|
471
+ print filename+"\t"+site.to_s+"\t" if $verbose
472
+ g = grep(SENDELISTE, /#{site.to_s}\t#{filename}/)
399
473
  if g.size > 0
400
474
  photo_sent[site] = true
401
475
  end
402
476
  }
403
477
  end
404
- if photo_sent.has_value?(false)
405
- #puts "#{filename} nicht an alle gesendet"
406
- else
407
- puts "#{filename} an alle Sites gesendet"
408
- if !File.exist? 'done'
409
- FileUtils.mkdir 'done'
478
+ unless photo_sent.has_value?(false)
479
+ puts "#{filename} sent to all sites"
480
+ if !File.exist? $done_dir
481
+ FileUtils.mkdir $done_dir
410
482
  end
411
483
  puts "mv #{filename} done/#{File.basename filename}"
412
- FileUtils.mv filename, "done/"
484
+ FileUtils.mv filename, $done_dir+"/"
485
+ if tagsfile?(filename)
486
+ puts "mv #{tagsfilename(filename)} done/#{File.basename(tagsfilename(filename))}"
487
+ FileUtils.mv(tagsfilename(filename), $done_dir+"/")
488
+ end
413
489
  end
414
490
  }
415
491
  end
492
+
493
+ # Listet alle Photo-Dateien auf, zu denen es keine .tags-Datei gibt
494
+ def no_tags
495
+ allfiles = Dir.glob($upload_dir+'/*')
496
+ if $ordered
497
+ allfiles.sort!
498
+ end
499
+ allfiles.each {|fn|
500
+ next if File.basename(fn)[0,4] == 'rot_'
501
+ if fn.upcase =~ PICTURE_FILES
502
+ puts fn unless tagsfile?(fn)
503
+ end
504
+ }
505
+ end
506
+
507
+ if $send_all or $total_per_site
508
+ send_all
509
+ end
510
+
511
+ if $check_orientation_loop
512
+ check_orientation_loop
513
+ end
514
+
515
+ if $rotate_photos
516
+ rotate_photos
517
+ end
518
+
519
+ if $not_sent
520
+ not_sent
521
+ end
522
+
523
+ if $stats
524
+ puts "Statistics"
525
+ stats
526
+ end
527
+
528
+ if $list_done
529
+ list_done
530
+ end
531
+
532
+ if $purge_done
533
+ purge_done
534
+ end
535
+
536
+ if $no_tags
537
+ no_tags
538
+ end
539
+