scene-toolkit 0.1.8 → 0.2.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.
- data/.gitignore +4 -0
- data/Gemfile +1 -4
- data/Gemfile.lock +22 -10
- data/Rakefile +2 -18
- data/bin/scene-toolkit +2 -3
- data/lib/scene_toolkit/cli/helpers.rb +74 -0
- data/lib/scene_toolkit/cli/playlists.rb +42 -0
- data/lib/scene_toolkit/cli/rename.rb +51 -0
- data/lib/scene_toolkit/cli/verify.rb +66 -0
- data/lib/scene_toolkit/cli.rb +8 -160
- data/lib/scene_toolkit/ext.rb +5 -1
- data/lib/scene_toolkit/release/helpers.rb +23 -0
- data/lib/scene_toolkit/release/rename.rb +15 -0
- data/lib/scene_toolkit/release/validations/checksum.rb +52 -0
- data/lib/scene_toolkit/release/validations/name.rb +20 -0
- data/lib/scene_toolkit/release/validations/playlist.rb +38 -0
- data/lib/scene_toolkit/release/validations/required_files.rb +23 -0
- data/lib/scene_toolkit/release/validations.rb +24 -0
- data/lib/scene_toolkit/release.rb +19 -101
- data/lib/scene_toolkit.rb +3 -7
- data/scene-toolkit.gemspec +16 -56
- metadata +81 -96
- data/lib/scene_toolkit/ext/hash.rb +0 -15
data/.gitignore
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,19 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
scene-toolkit (0.2.0)
|
5
|
+
activesupport (~> 3.0.0)
|
6
|
+
colored
|
7
|
+
i18n
|
8
|
+
nestful
|
9
|
+
optitron
|
10
|
+
|
1
11
|
GEM
|
2
12
|
remote: http://rubygems.org/
|
3
13
|
specs:
|
4
|
-
activesupport (3.0.
|
5
|
-
callsite (0.0.
|
6
|
-
|
7
|
-
|
14
|
+
activesupport (3.0.9)
|
15
|
+
callsite (0.0.5)
|
16
|
+
bundler (~> 1.0.0)
|
17
|
+
colored (1.2)
|
18
|
+
i18n (0.6.0)
|
19
|
+
nestful (0.0.6)
|
20
|
+
activesupport (>= 3.0.0.beta)
|
21
|
+
optitron (0.3.2)
|
8
22
|
callsite (~> 0.0.4)
|
23
|
+
parameters_extra (~> 0.2.0)
|
24
|
+
parameters_extra (0.2.0)
|
9
25
|
ruby2ruby (~> 1.2.4)
|
10
26
|
ruby_parser (~> 2.0)
|
11
27
|
sexp_processor (~> 3.0.4)
|
12
|
-
rainbow (1.1)
|
13
28
|
ruby2ruby (1.2.5)
|
14
29
|
ruby_parser (~> 2.0)
|
15
30
|
sexp_processor (~> 3.0)
|
16
|
-
ruby_parser (2.0.
|
31
|
+
ruby_parser (2.0.6)
|
17
32
|
sexp_processor (~> 3.0)
|
18
33
|
sexp_processor (3.0.5)
|
19
34
|
|
@@ -21,7 +36,4 @@ PLATFORMS
|
|
21
36
|
ruby
|
22
37
|
|
23
38
|
DEPENDENCIES
|
24
|
-
|
25
|
-
i18n (~> 0.5.0)
|
26
|
-
optitron (~> 0.2.2)
|
27
|
-
rainbow (~> 1.1)
|
39
|
+
scene-toolkit!
|
data/Rakefile
CHANGED
@@ -1,18 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'rake'
|
4
|
-
|
5
|
-
begin
|
6
|
-
require 'jeweler'
|
7
|
-
Jeweler::Tasks.new do |gem|
|
8
|
-
gem.name = "scene-toolkit"
|
9
|
-
gem.summary = %Q{Tool to assist scene MP3 library maintenance}
|
10
|
-
gem.description = %Q{Tool to assist scene MP3 library maintenance}
|
11
|
-
gem.email = "knoopx@gmail.com"
|
12
|
-
gem.homepage = "http://github.com/knoopx/scene-toolkit"
|
13
|
-
gem.authors = ["Víctor Martínez"]
|
14
|
-
end
|
15
|
-
Jeweler::GemcutterTasks.new
|
16
|
-
rescue LoadError
|
17
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
-
end
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
data/bin/scene-toolkit
CHANGED
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SceneToolkit
|
4
|
+
class CLI < Optitron::CLI
|
5
|
+
protected
|
6
|
+
|
7
|
+
def heading(release, color, &block)
|
8
|
+
puts release.name.send(color)
|
9
|
+
puts release.path
|
10
|
+
yield
|
11
|
+
puts
|
12
|
+
end
|
13
|
+
|
14
|
+
def warn(message)
|
15
|
+
puts " ✕ #{message}".yellow
|
16
|
+
end
|
17
|
+
|
18
|
+
def info(message)
|
19
|
+
puts " ■ #{message}".yellow
|
20
|
+
end
|
21
|
+
|
22
|
+
def error(message)
|
23
|
+
puts " ✕ #{message}".red
|
24
|
+
end
|
25
|
+
|
26
|
+
def print_errors(release)
|
27
|
+
release.errors.each do |validation, errors|
|
28
|
+
errors.each do |error|
|
29
|
+
warn "[#{validation.to_s.humanize}] #{error}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def print_warnings(release)
|
35
|
+
release.warnings.each do |validation, warnings|
|
36
|
+
warnings.each do |warning|
|
37
|
+
warn "[#{validation.to_s.humanize}] #{warning}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def move_release(release, destination)
|
43
|
+
target_dir = File.join(destination, release.name)
|
44
|
+
info "Moving release to #{target_dir}"
|
45
|
+
|
46
|
+
if File.directory?(target_dir)
|
47
|
+
error "Target directory already exists. Skipping."
|
48
|
+
else
|
49
|
+
begin
|
50
|
+
FileUtils.mv(release.path, target_dir)
|
51
|
+
rescue => e
|
52
|
+
error e.message
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def each_release(source, &block)
|
58
|
+
raise ArgumentError unless block_given?
|
59
|
+
raise ArgumentError("#{source} is not a directory") unless File.directory?(source)
|
60
|
+
|
61
|
+
releases = []
|
62
|
+
|
63
|
+
Dir.glob(File.join(source, "**", "*.mp3")).each do |file|
|
64
|
+
release_path = File.expand_path(File.dirname(file))
|
65
|
+
|
66
|
+
unless releases.include?(release_path)
|
67
|
+
release = SceneToolkit::Release.new(release_path)
|
68
|
+
releases << release_path
|
69
|
+
yield(release)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SceneToolkit
|
4
|
+
class CLI < Optitron::CLI
|
5
|
+
desc "Generate missing or invalid release playlists"
|
6
|
+
opt "force", "Force the modification of existing files"
|
7
|
+
|
8
|
+
def playlists(directory_string)
|
9
|
+
each_release(directory_string) do |release|
|
10
|
+
if release.valid_playlist?
|
11
|
+
heading(release, :green) do
|
12
|
+
info("Skipping. Playlist seems to be OK.")
|
13
|
+
end
|
14
|
+
else
|
15
|
+
heading(release, :green) do
|
16
|
+
print_errors(release)
|
17
|
+
|
18
|
+
candidates = release.files.select { |f| %w(.nfo .m3u .sfv).include?(File.extname(f).downcase) }.group_by { |f| File.basename(f, '.*') }
|
19
|
+
if candidates.none?
|
20
|
+
error "Unable to guess playlist filename"
|
21
|
+
next
|
22
|
+
end
|
23
|
+
|
24
|
+
playlist_filename = [candidates.max { |k, v| v.size }.first, ".m3u"].join
|
25
|
+
|
26
|
+
playlist_path = File.join(release.path, playlist_filename)
|
27
|
+
if File.exist?(playlist_path) and not params[:force]
|
28
|
+
error "Playlist #{playlist_filename} already exists. Use --force to replace it."
|
29
|
+
else
|
30
|
+
info "Generating new playlist: #{playlist_filename}"
|
31
|
+
File.open(playlist_path, "w") do |playlist_file|
|
32
|
+
release.mp3_files.map { |f| File.basename(f) }.each do |mp3_file|
|
33
|
+
playlist_file.puts mp3_file
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'nestful'
|
4
|
+
require 'scene_toolkit/ext'
|
5
|
+
|
6
|
+
module SceneToolkit
|
7
|
+
class CLI < Optitron::CLI
|
8
|
+
class GoogleMatcher
|
9
|
+
def self.match(release)
|
10
|
+
regex = Regexp.new(Regexp.escape(release.name), Regexp::IGNORECASE)
|
11
|
+
response = Nestful.get("http://www.google.com/search", :params => { :q => release.name, :num => 100 })
|
12
|
+
response.scan(regex).uniq.reject(&:downcase?)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class OrlydbMatcher
|
17
|
+
def self.match(release)
|
18
|
+
regex = Regexp.new(Regexp.escape(release.name), Regexp::IGNORECASE)
|
19
|
+
response = Nestful.get("http://orlydb.com", :params => { :q => release.search_string })
|
20
|
+
response.scan(regex).uniq.reject(&:downcase?)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Repair release names"
|
25
|
+
|
26
|
+
def rename(directory_string)
|
27
|
+
each_release(directory_string) do |release|
|
28
|
+
unless release.name.downcase?
|
29
|
+
heading(release, :green) { info "Skipping. Release name seems to be OK." }
|
30
|
+
next
|
31
|
+
end
|
32
|
+
|
33
|
+
match = nil
|
34
|
+
[OrlydbMatcher, GoogleMatcher].each do |matcher|
|
35
|
+
matches = matcher.match(release)
|
36
|
+
if matches.one?
|
37
|
+
match = matches.first
|
38
|
+
break
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if match.present?
|
43
|
+
heading(release, :green) { info "Renamed #{release.name} => #{match}" }
|
44
|
+
release.rename!(match)
|
45
|
+
else
|
46
|
+
heading(release, :red) { error "No matches found for #{release.name}" }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'scene_toolkit/release'
|
4
|
+
|
5
|
+
module SceneToolkit
|
6
|
+
class CLI < Optitron::CLI
|
7
|
+
desc "Verify library or release. Executes all validations if none specified"
|
8
|
+
SceneToolkit::Release.available_validations.each { |name, desc| opt name, desc }
|
9
|
+
opt "hide_valid", "Do not display valid releases"
|
10
|
+
opt "move_invalid_to", "Move INVALID releases to specified folder", :type => :string
|
11
|
+
opt "move_valid_to", "Move VALID releases to specified folder", :type => :string
|
12
|
+
|
13
|
+
def verify(directory_string)
|
14
|
+
validations_to_exec = []
|
15
|
+
SceneToolkit::Release.available_validations.keys.each do |name|
|
16
|
+
validations_to_exec << name if params.delete(name).eql?(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
if validations_to_exec.none?
|
20
|
+
validations_to_exec = SceneToolkit::Release::available_validations.keys
|
21
|
+
end
|
22
|
+
|
23
|
+
invalid_target_directory = params.delete(:move_invalid_to)
|
24
|
+
unless invalid_target_directory.nil?
|
25
|
+
raise ArgumentError.new("#{invalid_target_directory} does not exist") unless File.directory?(invalid_target_directory)
|
26
|
+
end
|
27
|
+
|
28
|
+
valid_target_directory = params.delete(:move_valid_to)
|
29
|
+
unless valid_target_directory.nil?
|
30
|
+
raise ArgumentError.new("#{invalid_target_directory} does not exist") unless File.directory?(valid_target_directory)
|
31
|
+
end
|
32
|
+
|
33
|
+
release_count = 0
|
34
|
+
valid_releases = 0
|
35
|
+
invalid_releases = 0
|
36
|
+
|
37
|
+
each_release(directory_string) do |release|
|
38
|
+
release_count += 1
|
39
|
+
if release.valid?(validations_to_exec)
|
40
|
+
valid_releases += 1
|
41
|
+
if not params[:hide_valid] or not valid_target_directory.nil?
|
42
|
+
heading(release, :green) do
|
43
|
+
print_errors(release)
|
44
|
+
print_warnings(release)
|
45
|
+
unless valid_target_directory.nil?
|
46
|
+
move_release(release, valid_target_directory)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
invalid_releases += 1
|
52
|
+
heading(release, :red) do
|
53
|
+
print_errors(release)
|
54
|
+
print_warnings(release)
|
55
|
+
unless invalid_target_directory.nil?
|
56
|
+
move_release(release, invalid_target_directory)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
puts "#{valid_releases} of #{release_count} releases valid"
|
63
|
+
puts "#{invalid_releases} of #{release_count} releases invalid"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/scene_toolkit/cli.rb
CHANGED
@@ -1,168 +1,16 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
5
|
-
gem 'rainbow', "~> 1.1"
|
6
|
-
gem "optitron", "~> 0.2.2"
|
7
|
-
|
3
|
+
require 'active_support/all'
|
8
4
|
require 'optitron'
|
9
|
-
require '
|
5
|
+
require 'fileutils'
|
6
|
+
require 'colored'
|
7
|
+
require 'scene_toolkit/release'
|
8
|
+
require 'scene_toolkit/cli/helpers'
|
9
|
+
require 'scene_toolkit/cli/playlists'
|
10
|
+
require 'scene_toolkit/cli/rename'
|
11
|
+
require 'scene_toolkit/cli/verify'
|
10
12
|
|
11
13
|
module SceneToolkit
|
12
14
|
class CLI < Optitron::CLI
|
13
|
-
desc "Repair releases"
|
14
|
-
opt "playlist", "Repair wrong playlist or generate missing ones"
|
15
|
-
opt "force", "Force the modification of existing files"
|
16
|
-
|
17
|
-
def repair(directory_string)
|
18
|
-
params.underscore_and_symbolize_keys!
|
19
|
-
|
20
|
-
each_release(directory_string) do |release|
|
21
|
-
if params[:playlist]
|
22
|
-
unless release.valid_playlist?
|
23
|
-
puts release.name.foreground(:red)
|
24
|
-
puts release.path
|
25
|
-
print_errors(release)
|
26
|
-
|
27
|
-
candidates = release.files.select { |f| %w(.nfo .m3u .sfv).include?(File.extname(f).downcase) }.group_by { |f| File.basename(f, '.*') }
|
28
|
-
if candidates.none?
|
29
|
-
puts " ✕ Unable to guess playlist filename".foreground(:red)
|
30
|
-
next
|
31
|
-
end
|
32
|
-
|
33
|
-
playlist_filename = [candidates.max { |k, v| v.size }.first, ".m3u"].join
|
34
|
-
|
35
|
-
playlist_path = File.join(release.path, playlist_filename)
|
36
|
-
if File.exist?(playlist_path) and not params[:force]
|
37
|
-
puts " ✕ Playlist #{playlist_filename} already exists. Use --force to replace it.".foreground(:red)
|
38
|
-
else
|
39
|
-
puts " ■ Generating new playlist: #{playlist_filename}".foreground(:yellow)
|
40
|
-
File.open(playlist_path, "w") do |playlist_file|
|
41
|
-
release.mp3_files.map { |f| File.basename(f) }.each do |mp3_file|
|
42
|
-
playlist_file.puts mp3_file
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
puts
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
desc "Verify library or release. Executes all validations if none specified"
|
53
|
-
opt "name", "Validate release name"
|
54
|
-
opt "required-files", "Validate inclusion of required files"
|
55
|
-
opt "playlist", "Validate playlist against existing files"
|
56
|
-
opt "checksum", "Validate release CRC-32 checksum"
|
57
|
-
opt "hide-valid", "Do not display valid releases"
|
58
|
-
opt "move-invalid-to", "Move INVALID releases to specified folder", :type => :string
|
59
|
-
opt "move-valid-to", "Move VALID releases to specified folder", :type => :string
|
60
|
-
|
61
|
-
def verify(directory_string)
|
62
|
-
params.underscore_and_symbolize_keys!
|
63
|
-
validations = []
|
64
|
-
SceneToolkit::Release::VALIDATIONS.each do |validation|
|
65
|
-
validations << validation if params.delete(validation).eql?(true)
|
66
|
-
end
|
67
|
-
|
68
|
-
if validations.none?
|
69
|
-
validations = SceneToolkit::Release::VALIDATIONS
|
70
|
-
end
|
71
|
-
|
72
|
-
invalid_target_directory = params.delete(:move_invalid_to)
|
73
|
-
unless invalid_target_directory.nil?
|
74
|
-
raise ArgumentError.new("#{invalid_target_directory} does not exist") unless File.directory?(invalid_target_directory)
|
75
|
-
end
|
76
|
-
|
77
|
-
valid_target_directory = params.delete(:move_valid_to)
|
78
|
-
unless valid_target_directory.nil?
|
79
|
-
raise ArgumentError.new("#{invalid_target_directory} does not exist") unless File.directory?(valid_target_directory)
|
80
|
-
end
|
81
|
-
|
82
|
-
release_count = 0
|
83
|
-
valid_releases = 0
|
84
|
-
invalid_releases = 0
|
85
|
-
|
86
|
-
each_release(directory_string) do |release|
|
87
|
-
release_count += 1
|
88
|
-
if release.valid?(validations)
|
89
|
-
valid_releases += 1
|
90
|
-
if not params[:hide_valid] or not valid_target_directory.nil?
|
91
|
-
puts release.name.foreground(:green)
|
92
|
-
puts release.path
|
93
|
-
print_errors(release)
|
94
|
-
print_warnings(release)
|
95
|
-
unless valid_target_directory.nil?
|
96
|
-
move_release(release, valid_target_directory)
|
97
|
-
end
|
98
|
-
puts
|
99
|
-
end
|
100
|
-
else
|
101
|
-
invalid_releases += 1
|
102
|
-
puts release.name.foreground(:red)
|
103
|
-
puts release.path
|
104
|
-
print_errors(release)
|
105
|
-
print_warnings(release)
|
106
|
-
unless invalid_target_directory.nil?
|
107
|
-
move_release(release, invalid_target_directory)
|
108
|
-
end
|
109
|
-
puts
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
puts
|
114
|
-
puts "#{valid_releases} of #{release_count} releases valid".foreground(:yellow)
|
115
|
-
puts "#{invalid_releases} of #{release_count} releases invalid".foreground(:yellow)
|
116
|
-
end
|
117
|
-
|
118
|
-
protected
|
119
|
-
|
120
|
-
def print_errors(release)
|
121
|
-
release.errors.each do |validation, errors|
|
122
|
-
errors.each do |error|
|
123
|
-
puts " ✕ [#{validation.to_s.humanize}] #{error}".foreground(:red)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def print_warnings(release)
|
129
|
-
release.warnings.each do |validation, warnings|
|
130
|
-
warnings.each do |warning|
|
131
|
-
puts " ✕ [#{validation.to_s.humanize}] #{warning}".foreground(:yellow)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def move_release(release, destination)
|
137
|
-
target_dir = File.join(destination, release.name)
|
138
|
-
puts " ■ Moving release to #{target_dir}".foreground(:yellow)
|
139
|
-
|
140
|
-
if File.directory?(target_dir)
|
141
|
-
puts " ✕ Target directory already exists. Skipping.".foreground(:red)
|
142
|
-
else
|
143
|
-
begin
|
144
|
-
FileUtils.mv(release.path, target_dir)
|
145
|
-
rescue => e
|
146
|
-
puts e.message.foreground(:red)
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def each_release(source, &block)
|
152
|
-
raise ArgumentError unless block_given?
|
153
|
-
raise ArgumentError("#{source} is not a directory") unless File.directory?(source)
|
154
|
-
|
155
|
-
releases = []
|
156
|
-
|
157
|
-
Dir.glob(File.join(source, "**", "*.mp3")).each do |file|
|
158
|
-
release_path = File.expand_path(File.dirname(file))
|
159
|
-
|
160
|
-
unless releases.include?(release_path)
|
161
|
-
release = SceneToolkit::Release.new(release_path)
|
162
|
-
releases << release_path
|
163
|
-
yield(release)
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
15
|
end
|
168
16
|
end
|
data/lib/scene_toolkit/ext.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module SceneToolkit
|
2
|
+
class Release
|
3
|
+
module Helpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
has_files_with_extension :mp3, :sfv, :nfo, :m3u
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
protected
|
12
|
+
|
13
|
+
def has_files_with_extension(*exts)
|
14
|
+
exts.each do |ext|
|
15
|
+
define_method "#{ext}_files" do
|
16
|
+
files.select { |f| File.extname(f).downcase.eql?(".#{ext}") }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module SceneToolkit
|
2
|
+
class Release
|
3
|
+
module Rename
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def rename!(new_name)
|
7
|
+
File.rename(@path, File.join(File.dirname(@path), new_name))
|
8
|
+
end
|
9
|
+
|
10
|
+
def search_string
|
11
|
+
@name.gsub(/[^A-Za-z0-9]+/, " ").gsub(/\s+/, " ")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module SceneToolkit
|
2
|
+
class Release
|
3
|
+
module Validations
|
4
|
+
module Checksum
|
5
|
+
def self.included(base)
|
6
|
+
base.register_validation(:checksum, "Validate release CRC-32 checksum")
|
7
|
+
end
|
8
|
+
|
9
|
+
def valid_checksum?
|
10
|
+
@errors[:checksum], @warnings[:checksum] = [], []
|
11
|
+
|
12
|
+
if sfv_files.any?
|
13
|
+
sfv_files.each do |sfv|
|
14
|
+
files_to_check = files.inject({ }) do |collection, file|
|
15
|
+
collection[File.basename(file).downcase] = File.expand_path(file)
|
16
|
+
collection
|
17
|
+
end
|
18
|
+
|
19
|
+
matched_something = false
|
20
|
+
File.read(sfv).split(/[\r\n]+/).each do |line|
|
21
|
+
line.strip!
|
22
|
+
|
23
|
+
if (/(generated|raped)/i =~ line and not /MorGoTH/i =~ line)
|
24
|
+
@warnings[:checksum] << "Possibly tampered SFV: #{line.strip}"
|
25
|
+
end
|
26
|
+
|
27
|
+
if match = /^(.+?)\s+([\dA-Fa-f]{8})$/.match(line)
|
28
|
+
matched_something = true
|
29
|
+
filename, checksum = match.captures
|
30
|
+
filename.strip!
|
31
|
+
filename.downcase!
|
32
|
+
|
33
|
+
if files_to_check.has_key?(filename)
|
34
|
+
unless Zlib.crc32(File.read(files_to_check[filename])).eql?(checksum.hex)
|
35
|
+
@errors[:checksum] << "File #{filename} is corrupted"
|
36
|
+
end
|
37
|
+
else
|
38
|
+
@errors[:checksum] << "File #{filename} not found"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
@warnings[:checksum] << "No files to verify found" unless matched_something
|
43
|
+
end
|
44
|
+
else
|
45
|
+
@errors[:checksum] << "No *.sfv files found"
|
46
|
+
end
|
47
|
+
@errors[:checksum].empty?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SceneToolkit
|
2
|
+
class Release
|
3
|
+
module Validations
|
4
|
+
module Name
|
5
|
+
def self.included(base)
|
6
|
+
base.register_validation(:name, "Validate release name")
|
7
|
+
end
|
8
|
+
|
9
|
+
def valid_name?
|
10
|
+
@errors[:name], @warnings[:name] = [], []
|
11
|
+
|
12
|
+
@errors[:name] << "Release name is not a valid scene release name" unless @name =~ /^([A-Z0-9\-_.()&]+)\-(\d{4}|\d{3}x|\d{2}xx)\-([A-Z0-9_]+)$/i
|
13
|
+
@errors[:name] << "Release name is lowercased" if @name.eql?(@name.downcase)
|
14
|
+
@errors[:name] << "Release name is uppercased" if @name.eql?(@name.upcase)
|
15
|
+
@errors[:name].empty?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SceneToolkit
|
2
|
+
class Release
|
3
|
+
module Validations
|
4
|
+
module Playlist
|
5
|
+
def self.included(base)
|
6
|
+
base.register_validation(:playlist, "Validate playlist against existing files")
|
7
|
+
end
|
8
|
+
|
9
|
+
def valid_playlist?
|
10
|
+
@errors[:playlist], @warnings[:playlist] = [], []
|
11
|
+
if m3u_files.any?
|
12
|
+
m3u_files.each do |playlist|
|
13
|
+
begin
|
14
|
+
validate_playlist(playlist)
|
15
|
+
rescue => e
|
16
|
+
@errors[:playlist] << e.message
|
17
|
+
end
|
18
|
+
end
|
19
|
+
else
|
20
|
+
@errors[:playlist] << "No *.m3u files found"
|
21
|
+
end
|
22
|
+
@errors[:playlist].empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def validate_playlist(playlist)
|
29
|
+
File.read(playlist).split(/[\r\n]+/).each do |filename|
|
30
|
+
filename.strip!
|
31
|
+
next if filename.blank? or filename.start_with?("#") or filename.start_with?(";")
|
32
|
+
@errors[:playlist] << "File #{filename} not found" unless File.exist?(File.join(@path, filename))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SceneToolkit
|
2
|
+
class Release
|
3
|
+
module Validations
|
4
|
+
module RequiredFiles
|
5
|
+
REQUIRED_FILES = [:sfv, :nfo, :m3u]
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.register_validation(:required_files, "Validate inclusion of required files")
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid_required_files?
|
12
|
+
@errors[:required_files], @warnings[:required_files] = [], []
|
13
|
+
REQUIRED_FILES.each do |ext|
|
14
|
+
file_count = send("#{ext}_files")
|
15
|
+
@errors[:required_files] << "No *.#{ext} files found." if file_count.none?
|
16
|
+
@warnings[:required_files] << "Multiple *.#{ext} files found." if file_count.size > 1
|
17
|
+
end
|
18
|
+
@warnings[:required_files].empty?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SceneToolkit
|
2
|
+
class Release
|
3
|
+
module Validations
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def valid?(validations_to_exec = @available_validations)
|
7
|
+
@errors, @warnings = { }, { }
|
8
|
+
validations_to_exec.each do |name|
|
9
|
+
send("valid_#{name}?")
|
10
|
+
end
|
11
|
+
@errors.values.sum { |errors| errors.size }.zero?
|
12
|
+
end
|
13
|
+
|
14
|
+
included do
|
15
|
+
cattr_accessor :available_validations
|
16
|
+
@@available_validations = { }
|
17
|
+
|
18
|
+
def self.register_validation(name, description)
|
19
|
+
@@available_validations[name] = description
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,119 +1,37 @@
|
|
1
1
|
require 'digest/md5'
|
2
2
|
require 'zlib'
|
3
3
|
|
4
|
+
require 'scene_toolkit/release/helpers'
|
5
|
+
require 'scene_toolkit/release/rename'
|
6
|
+
require 'scene_toolkit/release/validations'
|
7
|
+
require 'scene_toolkit/release/validations/checksum'
|
8
|
+
require 'scene_toolkit/release/validations/name'
|
9
|
+
require 'scene_toolkit/release/validations/playlist'
|
10
|
+
require 'scene_toolkit/release/validations/required_files'
|
11
|
+
|
4
12
|
module SceneToolkit
|
5
13
|
class Release
|
6
|
-
REQUIRED_FILES = [:sfv, :nfo, :m3u]
|
7
|
-
VALIDATIONS = [:name, :required_files, :playlist, :checksum]
|
8
|
-
|
9
14
|
attr_accessor :name, :path, :uid
|
10
15
|
attr_accessor :errors, :warnings
|
11
16
|
|
17
|
+
include Validations
|
18
|
+
include Rename
|
19
|
+
include Helpers
|
20
|
+
|
21
|
+
include Validations::Checksum
|
22
|
+
include Validations::Name
|
23
|
+
include Validations::Playlist
|
24
|
+
include Validations::RequiredFiles
|
25
|
+
|
12
26
|
def initialize(path)
|
13
|
-
@path = path
|
27
|
+
@path = File.expand_path(path)
|
14
28
|
@name = File.basename(path)
|
15
29
|
@uid = Digest::MD5.hexdigest(@name.downcase.gsub(/[^A-Z0-9]/i, ' ').gsub(/\s+/, ' '))
|
16
|
-
@errors, @warnings = {}, {}
|
17
|
-
end
|
18
|
-
|
19
|
-
def valid?(validations = VALIDATIONS)
|
20
|
-
@errors, @warnings = {}, {}
|
21
|
-
validations.each do |validation|
|
22
|
-
send("valid_#{validation}?")
|
23
|
-
end
|
24
|
-
@errors.sum { |validation, errors| errors.size }.zero?
|
25
|
-
end
|
26
|
-
|
27
|
-
def valid_required_files?
|
28
|
-
@errors[:required_files], @warnings[:required_files] = [], []
|
29
|
-
REQUIRED_FILES.each do |ext|
|
30
|
-
file_count = send("#{ext}_files")
|
31
|
-
@errors[:required_files] << "No *.#{ext} files found." if file_count.none?
|
32
|
-
@warnings[:required_files] << "Multiple *.#{ext} files found." if file_count.size > 1
|
33
|
-
end
|
34
|
-
@warnings[:required_files].empty?
|
35
|
-
end
|
36
|
-
|
37
|
-
def valid_playlist?
|
38
|
-
@errors[:playlist], @warnings[:playlist] = [], []
|
39
|
-
if m3u_files.any?
|
40
|
-
m3u_files.each do |playlist|
|
41
|
-
File.read(playlist).split(/[\r\n]+/).each do |filename|
|
42
|
-
filename.strip!
|
43
|
-
next if filename.blank? or filename.start_with?("#") or filename.start_with?(";")
|
44
|
-
@errors[:playlist] << "File #{filename} not found" unless File.exist?(File.join(@path, filename))
|
45
|
-
end
|
46
|
-
end
|
47
|
-
else
|
48
|
-
@errors[:playlist] << "No *.m3u files found"
|
49
|
-
end
|
50
|
-
@errors[:playlist].empty?
|
51
|
-
end
|
52
|
-
|
53
|
-
def valid_checksum?
|
54
|
-
@errors[:checksum], @warnings[:checksum] = [], []
|
55
|
-
|
56
|
-
if sfv_files.any?
|
57
|
-
sfv_files.each do |sfv|
|
58
|
-
files_to_check = files.inject({}) do |collection, file|
|
59
|
-
collection[File.basename(file).downcase] = File.expand_path(file)
|
60
|
-
collection
|
61
|
-
end
|
62
|
-
|
63
|
-
matched_something = false
|
64
|
-
File.read(sfv).split(/[\r\n]+/).each do |line|
|
65
|
-
line.strip!
|
66
|
-
|
67
|
-
if (/(generated|raped)/i =~ line and not /MorGoTH/i =~ line)
|
68
|
-
@warnings[:checksum] << "Possibly tampered SFV: #{line.strip}"
|
69
|
-
end
|
70
|
-
|
71
|
-
if match = /^(.+?)\s+([\dA-Fa-f]{8})$/.match(line)
|
72
|
-
matched_something = true
|
73
|
-
filename, checksum = match.captures
|
74
|
-
filename.strip!
|
75
|
-
filename.downcase!
|
76
|
-
|
77
|
-
if files_to_check.has_key?(filename)
|
78
|
-
unless Zlib.crc32(File.read(files_to_check[filename])).eql?(checksum.hex)
|
79
|
-
@errors[:checksum] << "File #{filename} is corrupted"
|
80
|
-
end
|
81
|
-
else
|
82
|
-
@errors[:checksum] << "File #{filename} not found"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
@warnings[:checksum] << "No files to verify found" unless matched_something
|
87
|
-
end
|
88
|
-
else
|
89
|
-
@errors[:checksum] << "No *.sfv files found"
|
90
|
-
end
|
91
|
-
@errors[:checksum].empty?
|
92
|
-
end
|
93
|
-
|
94
|
-
def valid_name?
|
95
|
-
@errors[:name], @warnings[:name] = [], []
|
96
|
-
@errors[:name] << "Release name is not a valid scene release name" unless @name =~ /^([A-Z0-9\-_.()&]+)\-(\d{4}|\d{3}x|\d{2}xx)\-([A-Z0-9_]+)$/i
|
97
|
-
@errors[:name] << "Release name is lowercased" if @name.eql?(@name.downcase)
|
98
|
-
@errors[:name] << "Release name is uppercased" if @name.eql?(@name.upcase)
|
99
|
-
@errors[:name].empty?
|
30
|
+
@errors, @warnings = { }, { }
|
100
31
|
end
|
101
32
|
|
102
33
|
def files
|
103
34
|
Dir.glob(File.join(@path, "*"))
|
104
35
|
end
|
105
|
-
|
106
|
-
class << self
|
107
|
-
protected
|
108
|
-
|
109
|
-
def has_files_with_extension(*exts)
|
110
|
-
exts.each do |ext|
|
111
|
-
define_method "#{ext}_files" do
|
112
|
-
files.select { |f| File.extname(f).downcase.eql?(".#{ext}") }
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
has_files_with_extension :mp3, :sfv, :nfo, :m3u
|
118
36
|
end
|
119
37
|
end
|
data/lib/scene_toolkit.rb
CHANGED
data/scene-toolkit.gemspec
CHANGED
@@ -1,63 +1,23 @@
|
|
1
|
-
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
-
# -*- encoding: utf-8 -*-
|
1
|
+
require File.expand_path("../lib/scene_toolkit", __FILE__)
|
5
2
|
|
6
3
|
Gem::Specification.new do |s|
|
7
4
|
s.name = %q{scene-toolkit}
|
8
|
-
s.version =
|
5
|
+
s.version = SceneToolkit::VERSION
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.homepage = "http://github.com/knoopx/scene-toolkit"
|
8
|
+
s.authors = ["Víctor Martínez"]
|
9
|
+
s.email = ["knoopx@gmail.com"]
|
10
|
+
s.summary = "Tool to assist scene MP3 library maintenance"
|
11
|
+
s.description = "Tool to assist scene MP3 library maintenance"
|
9
12
|
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
s.default_executable = %q{scene-toolkit}
|
14
|
-
s.description = %q{Tool to assist scene MP3 library maintenance}
|
15
|
-
s.email = %q{knoopx@gmail.com}
|
16
|
-
s.executables = ["scene-toolkit"]
|
17
|
-
s.extra_rdoc_files = [
|
18
|
-
"LICENSE",
|
19
|
-
"README.rdoc"
|
20
|
-
]
|
21
|
-
s.files = [
|
22
|
-
"Gemfile",
|
23
|
-
"Gemfile.lock",
|
24
|
-
"LICENSE",
|
25
|
-
"README.rdoc",
|
26
|
-
"Rakefile",
|
27
|
-
"VERSION",
|
28
|
-
"bin/scene-toolkit",
|
29
|
-
"lib/scene_toolkit.rb",
|
30
|
-
"lib/scene_toolkit/cli.rb",
|
31
|
-
"lib/scene_toolkit/ext.rb",
|
32
|
-
"lib/scene_toolkit/ext/hash.rb",
|
33
|
-
"lib/scene_toolkit/release.rb",
|
34
|
-
"scene-toolkit.gemspec"
|
35
|
-
]
|
36
|
-
s.homepage = %q{http://github.com/knoopx/scene-toolkit}
|
37
|
-
s.require_paths = ["lib"]
|
38
|
-
s.rubygems_version = %q{1.3.7}
|
39
|
-
s.summary = %q{Tool to assist scene MP3 library maintenance}
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
40
16
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
s.add_runtime_dependency(%q<activesupport>, ["~> 3.0.0"])
|
47
|
-
s.add_runtime_dependency(%q<i18n>, ["~> 0.5.0"])
|
48
|
-
s.add_runtime_dependency(%q<rainbow>, ["~> 1.1"])
|
49
|
-
s.add_runtime_dependency(%q<optitron>, ["~> 0.2.2"])
|
50
|
-
else
|
51
|
-
s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
|
52
|
-
s.add_dependency(%q<i18n>, ["~> 0.5.0"])
|
53
|
-
s.add_dependency(%q<rainbow>, ["~> 1.1"])
|
54
|
-
s.add_dependency(%q<optitron>, ["~> 0.2.2"])
|
55
|
-
end
|
56
|
-
else
|
57
|
-
s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
|
58
|
-
s.add_dependency(%q<i18n>, ["~> 0.5.0"])
|
59
|
-
s.add_dependency(%q<rainbow>, ["~> 1.1"])
|
60
|
-
s.add_dependency(%q<optitron>, ["~> 0.2.2"])
|
61
|
-
end
|
17
|
+
s.add_dependency("activesupport", ["~> 3.0.0"])
|
18
|
+
s.add_dependency("i18n")
|
19
|
+
s.add_dependency("colored")
|
20
|
+
s.add_dependency("optitron")
|
21
|
+
s.add_dependency("nestful")
|
62
22
|
end
|
63
23
|
|
metadata
CHANGED
@@ -1,96 +1,81 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: scene-toolkit
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 8
|
10
|
-
version: 0.1.8
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
13
|
-
-
|
7
|
+
authors:
|
8
|
+
- Víctor Martínez
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
- !ruby/object:Gem::Dependency
|
22
|
-
prerelease: false
|
23
|
-
type: :runtime
|
12
|
+
date: 2011-07-09 00:00:00.000000000 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
24
16
|
name: activesupport
|
25
|
-
|
17
|
+
requirement: &2157064380 !ruby/object:Gem::Requirement
|
26
18
|
none: false
|
27
|
-
requirements:
|
19
|
+
requirements:
|
28
20
|
- - ~>
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
hash: 7
|
31
|
-
segments:
|
32
|
-
- 3
|
33
|
-
- 0
|
34
|
-
- 0
|
21
|
+
- !ruby/object:Gem::Version
|
35
22
|
version: 3.0.0
|
36
|
-
requirement: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
prerelease: false
|
39
23
|
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2157064380
|
26
|
+
- !ruby/object:Gem::Dependency
|
40
27
|
name: i18n
|
41
|
-
|
28
|
+
requirement: &2157063960 !ruby/object:Gem::Requirement
|
42
29
|
none: false
|
43
|
-
requirements:
|
44
|
-
- -
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
|
47
|
-
segments:
|
48
|
-
- 0
|
49
|
-
- 5
|
50
|
-
- 0
|
51
|
-
version: 0.5.0
|
52
|
-
requirement: *id002
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
prerelease: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
55
34
|
type: :runtime
|
56
|
-
name: rainbow
|
57
|
-
version_requirements: &id003 !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
|
-
requirements:
|
60
|
-
- - ~>
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
hash: 13
|
63
|
-
segments:
|
64
|
-
- 1
|
65
|
-
- 1
|
66
|
-
version: "1.1"
|
67
|
-
requirement: *id003
|
68
|
-
- !ruby/object:Gem::Dependency
|
69
35
|
prerelease: false
|
36
|
+
version_requirements: *2157063960
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: colored
|
39
|
+
requirement: &2157063480 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
70
45
|
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2157063480
|
48
|
+
- !ruby/object:Gem::Dependency
|
71
49
|
name: optitron
|
72
|
-
|
50
|
+
requirement: &2157063060 !ruby/object:Gem::Requirement
|
73
51
|
none: false
|
74
|
-
requirements:
|
75
|
-
- -
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
requirement:
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *2157063060
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: nestful
|
61
|
+
requirement: &2157062640 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :runtime
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *2157062640
|
84
70
|
description: Tool to assist scene MP3 library maintenance
|
85
|
-
email:
|
86
|
-
|
71
|
+
email:
|
72
|
+
- knoopx@gmail.com
|
73
|
+
executables:
|
87
74
|
- scene-toolkit
|
88
75
|
extensions: []
|
89
|
-
|
90
|
-
|
91
|
-
-
|
92
|
-
- README.rdoc
|
93
|
-
files:
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- .gitignore
|
94
79
|
- Gemfile
|
95
80
|
- Gemfile.lock
|
96
81
|
- LICENSE
|
@@ -100,43 +85,43 @@ files:
|
|
100
85
|
- bin/scene-toolkit
|
101
86
|
- lib/scene_toolkit.rb
|
102
87
|
- lib/scene_toolkit/cli.rb
|
88
|
+
- lib/scene_toolkit/cli/helpers.rb
|
89
|
+
- lib/scene_toolkit/cli/playlists.rb
|
90
|
+
- lib/scene_toolkit/cli/rename.rb
|
91
|
+
- lib/scene_toolkit/cli/verify.rb
|
103
92
|
- lib/scene_toolkit/ext.rb
|
104
|
-
- lib/scene_toolkit/ext/hash.rb
|
105
93
|
- lib/scene_toolkit/release.rb
|
94
|
+
- lib/scene_toolkit/release/helpers.rb
|
95
|
+
- lib/scene_toolkit/release/rename.rb
|
96
|
+
- lib/scene_toolkit/release/validations.rb
|
97
|
+
- lib/scene_toolkit/release/validations/checksum.rb
|
98
|
+
- lib/scene_toolkit/release/validations/name.rb
|
99
|
+
- lib/scene_toolkit/release/validations/playlist.rb
|
100
|
+
- lib/scene_toolkit/release/validations/required_files.rb
|
106
101
|
- scene-toolkit.gemspec
|
107
102
|
has_rdoc: true
|
108
103
|
homepage: http://github.com/knoopx/scene-toolkit
|
109
104
|
licenses: []
|
110
|
-
|
111
105
|
post_install_message:
|
112
106
|
rdoc_options: []
|
113
|
-
|
114
|
-
require_paths:
|
107
|
+
require_paths:
|
115
108
|
- lib
|
116
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
110
|
none: false
|
118
|
-
requirements:
|
119
|
-
- -
|
120
|
-
- !ruby/object:Gem::Version
|
121
|
-
|
122
|
-
|
123
|
-
- 0
|
124
|
-
version: "0"
|
125
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
116
|
none: false
|
127
|
-
requirements:
|
128
|
-
- -
|
129
|
-
- !ruby/object:Gem::Version
|
130
|
-
|
131
|
-
segments:
|
132
|
-
- 0
|
133
|
-
version: "0"
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
134
121
|
requirements: []
|
135
|
-
|
136
122
|
rubyforge_project:
|
137
|
-
rubygems_version: 1.
|
123
|
+
rubygems_version: 1.6.2
|
138
124
|
signing_key:
|
139
125
|
specification_version: 3
|
140
126
|
summary: Tool to assist scene MP3 library maintenance
|
141
127
|
test_files: []
|
142
|
-
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module SceneToolkit
|
2
|
-
module Ext
|
3
|
-
module Hash
|
4
|
-
def underscore_and_symbolize_keys!
|
5
|
-
result = self.dup
|
6
|
-
self.each_key do |k|
|
7
|
-
result[k.underscore] = self[k]
|
8
|
-
end
|
9
|
-
result.symbolize_keys!
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
Hash.send(:include, SceneToolkit::Ext::Hash)
|