songmeta/songmeta

122 lines
2.6 KiB
Ruby
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env ruby
require "io/console"
require "optparse"
=begin
Limits:
- ~ not properly managed
- \ and / chars may be a problem
Dependencies: vorbis-tools, mid3v2
=end
CTRL_C = "\u0003"
options = {
music_ext: "mp3,ogg",
library: "#{ENV['HOME']}/Music",
yes: false,
dry: false,
}
opt_parse = OptionParser.new do |opts|
opts.banner = "Usage: id3bulk [options] [directories]"
opts.on("-l=PATH", "--library=PATH", "Library to edit music in. Default ~/Music.") do |dir|
options[:library] = dir
end
opts.on("-y", "--yes", "No confirm. Default ask keyboard confirmation.") do
options[:yes] = true
end
opts.on("-d", "--dry-run", "Do not modify files, only show up.") do
options[:dry] = true
end
end
opt_parse.parse!
if ARGV.empty?
puts opt_parse
exit 1
end
if options[:library] != ""
options[:library].gsub!(/^~/, ENV["HOME"])
Dir.chdir options[:library]
end
def execute(cmd, options)
if !options[:dry]
system(cmd)
else
cmd
end
end
class String
def songify!(artist: "")
# handle special chars
tr!(' ', ' ')
# handle special suffix
gsub!(/ \[[\w_-]{11}\]$/, '')
gsub!(/ \([\w_-]{11}\)$/, '')
gsub!(/-[\w_-]{11}$/, '')
gsub!(/[|_-] *Napalm Records/i, '')
gsub!(/\((Official Lyric Video|Official Video|Official)\)/i, '')
gsub!(/Lyrics|\(Lyrics\)$/i, '')
# handle prefix
gsub!(/^#{artist}/i, '')
# handle lost spaces and special chars
gsub!(/^[ _-]*/, '') # leading chars
gsub!(/[\s]+/, ' ') # multiple spaces
end
end
ARGV.each do |dir|
Dir["#{dir}/**/*.{#{options[:music_ext]}}"].each do |filepath|
artist, *subdirs, music = filepath.split("/")
subdirs.filter! { _1 != "" }
artist.tr!('"', "'")
song = music.gsub(/\.(#{options[:music_ext].tr(',', '|')})$/, '')
song.songify!(artist:)
album = subdirs.last || artist
cmd =
if filepath =~ /\.mp3/
"mid3v2 --album \"#{album}\" --artist \"#{artist}\" --song \"#{song}\" \"#{filepath}\""
elsif filepath =~ /\.ogg/
"vorbiscomment -w --tag album=\"#{album}\" --tag artist=\"#{artist}\" --tag song=\"#{song}\" \"#{filepath}\""
else
puts "Can't handle \"#{filepath}\""
next
end
if options[:yes] == true
puts cmd
execute(cmd, options)
else
puts cmd
print "Confirm? (y/N/e) "
char = STDIN.getch
print char
if char == "e" || char == CTRL_C
exit 0
elsif char == "y"
puts `\n#{execute(cmd, options)}`
else
puts "\npass"
end
end
puts
end
end