class AppleTvConverter::CommandLine
Public Class Methods
new(*args)
click to toggle source
# File lib/apple_tv_converter/command_line.rb, line 3 def initialize(*args) @skip_subtitles = false @skip_metadata = false @skip_cleanup = false begin options = parse_arguments(args) media_objects = options.media converter = AppleTvConverter::MediaConverter.new(options) media_objects.sort { |a, b| a.original_filename <=> b.original_filename }.each_with_index do |media, index| puts "---[ Processing file #{index + 1} of #{media_objects.length}: #{File.basename(media.original_filename)} ]----------------" converter.process_media media end rescue ArgumentError => e puts "Error: #{e.message}" rescue => e puts "Error: #{e.message}" puts e.backtrace end end
Private Instance Methods
parse_arguments(arguments)
click to toggle source
# File lib/apple_tv_converter/command_line.rb, line 29 def parse_arguments(arguments) require 'optparse' require 'optparse/time' require 'ostruct' id_switch = 0 options = OpenStruct.new options.skip_transcoding = false options.skip_subtitles = false options.skip_metadata = false options.skip_cleanup = false options.add_to_itunes = false options.skip_online_metadata = false options.plex_format = false options.interactive = true options.imdb_id = nil options.tvdb_id = nil options.tmdb_id = nil options.use_absolute_numbering = false options.episode_number_padding = nil options.languages = [] options.media = [] options.season = nil options.episode = nil options.width = -1 options.height = -1 opts = OptionParser.new do |opts| opts.banner = "Usage: apple-tv-converter [options] [file]\n" + " [file] must be provided unless the -d (--dir) switch is present.\n" opts.on('-i', '--id id', "Set a specific id for fetching metadata from online services") do |id| raise ArgumentError.new("Can't supply both --id and --imdb_id, --tvdb_id, or --tmdb_id at the same time!") if id_switch > 0 id_switch = 7 options.imdb_id = id options.tvdb_id = id options.tmdb_id = id end opts.on('--imdb_id id', "Set a specific id for fetching metadata from IMDB") do |id| raise ArgumentError.new("Can't supply both --id and --imdb_id, --tvdb_id, or --tmdb_id at the same time!") if id_switch & 1 > 0 id_switch |= 1 options.imdb_id = id end opts.on('--tvdb_id id', "Set a specific id for fetching metadata from TheTVDB") do |id| raise ArgumentError.new("Can't supply both --id and --imdb_id, --tvdb_id, or --tmdb_id at the same time!") if id_switch & 2 > 0 id_switch |= 2 options.tvdb_id = id end opts.on('--tmdb_id id', "Set a specific id for fetching metadata from TheMovieDB") do |id| raise ArgumentError.new("Can't supply both --id and --imdb_id, --tvdb_id, or --tmdb_id at the same time!") if id_switch & 4 > 0 id_switch |= 4 options.tmdb_id = id end opts.on('-l', '--languages eng,por,...', Array, "Only keep audio and subtitles in the specified languages") do |languages| options.languages.push *languages # If filtering by languages, always include the undetermined language options.languages.push 'und' unless options.languages.include?('und') options.languages.map!(&:to_sym) end opts.on('-d', '--dir DIRECTORY', 'Process all files in DIRECTORY recursively') do |dir| raise ArgumentError.new("Path not found: #{dir}") unless File.exists?(dir) raise ArgumentError.new("Path is not a directory: #{dir}") unless File.directory?(dir) found_files = Dir[File.join(dir, '**', '*')].delete_if do |f| # Skip files with subtitle or ignored extensions, or directories File.directory?(f) || [AppleTvConverter::Media.subtitle_extensions + AppleTvConverter::Media.ignored_extensions].flatten.include?(File.extname(f).gsub(/\./, '').downcase) end options.media.push *(found_files.map do |file| parse_filename(file) end.compact) end opts.on('--itunes', "Add processed file to iTunes library, if it isn't present yet") do |i| options.add_to_itunes = true end opts.on('--os [USERNAME:PASSWORD]', "Download subtitles and infer IMDB ID from opensubtitles.org") do |username_password| options.download_subtitles = true if username_password =~ /^(.*?)\:(.*?)/ options.download_subtitles_username = $1 if username_password =~ /^(.+?)\:.+$/ options.download_subtitles_password = $1 if username_password =~ /^.+?\:(.+)$/ end options.download_subtitles_username = nil if options.download_subtitles_username == '' options.download_subtitles_password = nil if options.download_subtitles_password == '' end opts.on('--plex', 'Rename file(s) to Plex Media Server recommended format') do options.plex_format = true options.skip_online_metadata = false end opts.separator "" opts.on('--no-transcoding', "Don't transcode video or audio") do |v| options.skip_transcoding = true end opts.on('--no-subtitles', "Don't add subtitles") do |v| options.skip_subtitles = true end opts.on('--no-metadata', "Don't add metadata (implies --no-online-metadata)") do |m| options.skip_metadata = true end opts.on('--no-online-metadata', "Don't fetch metadata from online services (IMDB or TheTVDB)") do |m| options.skip_online_metadata = true end opts.on('--no-interactive', "Perform all operations without user intervention, using sensible defaults") do |m| options.interactive = false end opts.on('--no-cleanup', "Don't cleanup the source files after processing") do |c| options.skip_cleanup = true end opts.separator "" opts.separator "Advanced options:" opts.on('--use-absolute-numbering', 'Use absolute numbering for TV Show episodes (specially useful for cartoons)') do |f| options.use_absolute_numbering = true end opts.on('--episode-number-padding NUMBER', 'Set the episode number padding length (ie, 3 for 001, 002, etc.)') do |i| options.episode_number_padding = i.to_i end opts.on('-s', '--season NUMBER', 'Set the season number for TV Shows in case folder/file naming scheme doesn\'t contain right season') do |i| options.season = i.to_i end opts.on('-e', '--episode NUMBER', 'Set the episode number for TV Shows in case folder/file naming scheme doesn\'t contain right episode number') do |i| options.episode = i.to_i end opts.on('--width NUMBER', 'Resize the video to the specified width. If used with --height, can result in a different aspect ratio') do |i| options.width = i.to_i options.width -= options.width % 2 # Ensure it's always a even number end opts.on('--height NUMBER', 'Resize the video to the specified height. If used with --width, can result in a different aspect ratio') do |i| options.height = i.to_i options.height -= options.height % 2 # Ensure it's always a even number end opts.separator "" opts.separator "Other options:" opts.on('-f', '--ffmpeg LOCATION', 'Set path to ffmpeg binary') do |f| FFMPEG.ffmpeg_binary = f end opts.separator "" opts.separator "DEPRECATED options:" opts.on('--imdb', "Gather data from IMDB (optionally specifying movie id)") do puts "Warning: Switch --imdb is DEPRECATED, and will be removed in a future version. It is now activated by default" puts " If you want to specify an id, please use the switch --id." end opts.separator "" opts.separator "Common options:" # No argument, shows at tail. This will print an options summary. # Try it and see! opts.on_tail("-h", "--help", "Show this message") do puts opts exit end # Another typical switch to print the version. opts.on_tail("--version", "Show version") do puts AppleTvConverter::VERSION exit end end opts.parse! arguments options.media.push *(arguments.map { |file| parse_filename(file) }.compact) raise ArgumentError.new("No media file supplied") unless options.media.any? return options end
parse_filename(file)
click to toggle source
# File lib/apple_tv_converter/command_line.rb, line 227 def parse_filename(file) begin return nil unless FFMPEG::Movie.new(file).valid? begin e = AppleTvConverter::Media.new parser = FilenameParser.new(file) e.show = parser.tvshow_name e.season = parser.season_number e.number = parser.episode_number e.last_number = parser.last_episode_number e.original_filename = file return e rescue => exc puts "File.expand_path(file): #{File.expand_path(file)}" puts "Couldn't parse filename, skipping: #{File.basename(file)}" puts "Reason: #{exc.respond_to?(:message) ? exc.message : exc}" puts "In: #{exc.backtrace.join("\n ")}" return nil end rescue Errno::ENOENT puts "File not found: #{file}" rescue Exception => e puts e exit! end end