multistockphoto 0.7.1 → 0.8.0
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.
- data/History.txt +11 -0
- data/Manifest.txt +1 -0
- data/bin/multistockphoto +128 -50
- data/config.yaml +7 -0
- data/lib/multistockphoto/photo.rb +94 -28
- data/lib/multistockphoto/sender.rb +1 -1
- data/lib/multistockphoto/site_bigstockphoto.rb +121 -0
- data/lib/multistockphoto/site_dreamstime.rb +33 -14
- data/lib/multistockphoto/site_fotolia.rb +29 -10
- data/lib/multistockphoto/site_photocase.rb +38 -13
- data/lib/multistockphoto/site_zoonar.rb +39 -18
- data/lib/multistockphoto/version.rb +2 -2
- data/lib/multistockphoto.rb +1 -0
- data/test/test_multistockphoto.rb +98 -18
- data/website/index.html +324 -15
- data/website/index.txt +249 -5
- metadata +4 -3
data/History.txt
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
== 0.8.0 2008-06-28
|
|
2
|
+
* 1 major enhancement
|
|
3
|
+
* neue Site Bigstockphoto erstellt
|
|
4
|
+
* Option --plist in bin/multistockphoto erstellt
|
|
5
|
+
* Option --count=N in Verbindung mit --no-tags und --tags_only erstellt
|
|
6
|
+
* 1 minor enhancement
|
|
7
|
+
* Absicherung/Fehlermeldung wenn Config-Datei nicht richtig gelesen werden kann
|
|
8
|
+
* Methode self.accept?/accept? je Site Klasse neu, fuer zulaessige File-Typen
|
|
9
|
+
* Optimierungen in bin/multistockphoto
|
|
10
|
+
* 1 bug fix
|
|
11
|
+
* --stats Fehler bei deaktivierten Sites behoben
|
|
1
12
|
== 0.7.1 2008-06-16
|
|
2
13
|
* 1 bug fix
|
|
3
14
|
* entfernen von ueberfluessiger aldi-site fuehrte anderweitig zu Fehler
|
data/Manifest.txt
CHANGED
|
@@ -21,6 +21,7 @@ lib/multistockphoto/site_zoonar.rb
|
|
|
21
21
|
lib/multistockphoto/mock_zoonar.rb
|
|
22
22
|
lib/multistockphoto/site_photocase.rb
|
|
23
23
|
lib/multistockphoto/site_dreamstime.rb
|
|
24
|
+
lib/multistockphoto/site_bigstockphoto.rb
|
|
24
25
|
lib/multistockphoto/photo.rb
|
|
25
26
|
lib/multistockphoto/upload_exception.rb
|
|
26
27
|
script/console
|
data/bin/multistockphoto
CHANGED
|
@@ -6,10 +6,18 @@ require 'multistockphoto'
|
|
|
6
6
|
require 'RMagick'
|
|
7
7
|
include Magick
|
|
8
8
|
require 'exifr'
|
|
9
|
+
require 'grep'
|
|
10
|
+
include Grep
|
|
9
11
|
|
|
10
12
|
SENDELISTE = 'sendeliste.dat'
|
|
13
|
+
ROT_PREFIX = 'rot_'
|
|
11
14
|
MAX_ERRORS = 3
|
|
12
|
-
PICTURE_FILES =
|
|
15
|
+
PICTURE_FILES = /(.PNG|.JPG|.GIF|.JPEG|.EPS|.AI|.PSD|.PDF|.TIF|.TIFF)$/
|
|
16
|
+
|
|
17
|
+
require 'fcntl'
|
|
18
|
+
|
|
19
|
+
#STDOUT.sync = true
|
|
20
|
+
#STDOUT.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
|
|
13
21
|
|
|
14
22
|
# alle Sites komplett bearbeitet?
|
|
15
23
|
def all_sites_done(sites,n)
|
|
@@ -170,11 +178,33 @@ Choice.options do
|
|
|
170
178
|
short '-q'
|
|
171
179
|
long '--no-tags'
|
|
172
180
|
desc 'List photos without tags file' #TODO: eigentlich muss man auch auf vorhandene IPTC in Photo selbst testen
|
|
181
|
+
#cast Integer
|
|
182
|
+
#default 0
|
|
173
183
|
action do
|
|
174
184
|
$no_tags = true
|
|
175
185
|
end
|
|
176
186
|
end
|
|
177
187
|
|
|
188
|
+
option :count do
|
|
189
|
+
short '-3'
|
|
190
|
+
long '--count'
|
|
191
|
+
desc 'count'
|
|
192
|
+
cast Integer
|
|
193
|
+
default 0
|
|
194
|
+
action do
|
|
195
|
+
$count_flag = true
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
option :plist do
|
|
200
|
+
short '-2'
|
|
201
|
+
long '--plist'
|
|
202
|
+
desc 'Show details sending status for each picture'
|
|
203
|
+
action do
|
|
204
|
+
$plist = true
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
178
208
|
option :dont_send do
|
|
179
209
|
long '--dont-send'
|
|
180
210
|
action do
|
|
@@ -200,51 +230,49 @@ def formatted_minutes(d)
|
|
|
200
230
|
mm = (d / 60.0).floor
|
|
201
231
|
d = d-mm*60
|
|
202
232
|
ss = d.round
|
|
203
|
-
# return sprintf("%02d:%02d:%02d",hh,mm,ss)
|
|
204
233
|
return sprintf("%d:%02d",mm,ss)
|
|
205
234
|
end
|
|
206
235
|
|
|
236
|
+
# Hilfsmethode fuer send_all
|
|
237
|
+
# false, falls keine Tags-Datei existiert oder laut Aufrufparameter --count zu wenige
|
|
238
|
+
# Keywords hat.
|
|
239
|
+
def not_enough_tags?(photo)
|
|
240
|
+
if $tags_only
|
|
241
|
+
if ! tagsfile?(photo.filename)
|
|
242
|
+
return true
|
|
243
|
+
else
|
|
244
|
+
if $count_flag
|
|
245
|
+
photo.set_keywords
|
|
246
|
+
if photo.tags.size < $count
|
|
247
|
+
return true
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end # tags_only
|
|
252
|
+
false
|
|
253
|
+
end
|
|
254
|
+
|
|
207
255
|
# Senden aller noch nicht gesendeten Photos an alle Sites
|
|
208
256
|
# unter Berücksichtigung sonstiger Optionsparameter
|
|
209
257
|
def send_all
|
|
258
|
+
if $count_flag
|
|
259
|
+
$count = Choice.choices[:count]
|
|
260
|
+
end
|
|
210
261
|
total_transfers = 0
|
|
211
262
|
total = {}
|
|
212
263
|
errors = {}
|
|
213
|
-
#sites = [:fotolia, :zoonar, :photocase]
|
|
214
264
|
$active_sites.each {|site|
|
|
215
265
|
total[site] = 0
|
|
216
266
|
errors[site] = 0
|
|
217
267
|
}
|
|
218
268
|
puts 'sending all unsent photos'
|
|
219
269
|
|
|
220
|
-
# rotate photos
|
|
221
|
-
# - true: we do the rotation
|
|
222
|
-
# - false: the site does the rotation automatically
|
|
223
|
-
# change to false if a photo site can automatically rotate photos
|
|
224
|
-
# rotate_photos = {
|
|
225
|
-
# :fotolia => true,
|
|
226
|
-
# :zoonar => true,
|
|
227
|
-
# :photocase => true,
|
|
228
|
-
# }
|
|
229
|
-
|
|
230
|
-
# done = {
|
|
231
|
-
# :fotolia => false,
|
|
232
|
-
# :zoonar => false,
|
|
233
|
-
# :photocase => false,
|
|
234
|
-
# :dreamstime => false,
|
|
235
|
-
# }
|
|
236
|
-
# remaining = {
|
|
237
|
-
# :fotolia => 999_999_999,
|
|
238
|
-
# :zoonar => 999_999_999,
|
|
239
|
-
# :photocase => 999_999_999,
|
|
240
|
-
# :dreamstime => 999_999_999,
|
|
241
|
-
# }
|
|
242
270
|
remaining = Hash.new
|
|
243
271
|
done = Hash.new
|
|
244
272
|
$active_sites.each {|site|
|
|
245
273
|
done[site] = false
|
|
246
274
|
remaining[site] = 999_999_999
|
|
247
|
-
|
|
275
|
+
}
|
|
248
276
|
$active_sites.each {|site|
|
|
249
277
|
# dynamisches Site.new("site")
|
|
250
278
|
s = eval("#{site.to_s.capitalize}"+".new(#{site.to_s.capitalize})")
|
|
@@ -257,25 +285,30 @@ def send_all
|
|
|
257
285
|
allfiles.sort!
|
|
258
286
|
end
|
|
259
287
|
allfiles.each {|filename|
|
|
260
|
-
next if File.basename(filename)[0,4] ==
|
|
288
|
+
next if File.basename(filename)[0,4] == ROT_PREFIX
|
|
261
289
|
#puts "rot_ uebersprungen"
|
|
262
290
|
if filename.upcase =~ PICTURE_FILES
|
|
263
291
|
total_per_site_flag = $total_per_site
|
|
264
292
|
photo = Photo.new(filename)
|
|
293
|
+
next if not_enough_tags? photo
|
|
265
294
|
$active_sites.each {|site_name|
|
|
266
295
|
begin
|
|
267
296
|
Timeout::timeout(10.0*60.0) do
|
|
268
297
|
t1 = Time.now
|
|
269
298
|
site = eval(site_name.to_s.capitalize+".new(#{site_name.to_s.capitalize})")
|
|
299
|
+
# if ! site.accept?(File.extname(filename))
|
|
300
|
+
# warn "Warning: Site (#{site_name}) does not support this file extension (#{File.extname(filename)}). Skipped"
|
|
301
|
+
# next
|
|
302
|
+
# end
|
|
270
303
|
# site.rotate_photos = rotate_photos[site_name]
|
|
271
304
|
done[site_name] = true if remaining[site_name] <= 0
|
|
272
305
|
next if done[site_name]
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
next
|
|
306
|
+
|
|
307
|
+
if ! site.accept?(File.extname(filename))
|
|
308
|
+
warn "Warning: Site (#{site_name}) does not support this file extension (#{File.extname(filename)}). Skipped"
|
|
309
|
+
next
|
|
278
310
|
end
|
|
311
|
+
#end
|
|
279
312
|
if $send_all or
|
|
280
313
|
(total_per_site_flag and
|
|
281
314
|
total[site_name] < Choice.choices[:total_per_site])
|
|
@@ -288,8 +321,8 @@ def send_all
|
|
|
288
321
|
remaining[site_name] -= 1
|
|
289
322
|
done[site_name] = true if remaining[site_name] <= 0
|
|
290
323
|
errors[site_name] = 0
|
|
324
|
+
t2 = Time.now
|
|
291
325
|
if $verbose
|
|
292
|
-
t2 = Time.now
|
|
293
326
|
if $dont_send and $dont_log
|
|
294
327
|
puts "1:23"
|
|
295
328
|
else
|
|
@@ -298,17 +331,13 @@ def send_all
|
|
|
298
331
|
p total # Summenzeile ausgeben
|
|
299
332
|
end
|
|
300
333
|
end
|
|
301
|
-
rescue UploadException
|
|
334
|
+
rescue UploadException
|
|
302
335
|
errors[site_name] += 1
|
|
303
336
|
if errors[site_name] >= MAX_ERRORS
|
|
304
|
-
done[site_name] = true
|
|
337
|
+
done[site_name] = true
|
|
305
338
|
puts "too many errors. giving up."
|
|
306
339
|
end
|
|
307
|
-
# puts "FTP-Fehler beim Senden an #{site_name} aufgetreten. Ggf. Konfiguration ueberpruefen oder spaeter erneut vesuchen"
|
|
308
340
|
puts "Upload error at sending to #{site_name} occurred. Check configuration or try again later!"
|
|
309
|
-
# rescue SocketError
|
|
310
|
-
# puts "SocketError: no net? waiting 60 secs"
|
|
311
|
-
# sleep 60
|
|
312
341
|
rescue Timeout::Error
|
|
313
342
|
puts "timeout error"
|
|
314
343
|
#timeout error
|
|
@@ -367,7 +396,7 @@ def not_sent
|
|
|
367
396
|
}
|
|
368
397
|
puts "not sent photos:"
|
|
369
398
|
Dir.glob(File.join($upload_dir,'*')).each {|filename|
|
|
370
|
-
next if File.basename(filename)[0,4] ==
|
|
399
|
+
next if File.basename(filename)[0,4] == ROT_PREFIX
|
|
371
400
|
if filename.upcase =~ PICTURE_FILES
|
|
372
401
|
$active_sites.each {|site|
|
|
373
402
|
print filename+"\t"+site.to_s+"\t" if $verbose
|
|
@@ -428,7 +457,10 @@ def stats
|
|
|
428
457
|
}
|
|
429
458
|
count.each_pair {|k,v|
|
|
430
459
|
site = k[0]
|
|
431
|
-
|
|
460
|
+
if $active_sites.include? site.to_sym # sonst kommt es zu Fehlern bei
|
|
461
|
+
# deaktivierten Sites
|
|
462
|
+
totals[site.to_sym] += v
|
|
463
|
+
end
|
|
432
464
|
all += v
|
|
433
465
|
}
|
|
434
466
|
print "total | "
|
|
@@ -445,7 +477,7 @@ def stats
|
|
|
445
477
|
count[:tags] = 0
|
|
446
478
|
count[:notags] = 0
|
|
447
479
|
Dir.glob(File.join($upload_dir,'*')).each {|filename|
|
|
448
|
-
next if File.basename(filename)[0,4] ==
|
|
480
|
+
next if File.basename(filename)[0,4] == ROT_PREFIX
|
|
449
481
|
if filename.upcase =~ PICTURE_FILES
|
|
450
482
|
if tagsfile?(filename)
|
|
451
483
|
count[:tags] += 1
|
|
@@ -467,7 +499,7 @@ def list_done
|
|
|
467
499
|
$active_sites.each {|site|
|
|
468
500
|
photo_sent[site] = false
|
|
469
501
|
}
|
|
470
|
-
next if File.basename(filename)[0,4] ==
|
|
502
|
+
next if File.basename(filename)[0,4] == ROT_PREFIX
|
|
471
503
|
if filename.upcase =~ PICTURE_FILES
|
|
472
504
|
$active_sites.each {|site|
|
|
473
505
|
print filename+"\t"+site.to_s+"\t" if $verbose
|
|
@@ -506,7 +538,7 @@ def purge_done
|
|
|
506
538
|
$active_sites.each {|site|
|
|
507
539
|
photo_sent[site] = false
|
|
508
540
|
}
|
|
509
|
-
next if File.basename(filename)[0,4] ==
|
|
541
|
+
next if File.basename(filename)[0,4] == ROT_PREFIX
|
|
510
542
|
if filename.upcase =~ PICTURE_FILES
|
|
511
543
|
$active_sites.each {|site|
|
|
512
544
|
print filename+"\t"+site.to_s+"\t" if $verbose
|
|
@@ -533,20 +565,63 @@ end
|
|
|
533
565
|
|
|
534
566
|
# Listet alle Photo-Dateien auf, zu denen es keine .tags-Datei gibt
|
|
535
567
|
def no_tags
|
|
536
|
-
|
|
568
|
+
if $count_flag
|
|
569
|
+
$count = Choice.choices[:count]
|
|
570
|
+
end
|
|
537
571
|
allfiles = Dir.glob(File.join($upload_dir,'*'))
|
|
538
572
|
if $ordered
|
|
539
573
|
allfiles.sort!
|
|
540
574
|
end
|
|
541
575
|
allfiles.each {|fn|
|
|
542
|
-
next if File.basename(fn)[0,4] ==
|
|
576
|
+
next if File.basename(fn)[0,4] == ROT_PREFIX
|
|
543
577
|
if fn.upcase =~ PICTURE_FILES
|
|
544
578
|
if ! tagsfile?(fn)
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
#
|
|
548
|
-
|
|
579
|
+
puts fn
|
|
580
|
+
else
|
|
581
|
+
# es gibt eine aber zu wenige keywords
|
|
582
|
+
if $count_flag
|
|
583
|
+
photo = Photo.new(fn)
|
|
584
|
+
photo.set_keywords_without_write
|
|
585
|
+
if photo.tags.size < $count
|
|
586
|
+
puts fn + " only #{photo.tags.size} keywords"
|
|
587
|
+
end
|
|
588
|
+
end
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
end
|
|
592
|
+
}
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
def plist
|
|
596
|
+
allfiles = Dir.glob(File.join($upload_dir,'*'))
|
|
597
|
+
if $ordered
|
|
598
|
+
allfiles.sort!
|
|
599
|
+
end
|
|
600
|
+
print ' '+' '*34
|
|
601
|
+
$active_sites.each {|site|
|
|
602
|
+
printf("%-10s",site)
|
|
603
|
+
}
|
|
604
|
+
puts
|
|
605
|
+
allfiles.each {|filename|
|
|
606
|
+
next if File.basename(filename)[0,4] == ROT_PREFIX
|
|
607
|
+
if filename.upcase =~ PICTURE_FILES
|
|
608
|
+
photo = Photo.new(filename)
|
|
609
|
+
photo.set_keywords_without_write
|
|
610
|
+
printf("%-30s ",filename)
|
|
611
|
+
if tagsfile?(filename)
|
|
612
|
+
printf "(t %2d) ", photo.tags.size
|
|
613
|
+
else
|
|
614
|
+
print ' '
|
|
549
615
|
end
|
|
616
|
+
$active_sites.each {|site|
|
|
617
|
+
g = grep(SENDELISTE, /#{site.to_s}\t#{filename}/)
|
|
618
|
+
if g.size == 0
|
|
619
|
+
print ' '*10
|
|
620
|
+
else
|
|
621
|
+
print '+'+' '*9
|
|
622
|
+
end
|
|
623
|
+
}
|
|
624
|
+
puts
|
|
550
625
|
end
|
|
551
626
|
}
|
|
552
627
|
end
|
|
@@ -584,3 +659,6 @@ if $no_tags
|
|
|
584
659
|
no_tags
|
|
585
660
|
end
|
|
586
661
|
|
|
662
|
+
if $plist
|
|
663
|
+
plist
|
|
664
|
+
end
|
data/config.yaml
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
- :zoonar
|
|
5
5
|
- :photocase
|
|
6
6
|
- :dreamstime
|
|
7
|
+
- :bigstockphoto
|
|
7
8
|
:zoonar:
|
|
8
9
|
:user: 'hugo'
|
|
9
10
|
:password: 'lalala'
|
|
@@ -24,3 +25,9 @@
|
|
|
24
25
|
:ftp_user: 'martha12345'
|
|
25
26
|
:ftp_password: 'ftpgeheimmartha'
|
|
26
27
|
:total_per_day: 1
|
|
28
|
+
:bigstockphoto:
|
|
29
|
+
:user: 'dennis'
|
|
30
|
+
:password: 'dennisgeheim'
|
|
31
|
+
:ftp_user: 'dennis12345'
|
|
32
|
+
:ftp_password: 'ftpgeheimdennis'
|
|
33
|
+
:total_per_day: 1
|
|
@@ -50,30 +50,56 @@ class Photo
|
|
|
50
50
|
pic.auto_orient!
|
|
51
51
|
puts "rotating picture, writing to #{tmpname}"
|
|
52
52
|
pic.write(tmpname)
|
|
53
|
-
|
|
54
53
|
end
|
|
55
54
|
@rotated_filename = tmpname
|
|
56
55
|
end
|
|
57
56
|
end
|
|
58
57
|
|
|
59
58
|
# setzt IPTC-Keywords, enthalten in Datei <imagefilename>.tags
|
|
60
|
-
|
|
59
|
+
# wenn from_lang und to_lang uebergeben, dann Uebersetzung der Keywords
|
|
60
|
+
# z.B. set_keywords(:de,:en)
|
|
61
|
+
def set_keywords(from_lang=nil,to_lang=nil)
|
|
61
62
|
ext = File.extname(@filename)
|
|
63
|
+
if ext.upcase != '.JPG' and ext.upcase != '.JPEG'
|
|
64
|
+
warn "cannot set Exif-Header with non-JPEG file #{@filename}"
|
|
65
|
+
return
|
|
66
|
+
end
|
|
62
67
|
fn = @filename.sub(ext,".tags")
|
|
63
68
|
lines=[]
|
|
64
69
|
begin
|
|
65
70
|
File.open(fn) {|f|
|
|
66
71
|
lines = f.read
|
|
67
72
|
}
|
|
68
|
-
puts "tags file #{fn} found"
|
|
69
73
|
tags = Photo.to_tags(lines)
|
|
74
|
+
if from_lang and to_lang
|
|
75
|
+
tags = translate_tags(tags,from_lang,to_lang)
|
|
76
|
+
end
|
|
70
77
|
self.tags = tags
|
|
71
|
-
print "writing tags to file ... "
|
|
72
|
-
|
|
78
|
+
#print "writing tags to file ... "
|
|
79
|
+
#$stdout.flush
|
|
73
80
|
write_keywords
|
|
74
|
-
puts "done"
|
|
81
|
+
#puts "done"
|
|
75
82
|
rescue Errno::ENOENT
|
|
76
|
-
warn "WARNING: no tags file #{fn}"
|
|
83
|
+
#warn "WARNING: no tags file #{fn}"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def set_keywords_without_write(from_lang=nil,to_lang=nil)
|
|
88
|
+
ext = File.extname(@filename)
|
|
89
|
+
fn = @filename.sub(ext,".tags")
|
|
90
|
+
lines=[]
|
|
91
|
+
begin
|
|
92
|
+
File.open(fn) {|f|
|
|
93
|
+
lines = f.read
|
|
94
|
+
}
|
|
95
|
+
#puts "tags file #{fn} found"
|
|
96
|
+
tags = Photo.to_tags(lines)
|
|
97
|
+
if from_lang and to_lang
|
|
98
|
+
tags = translate_tags(tags,from_lang,to_lang)
|
|
99
|
+
end
|
|
100
|
+
self.tags = tags
|
|
101
|
+
rescue Errno::ENOENT
|
|
102
|
+
#warn "WARNING: no tags file #{fn}"
|
|
77
103
|
end
|
|
78
104
|
end
|
|
79
105
|
|
|
@@ -82,15 +108,6 @@ class Photo
|
|
|
82
108
|
tags
|
|
83
109
|
end
|
|
84
110
|
|
|
85
|
-
# erstellt Key-Array aus String (getrennt durch newline,',' oder ' ')
|
|
86
|
-
def self.to_tags(s)
|
|
87
|
-
keys = []
|
|
88
|
-
s.split(/[, |\t\n]+/).each {|w|
|
|
89
|
-
keys << w
|
|
90
|
-
}
|
|
91
|
-
keys
|
|
92
|
-
end
|
|
93
|
-
|
|
94
111
|
# ermittelt Keywords aus Datei
|
|
95
112
|
def file_keywords
|
|
96
113
|
photo = MiniExiftool.new @filename
|
|
@@ -101,18 +118,20 @@ class Photo
|
|
|
101
118
|
# schreibt Keywords in Datei-Header
|
|
102
119
|
def write_keywords
|
|
103
120
|
photo = MiniExiftool.new @filename
|
|
104
|
-
s = ''
|
|
105
|
-
tags.each {|tag|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
121
|
+
#s = ''
|
|
122
|
+
#tags.each {|tag|
|
|
123
|
+
#if s == ''
|
|
124
|
+
#s = s + tag
|
|
125
|
+
#else
|
|
126
|
+
## s = s + ' ' + tag
|
|
127
|
+
## lieber durch Komma trennen, da sonst das Formular z.B. bei fotolia nicht
|
|
128
|
+
## richtig gefüllt wird
|
|
129
|
+
#s = s + ',' + tag
|
|
130
|
+
#end
|
|
131
|
+
#}
|
|
132
|
+
# lieber durch Komma trennen, da sonst das Formular z.B. bei fotolia nicht
|
|
133
|
+
# richtig gefüllt wird
|
|
134
|
+
photo['keywords'] = tags.join(',')
|
|
116
135
|
|
|
117
136
|
#TODO:
|
|
118
137
|
photo['title'] = 'Testtitel'
|
|
@@ -120,4 +139,51 @@ class Photo
|
|
|
120
139
|
photo.save
|
|
121
140
|
end
|
|
122
141
|
|
|
142
|
+
private
|
|
143
|
+
|
|
144
|
+
# erstellt Key-Array aus String (getrennt durch newline,',' oder ' ')
|
|
145
|
+
def self.to_tags(s)
|
|
146
|
+
keys = []
|
|
147
|
+
s.split(/[, |\t\n]+/).each {|w|
|
|
148
|
+
keys << w
|
|
149
|
+
}
|
|
150
|
+
keys
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# uebersetzt Tags von 'from_lang' nach 'to_lang'
|
|
155
|
+
# bisher realisiert: :de -> :en
|
|
156
|
+
# Achtung: bisher nur experimentell. Nicht verwenden!
|
|
157
|
+
def translate_tags(tags, from_lang, to_lang)
|
|
158
|
+
new_tags = []
|
|
159
|
+
tags.each {|tag|
|
|
160
|
+
new_tags << translate_tag(tag,from_lang,to_lang)
|
|
161
|
+
}
|
|
162
|
+
return new_tags
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# uebersetzt ein Tag von 'from_lang' nach 'to_lang'
|
|
166
|
+
# bisher realisiert: :de -> :en
|
|
167
|
+
# Achtung: bisher nur experimentell. Nicht verwenden!
|
|
168
|
+
def translate_tag(tag,from_lang,to_lang)
|
|
169
|
+
if from_lang == :de and to_lang == :en
|
|
170
|
+
case tag
|
|
171
|
+
when 'Baum'
|
|
172
|
+
'tree'
|
|
173
|
+
when 'Berlin'
|
|
174
|
+
'Berlin'
|
|
175
|
+
when 'gwb'
|
|
176
|
+
'gwb'
|
|
177
|
+
when 'Blume'
|
|
178
|
+
'flower'
|
|
179
|
+
when 'Biene'
|
|
180
|
+
'bee'
|
|
181
|
+
else
|
|
182
|
+
raise "unknown translation for '#{tag}' (#{from_lang} #{to_lang})"
|
|
183
|
+
end
|
|
184
|
+
else
|
|
185
|
+
raise "unknown translation codes: #{from_lang} #{to_lang}"
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
123
189
|
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
require 'net/ftp'
|
|
2
|
+
|
|
3
|
+
class Bigstockphoto < GenericSite
|
|
4
|
+
|
|
5
|
+
@@errors = 0
|
|
6
|
+
|
|
7
|
+
attr_reader :total_per_day
|
|
8
|
+
attr_accessor :ftp_user, :ftp_password, :max_errors
|
|
9
|
+
|
|
10
|
+
FTP_HOST = 'bigstockphoto.com'
|
|
11
|
+
SITENAME = 'bigstockphoto'
|
|
12
|
+
|
|
13
|
+
def initialize(name)
|
|
14
|
+
super
|
|
15
|
+
@config = load_config
|
|
16
|
+
begin
|
|
17
|
+
@user = @config[:bigstockphoto][:user]
|
|
18
|
+
@password = @config[:bigstockphoto][:password]
|
|
19
|
+
@ftp_user = @config[:bigstockphoto][:ftp_user]
|
|
20
|
+
@ftp_password = @config[:bigstockphoto][:ftp_password]
|
|
21
|
+
@total_per_day = @config[:bigstockphoto][:total_per_day]
|
|
22
|
+
rescue
|
|
23
|
+
puts 'cannot read configuration entries of '+SITENAME
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def transfer(photo, dont_send=nil, dont_log=nil)
|
|
28
|
+
# falls nicht in config Datei eingetragen dann nicht senden
|
|
29
|
+
if @user == nil or @password == nil
|
|
30
|
+
return
|
|
31
|
+
end
|
|
32
|
+
unless photo.class == Photo
|
|
33
|
+
raise 'not a Photo object'
|
|
34
|
+
end
|
|
35
|
+
unless File.exist?(photo.filename)
|
|
36
|
+
raise "file #{photo.filename} does not exist"
|
|
37
|
+
end
|
|
38
|
+
if @ftp_user == nil or @ftp_password == nil
|
|
39
|
+
raise "ftp_user/ftp_password not set"
|
|
40
|
+
end
|
|
41
|
+
print "#{SITENAME}:#{photo.filename} ... "
|
|
42
|
+
$stdout.flush
|
|
43
|
+
if already_sent_site?(photo,SITENAME)
|
|
44
|
+
puts "already sent"
|
|
45
|
+
return :duplicate
|
|
46
|
+
end
|
|
47
|
+
if photo.portrait? and ! Bigstockphoto.can_handle_orientation?
|
|
48
|
+
photo.drehen
|
|
49
|
+
end
|
|
50
|
+
if site_can_handle_keywords?
|
|
51
|
+
photo.set_keywords(:de,:en) # Keywords uebersetzen
|
|
52
|
+
end
|
|
53
|
+
if ! dont_send
|
|
54
|
+
begin
|
|
55
|
+
ftp = Net::FTP.new(FTP_HOST)
|
|
56
|
+
ftp.login(@ftp_user,@ftp_password)
|
|
57
|
+
files=ftp.list('*')
|
|
58
|
+
if photo.portrait?
|
|
59
|
+
#p photo.rotated_filename
|
|
60
|
+
res = ftp.putbinaryfile(photo.rotated_filename)
|
|
61
|
+
else
|
|
62
|
+
res = ftp.putbinaryfile(photo.filename)
|
|
63
|
+
end
|
|
64
|
+
files =ftp.list('*')
|
|
65
|
+
#p files
|
|
66
|
+
ftp.close
|
|
67
|
+
rescue Errno::EPIPE
|
|
68
|
+
raise UploadException
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
@@errors = 0
|
|
72
|
+
puts 'OK'
|
|
73
|
+
if ! dont_log
|
|
74
|
+
File.open(SENDLIST,'a') {|f|
|
|
75
|
+
f.puts "#{SITENAME}\t#{photo.filename}\t#{Time.now}"
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
true
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Anzahl heute schon gesendeter Photos
|
|
82
|
+
def sent_today
|
|
83
|
+
site = SITENAME
|
|
84
|
+
return sent_today_site(site)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# wurde dieses Photo schon gesendet?
|
|
88
|
+
def already_sent?(photo)
|
|
89
|
+
already_sent_site?(photo,SITENAME)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# can site handle orientation?
|
|
93
|
+
def self.can_handle_orientation?
|
|
94
|
+
false #TODO: pruefen!
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Site akzeptiert diese Extension
|
|
98
|
+
def self.accept?(ext)
|
|
99
|
+
ext = ext.downcase
|
|
100
|
+
if ext[0,1] == '.'
|
|
101
|
+
ext = ext[1..-1]
|
|
102
|
+
end
|
|
103
|
+
case ext
|
|
104
|
+
when 'jpg','jpeg','eps','ai','psd','png','pdf'
|
|
105
|
+
return true
|
|
106
|
+
else
|
|
107
|
+
return false
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def accept?(ext)
|
|
112
|
+
Bigstockphoto.accept?(ext)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
def site_can_handle_keywords?
|
|
118
|
+
true #TODO: pruefen!
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end # class
|