flickrup 0.0.2
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/bin/flickrup +6 -0
- data/lib/flickrup/logging.rb +5 -0
- data/lib/flickrup/processor.rb +31 -0
- data/lib/flickrup/quick_listener.rb +52 -0
- data/lib/flickrup/slow_listener.rb +69 -0
- data/lib/flickrup/tagged_image.rb +36 -0
- data/lib/flickrup/uploader.rb +56 -0
- data/lib/flickrup.rb +43 -0
- metadata +167 -0
data/bin/flickrup
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "flickrup/tagged_image"
|
2
|
+
require "flickrup/uploader"
|
3
|
+
require "flickrup/logging"
|
4
|
+
|
5
|
+
class Processor
|
6
|
+
include Logging
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(files = Dir["#{@config['watch_dir']}/*.{jpg,JPG,jpeg,JPEG}"])
|
13
|
+
|
14
|
+
logger.debug("Processing #{files.length} files")
|
15
|
+
|
16
|
+
images = files.map { |x| TaggedImage.new(x) }
|
17
|
+
|
18
|
+
tagged = images.select { |x| !(x.tags.nil? || x.tags.empty?) }
|
19
|
+
|
20
|
+
uploader = Uploader.new(@config["api_key"], @config["shared_secret"])
|
21
|
+
|
22
|
+
tagged.each { |x|
|
23
|
+
x.doUpload(uploader)
|
24
|
+
x.archive(@config["archive_dir"])
|
25
|
+
}
|
26
|
+
|
27
|
+
logger.debug("Processed #{tagged.length} valid files")
|
28
|
+
|
29
|
+
tagged.length
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'atomic'
|
2
|
+
require "thread"
|
3
|
+
require "listen"
|
4
|
+
|
5
|
+
class QuickListener
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
@changes = Atomic.new 0
|
10
|
+
@mutex = Mutex.new
|
11
|
+
@sync = ConditionVariable.new
|
12
|
+
@flickup = Flickrup.new(config)
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
Thread.new { run_loop }
|
17
|
+
Listen.to(@config['watch_dir']) do |modified, added, removed|
|
18
|
+
unless modified.empty? && added.empty?
|
19
|
+
on_change
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def run_loop
|
26
|
+
|
27
|
+
@mutex.synchronize do
|
28
|
+
while 1 do
|
29
|
+
reloop = @changes.swap 0
|
30
|
+
|
31
|
+
while reloop > 0 do
|
32
|
+
execute
|
33
|
+
reloop = @changes.swap 0
|
34
|
+
end
|
35
|
+
|
36
|
+
@sync.wait(@mutex)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def on_change
|
43
|
+
@mutex.synchronize do
|
44
|
+
@changes.set 1
|
45
|
+
@sync.signal
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def execute
|
50
|
+
@flickup.run
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rufus/scheduler'
|
3
|
+
require "flickrup/logging"
|
4
|
+
|
5
|
+
#modification ->
|
6
|
+
# schedule upload for 5 mins time
|
7
|
+
#
|
8
|
+
#upload run ->
|
9
|
+
# for files modified > 5 mins ago
|
10
|
+
# -> do upload
|
11
|
+
# if there are files modified < 5 mins ago
|
12
|
+
# -> schedule upload for minimum time
|
13
|
+
#
|
14
|
+
#When scheduling upload, remove all but the nearest
|
15
|
+
#When paused, upload run should be a no-op
|
16
|
+
|
17
|
+
class SlowListener
|
18
|
+
include Logging
|
19
|
+
|
20
|
+
WAIT = 5#*60 #5 min
|
21
|
+
|
22
|
+
def initialize(config)
|
23
|
+
@config = config
|
24
|
+
@scheduler = Rufus::Scheduler.start_new
|
25
|
+
@processor = Processor.new(config)
|
26
|
+
end
|
27
|
+
|
28
|
+
def run
|
29
|
+
logger.debug("Watching #{@config['watch_dir']}...")
|
30
|
+
Listen.to(@config['watch_dir']) do |modified, added, removed|
|
31
|
+
unless modified.empty? && added.empty?
|
32
|
+
on_change
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def do_upload
|
38
|
+
logger.debug("Checking files for upload")
|
39
|
+
files = Dir["#{@config['watch_dir']}/*.{jpg,JPG,jpeg,JPEG}"]
|
40
|
+
|
41
|
+
old, new = files.partition { |x| Time.now > File.mtime(x) + WAIT }
|
42
|
+
|
43
|
+
unless old.empty?
|
44
|
+
logger.debug("Found #{old.length} stable files")
|
45
|
+
@processor.run(old)
|
46
|
+
end
|
47
|
+
|
48
|
+
unless new.empty?
|
49
|
+
logger.debug("Found #{new.length} new files")
|
50
|
+
#todo: schedule for latest
|
51
|
+
schedule
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def on_change
|
56
|
+
logger.debug("Change detected")
|
57
|
+
schedule
|
58
|
+
end
|
59
|
+
|
60
|
+
def schedule
|
61
|
+
if @scheduler.jobs.empty?
|
62
|
+
logger.debug("Scheduling processing for #{WAIT} sec")
|
63
|
+
@scheduler.in WAIT do
|
64
|
+
do_upload
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'mini_exiftool'
|
2
|
+
require 'ftools'
|
3
|
+
require 'fileutils'
|
4
|
+
require "flickrup/logging"
|
5
|
+
|
6
|
+
class TaggedImage
|
7
|
+
include Logging
|
8
|
+
|
9
|
+
attr_reader :file
|
10
|
+
|
11
|
+
def initialize(file)
|
12
|
+
@file = file
|
13
|
+
@parsed = MiniExiftool.new @file
|
14
|
+
end
|
15
|
+
|
16
|
+
def tags
|
17
|
+
@parsed.keywords.to_a
|
18
|
+
end
|
19
|
+
|
20
|
+
def doUpload(uploader)
|
21
|
+
uploader.upload(file, tags)
|
22
|
+
end
|
23
|
+
|
24
|
+
def archive(to_dir)
|
25
|
+
date_taken = @parsed.date_time_original
|
26
|
+
target_dir = File.join(
|
27
|
+
to_dir,
|
28
|
+
date_taken.strftime("%y"),
|
29
|
+
date_taken.strftime("%m")
|
30
|
+
)
|
31
|
+
|
32
|
+
File.makedirs(target_dir)
|
33
|
+
FileUtils.mv(@file, File.join(target_dir, File.basename(@file)))
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require 'rubygems'
|
3
|
+
require "flickraw"
|
4
|
+
require "flickrup/logging"
|
5
|
+
|
6
|
+
class Uploader
|
7
|
+
include Logging
|
8
|
+
|
9
|
+
def initialize(api_key, shared_secret)
|
10
|
+
FlickRaw.api_key= api_key
|
11
|
+
FlickRaw.shared_secret=shared_secret
|
12
|
+
|
13
|
+
@token_file = File.join(ENV['HOME'], ".flickrup")
|
14
|
+
@flickr = FlickRaw::Flickr.new
|
15
|
+
|
16
|
+
if File.exist?(@token_file)
|
17
|
+
token = YAML.load_file(@token_file)
|
18
|
+
@flickr.access_token = token["access"]
|
19
|
+
@flickr.access_secret = token["secret"]
|
20
|
+
end
|
21
|
+
|
22
|
+
begin
|
23
|
+
login = @flickr.test.login
|
24
|
+
rescue FlickRaw::OAuthClient::FailedResponse => e
|
25
|
+
get_token
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_token
|
31
|
+
token = @flickr.get_request_token
|
32
|
+
auth_url = @flickr.get_authorize_url(token['oauth_token'], :perms => 'write')
|
33
|
+
|
34
|
+
puts "Open this url in your process to complete the authentication process : #{auth_url}"
|
35
|
+
puts "Copy here the number given when you complete the process."
|
36
|
+
verify = gets.strip
|
37
|
+
|
38
|
+
begin
|
39
|
+
@flickr.get_access_token(token['oauth_token'], token['oauth_token_secret'], verify)
|
40
|
+
token = {"access" => @flickr.access_token, "secret" => @flickr.access_secret}
|
41
|
+
login = @flickr.test.login
|
42
|
+
puts "You are now authenticated as #{login.username}"
|
43
|
+
File.open(@token_file, 'w') { |f| f.write(token.to_yaml) }
|
44
|
+
rescue FlickRaw::OAuthClient::FailedResponse => e
|
45
|
+
puts "Authentication failed : #{e.msg}"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def upload(image, tags)
|
51
|
+
logger.debug("Uploading #{image} with tags #{tags.join(",")}")
|
52
|
+
@flickr.upload_photo(image, :tags => tags.join(" "))
|
53
|
+
logger.debug("Uploaded #{image}")
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/lib/flickrup.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "rubygems"
|
3
|
+
require "trollop"
|
4
|
+
require "logger"
|
5
|
+
require "flickrup/quick_listener"
|
6
|
+
require "flickrup/slow_listener"
|
7
|
+
require "flickrup/tagged_image"
|
8
|
+
require "flickrup/uploader"
|
9
|
+
require "flickrup/processor"
|
10
|
+
require "flickrup/logging"
|
11
|
+
|
12
|
+
|
13
|
+
module Flickrup
|
14
|
+
|
15
|
+
def self.run_cmd(args = ARGV)
|
16
|
+
Runner.new.run(args)
|
17
|
+
end
|
18
|
+
|
19
|
+
class Runner
|
20
|
+
include Logging
|
21
|
+
|
22
|
+
def run(args = ARGV)
|
23
|
+
opts = Trollop::options do
|
24
|
+
opt :once, "Run single pass" # flag --once, default false
|
25
|
+
opt :nowait, "Upload immediately on change, no delay"
|
26
|
+
opt :loglevel, "Logging level", :type => :string, :default => "INFO"
|
27
|
+
opt :config, "Configuration file", :type => :string, :default => './flickrup.yml'
|
28
|
+
end
|
29
|
+
|
30
|
+
logger.level = Logger::Severity.const_get(opts.loglevel)
|
31
|
+
|
32
|
+
config = YAML::load(File.open(opts.config, "r"))
|
33
|
+
|
34
|
+
if opts.once
|
35
|
+
Processor.new(config).run
|
36
|
+
elsif opts.nowait
|
37
|
+
QuickListener.new(config).run
|
38
|
+
else
|
39
|
+
SlowListener.new(config).run
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: flickrup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jonathan Gilbert
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-12-21 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: atomic
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 23
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 0
|
32
|
+
- 0
|
33
|
+
version: 1.0.0
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: listen
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 7
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 6
|
48
|
+
- 0
|
49
|
+
version: 0.6.0
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: rufus-scheduler
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 15
|
61
|
+
segments:
|
62
|
+
- 2
|
63
|
+
- 0
|
64
|
+
- 0
|
65
|
+
version: 2.0.0
|
66
|
+
type: :runtime
|
67
|
+
version_requirements: *id003
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: mini_exiftool
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 15
|
77
|
+
segments:
|
78
|
+
- 1
|
79
|
+
- 6
|
80
|
+
- 0
|
81
|
+
version: 1.6.0
|
82
|
+
type: :runtime
|
83
|
+
version_requirements: *id004
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: flickraw
|
86
|
+
prerelease: false
|
87
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
hash: 55
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
- 9
|
96
|
+
- 6
|
97
|
+
version: 0.9.6
|
98
|
+
type: :runtime
|
99
|
+
version_requirements: *id005
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: trollop
|
102
|
+
prerelease: false
|
103
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
hash: 15
|
109
|
+
segments:
|
110
|
+
- 2
|
111
|
+
- 0
|
112
|
+
- 0
|
113
|
+
version: 2.0.0
|
114
|
+
type: :runtime
|
115
|
+
version_requirements: *id006
|
116
|
+
description: Flickr auto uploading script
|
117
|
+
email: bb..jgilbert@xoxy.net
|
118
|
+
executables:
|
119
|
+
- flickrup
|
120
|
+
extensions: []
|
121
|
+
|
122
|
+
extra_rdoc_files: []
|
123
|
+
|
124
|
+
files:
|
125
|
+
- lib/flickrup/logging.rb
|
126
|
+
- lib/flickrup/processor.rb
|
127
|
+
- lib/flickrup/quick_listener.rb
|
128
|
+
- lib/flickrup/slow_listener.rb
|
129
|
+
- lib/flickrup/tagged_image.rb
|
130
|
+
- lib/flickrup/uploader.rb
|
131
|
+
- lib/flickrup.rb
|
132
|
+
- bin/flickrup
|
133
|
+
homepage: http://bitbucket.org/jgilbert/flickrup
|
134
|
+
licenses: []
|
135
|
+
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
hash: 3
|
147
|
+
segments:
|
148
|
+
- 0
|
149
|
+
version: "0"
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
hash: 3
|
156
|
+
segments:
|
157
|
+
- 0
|
158
|
+
version: "0"
|
159
|
+
requirements: []
|
160
|
+
|
161
|
+
rubyforge_project:
|
162
|
+
rubygems_version: 1.8.24
|
163
|
+
signing_key:
|
164
|
+
specification_version: 3
|
165
|
+
summary: Flickr Uploader!
|
166
|
+
test_files: []
|
167
|
+
|