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_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
-
#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(dont_update_last_run, 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) ⇒ Object
- #today_shows_to_download ⇒ 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
57 58 59 60 61 |
# File 'lib/download_tv/downloader.rb', line 57 def date_to_check_from(offset) return @config.content[:date] if offset.zero? Date.today - offset end |
#detect_os ⇒ Object
220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/download_tv/downloader.rb', line 220 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 |
#download(link) ⇒ Object
Spawns a silent process to download a given magnet link
212 213 214 215 216 217 218 |
# File 'lib/download_tv/downloader.rb', line 212 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 |
# File 'lib/download_tv/downloader.rb', line 18 def download_entire_season(show, season) 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
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/download_tv/downloader.rb', line 43 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_single_show(show, season = nil) ⇒ Object
30 31 32 33 34 35 36 37 38 |
# File 'lib/download_tv/downloader.rb', line 30 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) ⇒ 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
205 206 207 208 |
# File 'lib/download_tv/downloader.rb', line 205 def filter_shows(links) f = Filterer.new(@config.content[:filters]) f.filter(links) end |
#find_and_download(shows) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/download_tv/downloader.rb', line 99 def find_and_download(shows) t = Torrent.new queue = Queue.new # Adds a link (or empty string to the queue) link_t = Thread.new do shows.each { |show| queue << get_link(t, show, save_pending: true) } end # Downloads the links as they are added download_t = Thread.new do shows.size.times do magnet = queue.pop next if magnet == '' # Doesn't download if no torrents are found download(magnet) end end link_t.join download_t.join end |
#fix_names(shows) ⇒ Object
Given a list of shows and episodes:
-
Removes apostrophes, colons and parens
197 198 199 |
# File 'lib/download_tv/downloader.rb', line 197 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 an emptry string
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/download_tv/downloader.rb', line 146 def get_link(torrent, show, save_pending: false) links = torrent.get_links(show) if links.empty? @config.content[:pending] << show if save_pending return '' end if @config.content[:auto] links = filter_shows(links) links.first[1] else prompt_links(links) get_link_from_user(links) end end |
#get_link_from_user(links) ⇒ Object
163 164 165 166 167 168 169 170 171 172 |
# File 'lib/download_tv/downloader.rb', line 163 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 ? '' : links[i][1] end |
#prompt_links(links) ⇒ Object
174 175 176 177 178 179 |
# File 'lib/download_tv/downloader.rb', line 174 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
185 186 187 188 189 190 191 |
# File 'lib/download_tv/downloader.rb', line 185 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) ⇒ 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 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
71 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 71 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) ⇒ Object
122 123 124 125 126 127 128 129 |
# File 'lib/download_tv/downloader.rb', line 122 def shows_to_download(date) myepisodes = MyEpisodes.new(@config.content[:myepisodes_user], @config.content[:cookie]) myepisodes. shows = myepisodes.get_shows_since(date) shows = reject_ignored(shows) fix_names(shows) end |
#today_shows_to_download ⇒ Object
131 132 133 134 135 136 137 138 |
# File 'lib/download_tv/downloader.rb', line 131 def today_shows_to_download myepisodes = MyEpisodes.new(@config.content[:myepisodes_user], @config.content[:cookie]) myepisodes. shows = myepisodes.today_shows shows = reject_ignored(shows) fix_names(shows) end |