sicily 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +17 -0
- data/.ruby-version +1 -1
- data/Gemfile +4 -2
- data/Gemfile.lock +1 -1
- data/README.md +11 -6
- data/Rakefile +5 -3
- data/bin/console +6 -4
- data/exe/sicily +69 -69
- data/generator/god.rb +12 -10
- data/generator/google_photo.rb +18 -14
- data/generator/rules.rb +22 -13
- data/generator/schedule.rb +10 -8
- data/lib/sicily.rb +48 -22
- data/lib/sicily/batch_processor.rb +47 -26
- data/lib/sicily/config.rb +6 -4
- data/lib/sicily/error/monitor_error.rb +6 -0
- data/lib/sicily/file_processor.rb +9 -1
- data/lib/sicily/generator.rb +3 -1
- data/lib/sicily/logger.rb +51 -0
- data/lib/sicily/monitor.rb +26 -8
- data/lib/sicily/task/dummy_task.rb +4 -2
- data/lib/sicily/task/file_task.rb +24 -13
- data/lib/sicily/task/google_photo_task.rb +33 -10
- data/lib/sicily/task/resize_task.rb +11 -11
- data/lib/sicily/task_loader.rb +30 -10
- data/lib/sicily/util/exif_util.rb +4 -2
- data/lib/sicily/util/file_util.rb +10 -7
- data/lib/sicily/util/image_util.rb +3 -1
- data/lib/sicily/util/notification_util.rb +19 -6
- data/lib/sicily/version.rb +3 -1
- data/sicily.gemspec +34 -35
- metadata +37 -37
@@ -1,38 +1,59 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sicily/config'
|
4
|
+
require 'sicily/file_processor'
|
5
|
+
require 'sicily/util/notification_util'
|
4
6
|
|
5
7
|
module Sicily
|
6
8
|
class BatchProcessor
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
9
|
+
def initialize(files)
|
10
|
+
@files = files
|
11
|
+
@pool = Concurrent::FixedThreadPool.new(Sicily.config.num_thread_pool)
|
12
|
+
@latch = Concurrent::CountDownLatch.new(@files.size)
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(&user_rule_block)
|
16
|
+
return if @files.empty?
|
17
|
+
|
18
|
+
notify_beginning
|
19
|
+
process_files_in_thread(&user_rule_block)
|
20
|
+
notify_done_when_finished
|
21
|
+
end
|
22
|
+
|
23
|
+
def notify_beginning
|
24
|
+
Util::NotificationUtil.notify_beginning(@files)
|
25
|
+
end
|
26
|
+
|
27
|
+
def process_files_in_thread(&user_rule_block)
|
28
|
+
@files.each do |file|
|
29
|
+
process_each_file_in_thread file, &user_rule_block
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def process_each_file_in_thread(file, &user_rule_block)
|
34
|
+
@pool.post do
|
35
|
+
process_added_file(file, &user_rule_block)
|
36
|
+
@latch.count_down
|
22
37
|
end
|
38
|
+
end
|
23
39
|
|
24
|
-
|
25
|
-
|
26
|
-
|
40
|
+
def notify_done_when_finished
|
41
|
+
@pool.post do
|
42
|
+
@latch.wait
|
43
|
+
notify_done
|
27
44
|
end
|
28
45
|
end
|
29
46
|
|
30
|
-
def process_added_file(file, &
|
31
|
-
FileProcessor.new(file)
|
47
|
+
def process_added_file(file, &user_rule_block)
|
48
|
+
file_processor = FileProcessor.new(file)
|
49
|
+
file_processor.instance_eval(&user_rule_block)
|
50
|
+
file_processor.info 'Done'
|
51
|
+
rescue RuntimeError => e
|
52
|
+
Sicily.logger.error e.message
|
32
53
|
end
|
33
54
|
|
34
|
-
def
|
35
|
-
Util::NotificationUtil.
|
55
|
+
def notify_done
|
56
|
+
Util::NotificationUtil.notify_done(@files)
|
36
57
|
end
|
37
58
|
end
|
38
|
-
end
|
59
|
+
end
|
data/lib/sicily/config.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sicily
|
2
4
|
class << self
|
3
5
|
attr_accessor :config
|
@@ -5,15 +7,15 @@ module Sicily
|
|
5
7
|
|
6
8
|
class Config
|
7
9
|
attr_reader :forbid_new_file_in_subfolder,
|
8
|
-
:
|
9
|
-
:
|
10
|
+
:num_thread_pool,
|
11
|
+
:delay_on_file_monitoring
|
10
12
|
|
11
13
|
def initialize
|
12
14
|
@forbid_new_file_in_subfolder = true
|
13
|
-
@notify_when_done = true
|
14
15
|
@num_thread_pool = 50
|
16
|
+
@delay_on_file_monitoring = 10
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
20
|
Sicily.config = Config.new
|
19
|
-
end
|
21
|
+
end
|
@@ -1,7 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sicily
|
2
4
|
class FileProcessor
|
3
5
|
def initialize(path)
|
4
6
|
@path = path
|
7
|
+
@tag = File.basename(path)
|
8
|
+
info 'Start processing...'
|
9
|
+
end
|
10
|
+
|
11
|
+
def info(message)
|
12
|
+
Sicily.logger.info "#{@tag}\t=>\t#{message}"
|
5
13
|
end
|
6
14
|
end
|
7
|
-
end
|
15
|
+
end
|
data/lib/sicily/generator.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module Sicily
|
6
|
+
class << self
|
7
|
+
attr_accessor :logger
|
8
|
+
end
|
9
|
+
|
10
|
+
class LoggerWrapper
|
11
|
+
def initialize
|
12
|
+
create_logger
|
13
|
+
end
|
14
|
+
|
15
|
+
def unknown(*args)
|
16
|
+
@logger.unknown(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def fatal(*args)
|
20
|
+
@logger.fatal(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def error(*args)
|
24
|
+
@logger.error(*args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def warn(*args)
|
28
|
+
@logger.warn(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def info(*args)
|
32
|
+
@logger.info(*args)
|
33
|
+
end
|
34
|
+
|
35
|
+
def debug(*args)
|
36
|
+
@logger.debug(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def create_logger
|
42
|
+
@logger = if $SICILY_LOG_TO_FILE
|
43
|
+
Logger.new File.join(File.dirname(__FILE__), '../../monitor.log')
|
44
|
+
else
|
45
|
+
Logger.new STDOUT
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Sicily.logger = LoggerWrapper.new
|
51
|
+
end
|
data/lib/sicily/monitor.rb
CHANGED
@@ -1,16 +1,34 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'listen'
|
4
|
+
require 'concurrent'
|
5
|
+
require 'sicily/batch_processor'
|
6
|
+
require 'sicily/error/monitor_error'
|
4
7
|
|
5
8
|
module Sicily
|
6
9
|
class Monitor
|
7
|
-
def on(path, &
|
10
|
+
def on(path, &user_rule_block)
|
11
|
+
Sicily.logger.info "Starting a monitor on #{path}"
|
12
|
+
path = validate_and_expand_path(path)
|
13
|
+
start_listener(path) do |files|
|
14
|
+
BatchProcessor.new(files).run(&user_rule_block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate_and_expand_path(path)
|
8
19
|
path = File.expand_path(path)
|
9
|
-
raise "Unknown path : #{path}" unless File.
|
10
|
-
|
11
|
-
|
20
|
+
raise MonitorError, "Monitor Failed. Unknown path : #{path}" unless File.exist?(path)
|
21
|
+
path
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def start_listener(path)
|
27
|
+
delay = Sicily.config.delay_on_file_monitoring
|
28
|
+
listener = Listen.to(path, wait_for_delay: delay) do |_modified, added, _removed|
|
29
|
+
yield added
|
12
30
|
end
|
13
31
|
listener.start
|
14
32
|
end
|
15
33
|
end
|
16
|
-
end
|
34
|
+
end
|
@@ -1,21 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'sicily/config'
|
3
5
|
|
4
6
|
module Sicily
|
5
7
|
module Task
|
6
8
|
class Base
|
7
9
|
def self.prepare_dest_path(path_src, path_dest)
|
8
|
-
|
9
|
-
Util::FileUtil.is_related?(path_src, path_dest)
|
10
|
-
|
11
|
-
if cannot_op
|
12
|
-
raise [
|
13
|
-
"Cannot do file operation to child folder",
|
14
|
-
" src : #{path_src}",
|
15
|
-
" dest : #{path_dest}",
|
16
|
-
].join("\n")
|
17
|
-
return
|
18
|
-
end
|
10
|
+
check_if_can_operate(path_dest, path_src)
|
19
11
|
|
20
12
|
final_dest_path = Util::FileUtil.eval_dest_path(path_src, path_dest)
|
21
13
|
final_dest_path = File.expand_path final_dest_path
|
@@ -23,20 +15,39 @@ module Sicily
|
|
23
15
|
|
24
16
|
final_dest_path
|
25
17
|
end
|
18
|
+
|
19
|
+
def self.check_if_can_operate(path_dest, path_src)
|
20
|
+
return unless cannot_op(path_dest, path_src)
|
21
|
+
|
22
|
+
msg = [
|
23
|
+
'Cannot do file operation to child folder', "src : #{path_src}", "dest : #{path_dest}"
|
24
|
+
].join('\n')
|
25
|
+
raise msg
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.cannot_op(path_dest, path_src)
|
29
|
+
forbid_new_file_in_subfolder = Sicily.config.forbid_new_file_in_subfolder
|
30
|
+
related = Util::FileUtil.related?(path_src, path_dest)
|
31
|
+
|
32
|
+
forbid_new_file_in_subfolder && related
|
33
|
+
end
|
26
34
|
end
|
27
35
|
|
28
36
|
module FileTask
|
29
37
|
def mv(path_dest)
|
38
|
+
info "mv to #{path_dest}"
|
30
39
|
path_dest = Base.prepare_dest_path(@path, path_dest)
|
31
40
|
FileUtils.mv @path, path_dest
|
32
41
|
end
|
33
42
|
|
34
43
|
def cp(path_dest)
|
44
|
+
info "cp to #{path_dest}"
|
35
45
|
path_dest = Base.prepare_dest_path(@path, path_dest)
|
36
46
|
FileUtils.cp @path, path_dest
|
37
47
|
end
|
38
48
|
|
39
49
|
def rm
|
50
|
+
info 'rm'
|
40
51
|
FileUtils.rm @path
|
41
52
|
end
|
42
53
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sicily/config'
|
2
4
|
|
3
5
|
module Sicily
|
4
6
|
class << self
|
@@ -17,17 +19,38 @@ module Sicily
|
|
17
19
|
end
|
18
20
|
|
19
21
|
module Task
|
22
|
+
class Base
|
23
|
+
def self.google_photo(path)
|
24
|
+
validate_credentials!
|
25
|
+
cmd = build_command(path)
|
26
|
+
execute_command(cmd)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.execute_command(cmd)
|
30
|
+
`#{cmd}`
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.build_command(path)
|
34
|
+
"upload-gphotos \"#{path}\" -u #{id} -p #{pw}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.pw
|
38
|
+
Sicily.config_google.pw
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.id
|
42
|
+
Sicily.config_google.id
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.validate_credentials!
|
46
|
+
raise 'no google credential' if id.to_s.empty? || pw.to_s.empty?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
20
50
|
module GooglePhotoTask
|
21
51
|
def google_photo
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
if id.to_s.empty? or pw.to_s.empty?
|
26
|
-
raise "no google credential"
|
27
|
-
else
|
28
|
-
cmd = "upload-gphotos \"#{@path}\" -u #{id} -p #{pw}"
|
29
|
-
`#{cmd}`
|
30
|
-
end
|
52
|
+
info 'google_photo'
|
53
|
+
Base.google_photo(@path)
|
31
54
|
end
|
32
55
|
end
|
33
56
|
end
|
@@ -1,27 +1,27 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sicily/util/image_util'
|
4
|
+
require 'fastimage_resize'
|
3
5
|
|
4
6
|
module Sicily
|
5
7
|
module Task
|
6
8
|
class SizeCalculator
|
7
9
|
def self.size_to_fit(container_width, container_height, image_width, image_height)
|
8
|
-
if container_width*image_height > container_height*image_width
|
9
|
-
[(image_width*container_height/image_height).to_i, container_height]
|
10
|
+
if container_width * image_height > container_height * image_width
|
11
|
+
[(image_width * container_height / image_height).to_i, container_height]
|
10
12
|
else
|
11
|
-
[container_width, (image_height*container_width/image_width).to_i]
|
13
|
+
[container_width, (image_height * container_width / image_width).to_i]
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
16
18
|
module ResizeTask
|
17
19
|
def fit_if_photo(container_width, container_height)
|
20
|
+
info "fit_if_photo to #{container_width}x#{container_height}"
|
18
21
|
size = Util::ImageUtil.get_size(@path)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
dest_size = SizeCalculator.size_to_fit container_width, container_height, image_width, image_height
|
23
|
-
FastImage.resize(@path, dest_size[0], dest_size[1], :outfile => @path)
|
22
|
+
dest_size = SizeCalculator.size_to_fit container_width, container_height, size[0], size[1]
|
23
|
+
FastImage.resize(@path, dest_size[0], dest_size[1], outfile: @path)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
27
|
-
end
|
27
|
+
end
|
data/lib/sicily/task_loader.rb
CHANGED
@@ -1,20 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sicily
|
2
4
|
class TaskLoader
|
3
5
|
def load_all_tasks
|
4
|
-
|
6
|
+
list_all_files.each do |file|
|
5
7
|
require file
|
6
|
-
|
7
|
-
|
8
|
-
maybe_module = Task.const_get(module_name)
|
9
|
-
if maybe_module.class.name == "Module"
|
10
|
-
FileProcessor.send(:include, maybe_module)
|
11
|
-
end
|
12
|
-
}
|
8
|
+
include_module_if_exists(file)
|
9
|
+
end
|
13
10
|
end
|
14
11
|
|
15
12
|
private
|
13
|
+
|
14
|
+
def include_module_if_exists(file)
|
15
|
+
maybe_module = guess_module(file)
|
16
|
+
include_the_module(maybe_module) if really_module?(maybe_module)
|
17
|
+
end
|
18
|
+
|
19
|
+
def include_the_module(maybe_module)
|
20
|
+
FileProcessor.send(:include, maybe_module)
|
21
|
+
end
|
22
|
+
|
23
|
+
def really_module?(maybe_module)
|
24
|
+
maybe_module.class.name == 'Module'
|
25
|
+
end
|
26
|
+
|
27
|
+
def guess_module(file)
|
28
|
+
module_name = camelize(File.basename(file, '.*'))
|
29
|
+
Task.const_get(module_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def list_all_files
|
33
|
+
Dir["#{File.dirname(__FILE__)}/task/*.rb"]
|
34
|
+
end
|
35
|
+
|
16
36
|
def camelize(str)
|
17
|
-
str.split('_').map
|
37
|
+
str.split('_').map(&:capitalize).join
|
18
38
|
end
|
19
39
|
end
|
20
|
-
end
|
40
|
+
end
|