sicily 0.1.4 → 0.1.5
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.
- 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
|