Class: DownloadTV::Downloader
- Inherits:
-
Object
- Object
- DownloadTV::Downloader
- Defined in:
- lib/download_tv/downloader.rb
Overview
Entry point of the application
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
Instance Method Summary collapse
-
#date_to_check_from(offset) ⇒ Object
Returns the date from which to check shows.
- #detect_os ⇒ Object
-
#download(link) ⇒ Object
Spawns a silent process to download a given magnet link.
-
#download_entire_season(show, season) ⇒ Object
Tries to download episodes in order for a given season, until it can’t find any.
-
#download_from_file(filename) ⇒ Object
Given a file containing a list of episodes (one per line) it tries to find download links for each.
- #download_from_queue(queue) ⇒ Object
- #download_single_show(show, season = nil) ⇒ Object
-
#filter_shows(links) ⇒ Object
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.
- #find_and_download(shows) ⇒ Object
- #find_links(torrent, shows, queue) ⇒ Object
-
#fix_names(shows) ⇒ Object
Given a list of shows and episodes:.
-
#get_link(torrent, show, save_pending: false) ⇒ Object
Uses a Torrent object to obtain links to the given tv show When :auto is true it will try to find the best match based on a set of filters.
- #get_link_from_user(links) ⇒ Object
-
#initialize(config = {}) ⇒ Downloader
constructor
A new instance of Downloader.
- #prompt_links(links) ⇒ Object
-
#reject_ignored(shows) ⇒ Object
Given a list of shows and episodes:.
-
#run(dry_run = false, offset = 0, include_tomorrow: false) ⇒ Object
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.
- #shows_to_download(date, include_tomorrow) ⇒ Object
Constructor Details
#initialize(config = {}) ⇒ Downloader
Returns a new instance of Downloader.
9 10 11 12 13 |
# File 'lib/download_tv/downloader.rb', line 9 def initialize(config = {}) @config = Configuration.new(config) # Load configuration Thread.abort_on_exception = true end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
7 8 9 |
# File 'lib/download_tv/downloader.rb', line 7 def config @config end |
Instance Method Details
#date_to_check_from(offset) ⇒ Object
Returns the date from which to check shows
58 59 60 61 62 |
# File 'lib/download_tv/downloader.rb', line 58 def date_to_check_from(offset) return @config[:date] if offset.zero? Date.today - offset end |
#detect_os ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/download_tv/downloader.rb', line 216 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) ⇒ Object
Spawns a silent process to download a given magnet link
208 209 210 211 212 213 214 |
# File 'lib/download_tv/downloader.rb', line 208 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) ⇒ Object
Tries to download episodes in order for a given season, until it can’t find any
18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/download_tv/downloader.rb', line 18 def download_entire_season(show, season) t = Torrent.new(@config[: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) ⇒ Object
Given a file containing a list of episodes (one per line) it tries to find download links for each
44 45 46 47 48 49 50 51 52 53 54 |
# 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[: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) ⇒ Object
106 107 108 109 110 111 112 113 |
# File 'lib/download_tv/downloader.rb', line 106 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) ⇒ Object
31 32 33 34 35 36 37 38 39 |
# File 'lib/download_tv/downloader.rb', line 31 def download_single_show(show, season = nil) t = Torrent.new(@config[:grabber]) show = fix_names([show]).first if season download_entire_season(show, season) else download(get_link(t, show)) end end |
#filter_shows(links) ⇒ Object
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
201 202 203 204 |
# File 'lib/download_tv/downloader.rb', line 201 def filter_shows(links) @filterer ||= Filterer.new(@config[:filters]) @filterer.filter(links) end |
#find_and_download(shows) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/download_tv/downloader.rb', line 115 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 |
#find_links(torrent, shows, queue) ⇒ Object
99 100 101 102 103 104 |
# File 'lib/download_tv/downloader.rb', line 99 def find_links(torrent, shows, queue) Thread.new do shows.each { |show| queue << get_link(torrent, show, save_pending: true) } queue.close end end |
#fix_names(shows) ⇒ Object
Given a list of shows and episodes:
-
Removes apostrophes, colons and parens
193 194 195 |
# File 'lib/download_tv/downloader.rb', line 193 def fix_names(shows) shows.map { |i| i.gsub(/ \(.+\)|[':]/, '') } end |
#get_link(torrent, show, save_pending: false) ⇒ Object
Uses a Torrent object to obtain links to the given tv show When :auto is true it will try to find the best match based on a set of filters. When it’s false it will prompt the user to select the preferred result Returns either a magnet link or nil
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/download_tv/downloader.rb', line 142 def get_link(torrent, show, save_pending: false) links = torrent.get_links(show) if links.empty? @config[:pending] << show if save_pending return end if @config[:auto] filter_shows(links).first[1] else prompt_links(links) get_link_from_user(links) end end |
#get_link_from_user(links) ⇒ Object
158 159 160 161 162 163 164 165 166 167 |
# File 'lib/download_tv/downloader.rb', line 158 def get_link_from_user(links) i = $stdin.gets.chomp.to_i until i.between?(-1, links.size - 1) puts 'Index out of bounds. Try again [-1 to skip]: ' i = $stdin.gets.chomp.to_i end i == -1 ? nil : links[i][1] end |
#prompt_links(links) ⇒ Object
169 170 171 172 173 174 |
# File 'lib/download_tv/downloader.rb', line 169 def prompt_links(links) links.each_with_index { |data, i| puts "#{i}\t\t#{data[0]}" } puts print 'Select the torrent you want to download [-1 to skip]: ' end |
#reject_ignored(shows) ⇒ Object
Given a list of shows and episodes:
-
Removes ignored shows
180 181 182 183 184 185 186 187 |
# File 'lib/download_tv/downloader.rb', line 180 def reject_ignored(shows) shows.reject do |i| # Remove season+episode @config[:ignored].include?( i.split(' ')[0..-2].join(' ').downcase ) end end |
#run(dry_run = false, offset = 0, include_tomorrow: false) ⇒ Object
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 dry_run
prevents changing the persisted configuration 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
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/download_tv/downloader.rb', line 72 def run(dry_run = false, offset = 0, include_tomorrow: false) pending = @config[:pending].clone @config[:pending].clear pending ||= [] date = date_to_check_from(offset) pending.concat shows_to_download(date, include_tomorrow) if date < (include_tomorrow ? Date.today.next : Date.today) if pending.empty? puts 'Nothing to download' else find_and_download(pending.uniq) puts 'Completed. Exiting...' end unless dry_run @config[:date] = if include_tomorrow Date.today.next else [Date.today, @config[:date]].max end @config.serialize end rescue InvalidLoginError warn 'Wrong username/password combination' end |
#shows_to_download(date, include_tomorrow) ⇒ Object
128 129 130 131 132 133 134 |
# File 'lib/download_tv/downloader.rb', line 128 def shows_to_download(date, include_tomorrow) myepisodes = MyEpisodes.new(@config[:myepisodes_user], @config[:cookie]) shows = myepisodes.get_shows_since(date, include_tomorrow: include_tomorrow) shows = reject_ignored(shows) fix_names(shows) end |