class DownloadTV::Downloader

Entry point of the application
#

def check_date(offset)

def check_date(offset)
  last = @config.content[:date]
  if last - offset != Date.today
    last - offset
  else
    puts 'Everything up to date'
    exit
  end
end

def detect_os

def detect_os
  case RbConfig::CONFIG['host_os']
  when /linux/
    'xdg-open'
  when /darwin/
    'open'
  else
    warn "You're using an unsupported platform."
    exit 1
  end
end

def download(link)

Uses xdg-open (not portable)
Spawns a silent process to download a given magnet link
#
def download(link)
  @cmd ||= detect_os
  exec = "#{@cmd} \"#{link}\""
  Process.detach(Process.spawn(exec, %i[out err] => '/dev/null'))
end

def download_from_file(filename)

Given a file containing a list of episodes (one per line), it tries to find download links for each
#
def download_from_file(filename)
  if File.exist? filename
    filename = File.realpath(filename)
    t = Torrent.new(@config.content[:grabber])
    File.readlines(filename).each { |show| download(get_link(t, show.chomp)) }
  else
    puts "Error: #{filename} not found"
    exit 1
  end
end

def download_single_show(show)

def download_single_show(show)
  t = Torrent.new(@config.content[:grabber])
  download(get_link(t, show))
end

def filter_shows(links)

These filters are defined at @filters
Iteratively applies filters until they've all been applied or applying the next filter would result in no results
#
def filter_shows(links)
  @filters.each do |f| # Apply each filter
    new_links = links.reject { |name, _link| f.call(name) }
    # Stop if the filter removes every release
    break if new_links.empty?
    links = new_links
  end
  links
end

def fix_names(shows)

* Removes apostrophes, colons and parens
* Removes ignored shows

Given a list of shows and episodes:
#
def fix_names(shows)
  # Ignored shows
  s = shows.reject do |i|
    # Remove season+episode
    @config.content[:ignored].include?(i.split(' ')[0..-2].join(' ').downcase)
  end
  s.map { |i| i.gsub(/ \(.+\)|[':]/, '') }
end

def get_link(t, show)

Returns either a magnet link or an emptry string
When it's false it will prompt the user to select the preferred result
When :auto is true it will try to find the best match based on a set of filters
Uses a Torrent object to obtain links to the given tv show
#
def get_link(t, show)
  links = t.get_links(show)
  return '' if links.empty?
  if @config.content[:auto]
    links = filter_shows(links)
    links.first[1]
  else
    puts "Collecting links for #{show}"
    links.each_with_index { |data, i| puts "#{i}\t\t#{data[0]}" }
    puts
    print 'Select the torrent you want to download [-1 to skip]: '
    i = $stdin.gets.chomp.to_i
    while i >= links.size || i < -1
      puts 'Index out of bounds. Try again [-1 to skip]: '
      i = $stdin.gets.chomp.to_i
    end
    # Use -1 to skip the download
    i == -1 ? '' : links[i][1]
  end
end

def initialize(config = {})

def initialize(config = {})
  @config = Configuration.new(config) # Load configuration
  @filters = [
    ->(n) { n.include?('2160p') },
    ->(n) { n.include?('1080p') },
    ->(n) { n.include?('720p')  },
    ->(n) { n.include?('WEB')   },
    ->(n) { !n.include?('PROPER') && !n.include?('REPACK') }
  ]
  Thread.abort_on_exception = true
end

def run(dont_update_last_run, offset = 0)

It connects to MyEpisodes in order to find which shows to track and which new episodes aired.
Finds download links for all new episodes aired since the last run of the program
#
def run(dont_update_last_run, offset = 0)
  date = check_date(offset)
  myepisodes = MyEpisodes.new(@config.content[:myepisodes_user], @config.content[:cookie])
  # Log in using cookie by default
  myepisodes.load_cookie
  shows = myepisodes.get_shows(date)
  to_download = fix_names(shows)
  if to_download.empty?
    puts 'Nothing to download'
  else
    t = Torrent.new(@config.content[:grabber])
    queue = Queue.new
    # Adds a link (or empty string to the queue)
    link_t = Thread.new do
      to_download.each { |show| queue << get_link(t, show) }
    end
    # Downloads the links as they are added
    download_t = Thread.new do
      to_download.size.times do
        magnet = queue.pop
        next if magnet == '' # Doesn't download if no torrents are found
        download(magnet)
      end
    end
    # Downloading the subtitles
    # subs_t = @config.content[:subs] and Thread.new do
    #   to_download.each { |show| @s.get_subs(show) }
    # end
    link_t.join
    download_t.join
    # subs_t.join
    puts 'Completed. Exiting...'
  end
  @config.content[:date] = Date.today unless dont_update_last_run
  @config.serialize
rescue InvalidLoginError
  warn 'Wrong username/password combination'
end