ehbrs-tools 0.5.0 → 0.11.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ehbrs/executables.rb +7 -1
  3. data/lib/ehbrs/fs.rb +9 -0
  4. data/lib/ehbrs/fs/compressed_package.rb +48 -0
  5. data/lib/ehbrs/gems.rb +37 -0
  6. data/lib/ehbrs/observers.rb +11 -0
  7. data/lib/ehbrs/observers/base.rb +64 -0
  8. data/lib/ehbrs/observers/with_persistence.rb +34 -0
  9. data/lib/ehbrs/runner/fs.rb +19 -0
  10. data/lib/ehbrs/runner/fs/used_space.rb +161 -0
  11. data/lib/ehbrs/runner/self.rb +19 -0
  12. data/lib/ehbrs/runner/self/test.rb +30 -0
  13. data/lib/ehbrs/runner/vg/ips.rb +67 -18
  14. data/lib/ehbrs/runner/videos/extract.rb +71 -0
  15. data/lib/ehbrs/runner/videos/series.rb +21 -0
  16. data/lib/ehbrs/runner/videos/series/rename.rb +75 -0
  17. data/lib/ehbrs/self.rb +9 -0
  18. data/lib/ehbrs/self/observers/used_space.rb +22 -0
  19. data/lib/ehbrs/self/observers/with_persistence.rb +38 -0
  20. data/lib/ehbrs/tools/version.rb +1 -1
  21. data/lib/ehbrs/user_dirs.rb +34 -0
  22. data/lib/ehbrs/vg/wii/game_file.rb +13 -0
  23. data/lib/ehbrs/videos/extract.rb +11 -0
  24. data/lib/ehbrs/videos/extract/package.rb +75 -0
  25. data/lib/ehbrs/videos/extract/package_file.rb +54 -0
  26. data/lib/ehbrs/videos/series.rb +11 -0
  27. data/lib/ehbrs/videos/series/rename.rb +13 -0
  28. data/lib/ehbrs/videos/series/rename/directory_group.rb +28 -0
  29. data/lib/ehbrs/videos/series/rename/file.rb +114 -0
  30. data/lib/ehbrs/videos/series/rename/file/basename_parser.rb +44 -0
  31. data/lib/ehbrs/videos/series/rename/file/options.rb +30 -0
  32. data/lib/ehbrs/videos/series/rename/line_result.rb +26 -0
  33. data/lib/ehbrs/videos/series/rename/line_result_group.rb +39 -0
  34. data/lib/ehbrs/videos/series/rename/results_builder.rb +32 -0
  35. data/lib/ehbrs/videos/series/rename/season_group.rb +39 -0
  36. data/vendor/eac_ruby_utils/eac_ruby_utils.gemspec +1 -1
  37. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/command.rb +8 -2
  38. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/executable.rb +2 -2
  39. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/fs/extname.rb +30 -0
  40. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/fs/temp.rb +52 -0
  41. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/fs/temp/directory.rb +16 -0
  42. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/fs/temp/file.rb +34 -0
  43. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/on_clean_ruby_environment.rb +5 -16
  44. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/enumerable.rb +4 -0
  45. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/enumerable/boolean_combinations.rb +45 -0
  46. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object/to_pathname.rb +15 -0
  47. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/regexp.rb +4 -0
  48. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/regexp/if_match.rb +16 -0
  49. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/time.rb +4 -0
  50. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/time/default_time_zone_set.rb +5 -0
  51. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/time/local_time_zone.rb +25 -0
  52. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/ruby.rb +9 -0
  53. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/ruby/command.rb +31 -0
  54. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/ruby/on_clean_environment.rb +26 -0
  55. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/version.rb +1 -1
  56. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/fs/extname_spec.rb +18 -0
  57. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/fs/temp/temp_spec.rb +12 -0
  58. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/fs/temp_spec.rb +52 -0
  59. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/enumerable/boolean_combinations_spec.rb +39 -0
  60. metadata +85 -2
