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 ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'flickrup'
5
+
6
+ Flickrup.run_cmd(ARGV)
@@ -0,0 +1,5 @@
1
+ module Logging
2
+ def logger
3
+ @logger ||= Logger.new(STDOUT)
4
+ end
5
+ end
@@ -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
+