bin/iml

Summary

Maintainability
Test Coverage
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'iml'
require 'optparse'

options = {}
@logger = Logger.new(STDOUT)

begin
  OptionParser.new do |opts|
    opts.banner = "Usage: #{File.basename $PROGRAM_NAME} [options] MEDIA_FILE [MEDIA_FILE] ..."

    opts.on('-v', '--[no-]verbose', 'Run verbosely') do |v|
      options[:verbose] = v
    end
    opts.on('-p', '--[no-]pretend', 'Dry run, do not move any files') do |p|
      options[:pretend] = p
    end
    opts.on('-t', '--target PATH', 'Path to move media files to, default: current directory') do |t|
      options[:target] = t
    end
    opts.on('-o', '--movie-format FORMAT', "Format of the output path of movies, default: '#{IML::Movie::DEFAULT_FORMAT}'") do |f|
      options[:movie_format] = f
    end
    opts.on('-O', '--tv-format FORMAT', "Format of the output path of TV series, default: '#{IML::TVSeries::DEFAULT_FORMAT}'") do |f|
      options[:tv_format] = f
    end
    opts.on('-l', '--list-formats', 'Format description') do |f|
      options[:format] = f
    end
    opts.on('-f', '--force', 'Use the force, override output files') do |f|
      options[:force] = f
    end
    puts opts if opts.default_argv.empty? && STDIN.tty?
  end.parse!
rescue OptionParser::InvalidOption => e
  @logger.error e.message
end

if options[:format]
  puts <<~FORMAT
    Formatting description:
    %T - title
    %t - episode title
    %Y - year
    %S - season number string as found in the input path
    %s - season number integer
    %E - episode number string as found in the input path
    %e - episode number integer
    %g - group name
    %a - audio codec
    %v - video codec
    %f - file format / extension
    %z - source
    %q - quality

  FORMAT
  exit
end

input = STDIN.tty? ? ARGV : $stdin.readlines

input ||= ARGV

def file_operations(path, media, options)
  pathname = media.pathname
  dirname = pathname.dirname
  unless dirname.to_s == '.'
    @logger.info "Creating #{dirname}" if options[:verbose] || options[:pretend]
    media.create_dir
  end
  @logger.info "Moving #{path} to #{pathname}" if options[:verbose] || options[:pretend]
  media.move(path)
end

input.map { |p| Pathname(p.chomp) }.tqdm(desc: 'Processing input', leave: true).each do |path|
  filename = path.basename.to_s
  unless path.exist?
    @logger.warn("File #{path} does not exist, skipping")
    next
  end
  media = IML::Text.new(filename, options).detect
  unless media
    @logger.warn "#{path} doesn't look like a media file" if options[:verbose] || options[:pretend]
    next
  end
  if media.movie?
    media.format_string = options[:movie_format] if options[:movie_format]
    @logger.info "#{path} looks like a movie"
  elsif media.tv?
    media.format_string = options[:tv_format] if options[:tv_format]
    @logger.info "#{path} looks like a TV series"
  end
  file_operations(path, media, options)
end