@@ -12,12 +12,16 @@ module Ehbrs
12
12
  class GameFile < ::Pathname
13
13
  enable_simple_cache
14
14
 
15
+ DISC_NUMBER_PATTERN = /disc.?(\d)/i.freeze
16
+
15
17
  FORMAT = ::EacRubyUtils::CustomFormat.new(
16
18
  b: :basename,
17
19
  d: :dirname,
20
+ D: :disc_number,
18
21
  e: :extname,
19
22
  i: :id6,
20
23
  n: :disc_name,
24
+ N: :nintendont_basename,
21
25
  t: :database_title,
22
26
  T: :disc_type
23
27
  )
@@ -30,6 +34,10 @@ module Ehbrs
30
34
  properties.fetch('Disc name')
31
35
  end
32
36
 
37
+ def disc_number
38
+ DISC_NUMBER_PATTERN.if_match(basename.to_s, false) { |m| m[1].to_i }.if_present(1)
39
+ end
40
+
33
41
  def disc_type
34
42
  properties.fetch('File & disc type/type')
35
43
  end
@@ -38,6 +46,11 @@ module Ehbrs
38
46
  FORMAT.format(string).with(self)
39
47
  end
40
48
 
49
+ def nintendont_basename
50
+ n = disc_number
51
+ n == 1 ? 'game' : "disc#{n}"
52
+ end
53
+
41
54
  def id6
42
55
  properties.fetch('Disc & part IDs/disc')
