class DownloadTV::Downloader

Entry point of the application

Attributes

config[R]

Public Class Methods

new(config = {}) click to toggle source
# File lib/download_tv/downloader.rb, line 9
def initialize(config = {})
  @config = Configuration.new(config) # Load configuration

  Thread.abort_on_exception = true
end

Public Instance Methods

date_to_check_from(offset) click to toggle source

Returns the date from which to check shows

# File lib/download_tv/downloader.rb, line 58
def date_to_check_from(offset)
  return @config.content[:date] if offset.zero?

  Date.today - offset
end
detect_os() click to toggle source
# File lib/download_tv/downloader.rb, line 226
def detect_os
  case RbConfig::CONFIG['host_os']
  when /linux/
    'xdg-open'
  when /darwin/
    'open'
  else
    warn "You're using an unsupported platform (#{RbConfig::CONFIG['host_os']})."
    exit 1
  end
end
download(link) click to toggle source

Spawns a silent process to download a given magnet link

# File lib/download_tv/downloader.rb, line 218
def download(link)
  @cmd ||= detect_os

  exec = "#{@cmd} \"#{link}\""

  Process.detach(Process.spawn(exec, %i[out err] => '/dev/null'))
end
download_entire_season(show, season) click to toggle source

Tries to download episodes in order for a given season, until it can't find any

# File lib/download_tv/downloader.rb, line 18
def download_entire_season(show, season)
  t = Torrent.new(@config.content[:grabber])
  season.insert(0, '0') if season.size == 1
  episode = "#{show} s#{season}e01"
  loop do
    link = get_link(t, episode)
    break if link.empty?

    download(link)
    episode = episode.next
  end
end
download_from_file(filename) click to toggle source

Given a file containing a list of episodes (one per line) it tries to find download links for each

# File lib/download_tv/downloader.rb, line 44
def download_from_file(filename)
  if File.exist? filename
    filename = File.realpath(filename)
    t = Torrent.new(@config.content[:grabber])
    to_download = File.readlines(filename, chomp: true)
    fix_names(to_download).each { |show| download(get_link(t, show)) }
  else
    puts "Error: #{filename} not found"
    exit 1
  end
end
download_from_queue(queue) click to toggle source
# File lib/download_tv/downloader.rb, line 107
def download_from_queue(queue)
  Thread.new do
    until queue.closed?
      magnet = queue.pop
      download(magnet) if magnet # Doesn't download if no torrents are found
    end
  end
end
download_single_show(show, season = nil) click to toggle source
# File lib/download_tv/downloader.rb, line 31
def download_single_show(show, season = nil)
  t = Torrent.new(@config.content[:grabber])
  show = fix_names([show]).first
  if season
    download_entire_season(show, season)
  else
    download(get_link(t, show))
  end
end
filter_shows(links) click to toggle source

Removes links whose names don't match the user filters Runs until no filters are left to be applied or applying a filter would leave no results

# File lib/download_tv/downloader.rb, line 211
def filter_shows(links)
  @filterer ||= Filterer.new(@config.content[:filters])
  @filterer.filter(links)
end
find_and_download(shows) click to toggle source
# File lib/download_tv/downloader.rb, line 116
def find_and_download(shows)
  t = Torrent.new
  queue = Queue.new

  link_t = find_links(t, shows, queue)

  # Downloads the links as they are added
  download_t = download_from_queue(queue)

  link_t.join
  download_t.join
end
fix_names(shows) click to toggle source

Given a list of shows and episodes:

  • Removes apostrophes, colons and parens

# File lib/download_tv/downloader.rb, line 203
def fix_names(shows)
  shows.map { |i| i.gsub(/ \(.+\)|[':]/, '') }
end
reject_ignored(shows) click to toggle source

Given a list of shows and episodes:

  • Removes ignored shows

# File lib/download_tv/downloader.rb, line 191
def reject_ignored(shows)
  shows.reject do |i|
    # Remove season+episode
    @config.content[:ignored]
           .include?(i.split(' ')[0..-2].join(' ').downcase)
  end
end
run(dont_update_last_run, offset = 0, include_tomorrow: false) click to toggle source

Finds download links for all new episodes aired since the last run of the program It connects to MyEpisodes in order to find which shows to track and which new episodes aired. The param dont_update_last_run prevents changing the configuration's date value The param offset can be used to move the date back that many days in the check The param include_tomorrow will add the current day to the list of dates to search

# File lib/download_tv/downloader.rb, line 72
def run(dont_update_last_run, offset = 0, include_tomorrow: false)
  pending = @config.content[:pending].clone
  @config.content[:pending].clear
  pending ||= []
  date = date_to_check_from(offset)

  pending.concat shows_to_download(date) if date < Date.today
  pending.concat today_shows_to_download if include_tomorrow && date < Date.today.next

  if pending.empty?
    puts 'Nothing to download'
  else
    find_and_download(pending.uniq)
    puts 'Completed. Exiting...'
  end

  unless dont_update_last_run
    @config.content[:date] = if include_tomorrow
                               Date.today.next
                             else
                               [Date.today, @config.content[:date]].max
                             end
  end
  @config.serialize
rescue InvalidLoginError
  warn 'Wrong username/password combination'
end
shows_to_download(date) click to toggle source
# File lib/download_tv/downloader.rb, line 129
def shows_to_download(date)
  myepisodes = MyEpisodes.new(@config.content[:myepisodes_user],
                              @config.content[:cookie])
  myepisodes.load_cookie
  shows = myepisodes.get_shows_since(date)
  shows = reject_ignored(shows)
  fix_names(shows)
end
today_shows_to_download() click to toggle source
# File lib/download_tv/downloader.rb, line 138
def today_shows_to_download
  myepisodes = MyEpisodes.new(@config.content[:myepisodes_user],
                              @config.content[:cookie])
  myepisodes.load_cookie
  shows = myepisodes.today_shows
  shows = reject_ignored(shows)
  fix_names(shows)
end