43
56
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Ehbrs
6
+ module Videos
7
+ module Extract
8
+ require_sub __FILE__
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+ require 'ehbrs/fs/compressed_package'
5
+ require 'ehbrs/videos/extract/package_file'
6
+
7
+ module Ehbrs
8
+ module Videos
9
+ module Extract
10
+ class Package
11
+ enable_simple_cache
12
+
13
+ common_constructor :path, :target_dir, :qualities do
14
+ self.path = path.to_pathname
15
+ self.target_dir = target_dir.to_pathname
16
+ end
17
+
18
+ delegate :to_s, to: :path
19
+
20
+ def run(delete)
21
+ selected_files.each(&:copy_to_selected_dir)
22
+ files.each(&:move_to_quality_dir)
23
+ extract_dir.rmdir
24
+ path.unlink if delete
25
+ end
26
+
27
+ private
28
+
29
+ def files_uncached
30
+ ::Pathname.glob("#{extract_dir}/**/*").map do |file|
31
+ ::Ehbrs::Videos::Extract::PackageFile.new(self, file)
32
+ end
33
+ end
34
+
35
+ def extract_dir_uncached
36
+ r = target_dir / path.basename
37
+ raise "Extract directory \"#{r}\" is a file" if r.file?
38
+
39
+ r.rmtree if r.directory?
40
+ ::Ehbrs::Fs::CompressedPackage.new(path).extract_to(r)
41
+ r
42
+ end
43
+
44
+ def files_qualities_uncached
45
+ qualities_with_default.select { |q| grouped_files.keys.include?(q) }
46
+ end
47
+
48
+ def grouped_files_uncached
49
+ r = {}
50
+ files.each do |file|
51
+ r[file.quality] ||= []
52
+ r[file.quality] << file
53
+ end
54
+ r
55
+ end
56
+
57
+ def qualities_with_default
58
+ qualities + [::Ehbrs::Videos::Extract::PackageFile::DEFAULT_QUALITY]
59
+ end
60
+
61
+ def selected_dir_uncached
62
+ target_dir / 'selected'
63
+ end
64
+
65
+ def selected_files
66
+ files.select { |f| f.quality == selected_quality }
67
+ end
68
+
69
+ def selected_quality_uncached
70
+ files_qualities.first
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+ require 'ehbrs/fs/compressed_package'
5
+
6
+ module Ehbrs
7
+ module Videos
8
+ module Extract
9
+ class PackageFile
10
+ DEFAULT_QUALITY = '__default__'
11
+
12
+ enable_simple_cache
13
+ common_constructor :package, :path do
14
+ self.path = path.to_pathname
15
+ end
16
+
17
+ def copy_to_selected_dir
18
+ ::FileUtils.cp(path.to_path, selected_dir.to_path)
19
+ end
20
+
21
+ def match_quality?(quality)
22
+ path.basename_sub { |b| b.to_s.downcase }.basename
23
+ .fnmatch?("*#{quality.downcase}*".gsub(/\A\*+/, '*').gsub(/\*+\z/, '*'))
24
+ end
25
+
26
+ def move_to_quality_dir
27
+ ::FileUtils.mv(path.to_path, quality_dir.to_path)
28
+ end
29
+
30
+ private
31
+
32
+ def quality_uncached
33
+ package.qualities.find { |q| match_quality?(q) } || DEFAULT_QUALITY
34
+ end
35
+
36
+ def quality_dir
37
+ r = package.target_dir / quality
38
+ r.mkpath
39
+ r
40
+ end
41
+
42
+ def selected_dir
43
+ r = nil
44
+ r = package.target_dir / 'source' if /\.torrent/ =~ path.to_path
45
+ r = package.target_dir / 'subtitle' if /\.srt/ =~ path.to_path
46
+ raise "Destination unknown: #{path}" unless r
47
+
48
+ r.mkpath
49
+ r
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Ehbrs
6
+ module Videos
7
+ module Series
8
+ require_sub __FILE__
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Ehbrs
6
+ module Videos
7
+ module Series
8
+ module Rename
9
+ require_sub __FILE__
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ehbrs/videos/series/rename/line_result_group'
4
+ require 'ehbrs/videos/series/rename/season_group'
5
+
6
+ module Ehbrs
7
+ module Videos
8
+ module Series
9
+ module Rename
10
+ class DirectoryGroup < LineResultGroup
11
+ def line_out
12
+ name.light_yellow
13
+ end
14
+
15
+ protected
16
+
17
+ def child_key
18
+ :season
19
+ end
20
+
21
+ def child_class
22
+ ::Ehbrs::Videos::Series::Rename::SeasonGroup
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/fs/extname'
4
+ require 'ostruct'
5
+ require_relative 'line_result'
6
+ require_relative 'file/basename_parser'
7
+
8
+ module Ehbrs
9
+ module Videos
10
+ module Series
11
+ module Rename
12
+ class File < ::Ehbrs::Videos::Series::Rename::LineResult
13
+ include ::Ehbrs::Videos::Series::Rename::File::BasenameParser
14
+
15
+ attr_reader :file, :options
16
+
17
+ def initialize(file, options)
18
+ @file = file
19
+ @options = options
20
+ @options = ::OpenStruct.new(options) if options.is_a?(::Hash)
21
+ end
22
+
23
+ def rename
24
+ target = ::File.expand_path(new_name, dirname)
25
+ return if ::File.exist?(target)
26
+
27
+ infov 'Renaming', @file
28
+ FileUtils.mv(@file, target)
29
+ end
30
+
31
+ def season
32
+ return '??' if parse.blank?
33
+
34
+ parse.fetch(:s)
35
+ end
36
+
37
+ def episode
38
+ return '??' if parse.blank?
39
+
40
+ parse.fetch(:e)
41
+ end
42
+
43
+ def dirname
44
+ d = @file
45
+ while d != '/'
46
+ d = ::File.dirname(d)
47
+ return ::File.expand_path(d) + '/' unless ::File.basename(d).starts_with?('_')
48
+ end
49
+ raise "series_dirname not found for #{@file}"
50
+ end
51
+
52
+ def line_out
53
+ "#{episode.green}: " + if new_name == current_name
54
+ current_name.light_black
55
+ else
56
+ "#{new_name} <= #{current_name}"
57
+ end
58
+ end
59
+
60
+ def new_name
61
+ return "#{kernel}-s#{parse[:s]}e#{new_name_episodes}#{extension}" if parse.present?
62
+
63
+ current_name
64
+ end
65
+
66
+ private
67
+
68
+ def current_name
69
+ ::File.expand_path(@file).gsub(/\A#{::Regexp.quote(dirname)}/, '')
70
+ end
71
+
72
+ def rename?
73
+ return false unless new_name
74
+
75
+ current_name != new_name
76
+ end
77
+
78
+ def kernel
79
+ options.kernel || kernel_from_directory_name ||
80
+ raise("Kernel undefined (File: #{@file})")
81
+ end
82
+
83
+ def kernel_from_directory_name
84
+ dir = ::File.basename(dirname).sub(/\([0-9]+\)/, '')
85
+ dir.split(/\W+/).select { |w| /\A[a-z0-9]/.match(w) }.map { |p| p[0].downcase }.join('')
86
+ end
87
+
88
+ def extension
89
+ return options.extension if options.extension
90
+
91
+ extension_by_directory || ::EacRubyUtils::Fs.extname2(current_name)
92
+ end
93
+
94
+ def extension_by_directory
95
+ r = ::File.dirname(current_name)
96
+ return nil if r == '.'
97
+
98
+ r.gsub(/\A_/, '.')
99
+ end
100
+
101
+ def source_episodes
102
+ parse[:e].split('-').map(&:to_i)
103
+ end
104
+
105
+ def new_name_episodes
106
+ source_episodes.map do |i|
107
+ (i + options.episode_increment).to_s.rjust(2, '0')
108
+ end.join('-')
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ehbrs/videos/series/rename/line_result'
4
+
5
+ module Ehbrs
6
+ module Videos
7
+ module Series
8
+ module Rename
9
+ class File < ::Ehbrs::Videos::Series::Rename::LineResult
10
+ module BasenameParser
11
+ FORMATS = [{
12
+ format: /(\d+)(\d{2})(\d{2})/i,
13
+ build: ->(m) { { s: padding(m[1]), e: padding(m[2]) + '-' + padding(m[3]) } }
14
+ }, {
15
+ format: /s(\d+)e(\d+)-(\d+)/i,
16
+ build: ->(m) { { s: padding(m[1]), e: padding(m[2]) + '-' + padding(m[3]) } }
17
+ }, {
18
+ format: /(\d{1,2})\s*[^\d]\s*(\d{2})/i,
19
+ build: ->(m) { { s: padding(m[1]), e: padding(m[2]) } }
20
+ }, {
21
+ format: /(\d+)(\d{2})/i,
22
+ build: ->(m) { { s: padding(m[1]), e: padding(m[2]) } }
23
+ }, {
24
+ format: /(\d{2})/i,
25
+ build: ->(m) { { s: padding(1), e: padding(m[1]) } }
26
+ }].freeze
27
+
28
+ def self.padding(string)
29
+ string.to_s.rjust(2, '0')
30
+ end
31
+
32
+ def parse_uncached
33
+ FORMATS.each do |format|
34
+ m = format.fetch(:format).match(current_name)
35
+ return format.fetch(:build).call(m) if m
36
+ end
37
+ nil
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ehbrs
4
+ module Videos
5
+ module Series
6
+ module Rename
7
+ class File
8
+ class Options
9
+ def initialize(docopt_runner_options)
10
+ @options = docopt_runner_options
11
+ end
12
+
13
+ %w[kernel confirm recursive extension].each do |method|
14
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
15
+ def #{method}
16
+ @options.fetch('--#{method}')
17
+ end
18
+ RUBY_EVAL
19
+ end
20
+
21
+ def episode_increment
22
+ r = @options.fetch('--episode-increment')
23
+ r.present? ? r.to_i : 0
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Ehbrs
6
+ module Videos
7
+ module Series
8
+ module Rename
9
+ class LineResult
10
+ enable_simple_cache
11
+ enable_console_speaker
12
+
13
+ def show(level)
14
+ out(padding_level(level) + line_out + "\n")
15
+ end
16
+
17
+ private
18
+
19
+ def padding_level(level)
20
+ (' ' * level.to_i) + '* '
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end