lib/download_tv/downloader.rb in download_tv-2.1.0 vs lib/download_tv/downloader.rb in download_tv-2.1.1
- old
+ new
@@ -1,46 +1,51 @@
module DownloadTV
class Downloader
- attr_reader :offset, :auto, :subs, :grabber
- attr_accessor :config
+ attr_reader :offset, :config
- def initialize(offset, auto, subs, grabber, config={})
+ def initialize(offset=0, config={})
+ # Change to installation directory
+ Dir.chdir(__dir__)
+
@offset = offset.abs
- @auto = auto
- @subs = subs
- @grabber = grabber
- if config.empty?
- @config = Configuration.new.content # Load configuration
- else
- @config = config
- end
+ @config = Configuration.new(config).content # 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 download_single_show(show)
- t = Torrent.new(@grabber)
- download(t.get_link(show, @auto))
+ t = Torrent.new(@config[:grabber])
+ download(get_link(t, show))
end
+ ##
+ # 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
+ puts "Error: #{filename} not found"
+ exit 1
+ end
filename = File.realpath(filename)
- raise "File doesn't exist" if !File.exists? filename
- t = Torrent.new(@grabber)
- File.readlines(filename).each { |show| download(t.get_link(show, @auto)) }
-
+ t = Torrent.new(@config[:grabber])
+ File.readlines(filename).each { |show| download(get_link(t, show)) }
end
##
- # Gets the links.
+ # 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.
def run(dont_write_to_date_file)
- # Change to installation directory
- Dir.chdir(__dir__)
-
date = check_date
myepisodes = MyEpisodes.new(@config[:myepisodes_user], @config[:cookie])
# Log in using cookie by default
myepisodes.load_cookie
@@ -48,18 +53,18 @@
if shows.empty?
puts "Nothing to download"
else
- t = Torrent.new(@grabber)
+ t = Torrent.new(@config[:grabber])
to_download = fix_names(shows)
queue = Queue.new
# Adds a link (or empty string to the queue)
link_t = Thread.new do
- to_download.each { |show| queue << t.get_link(show, @auto) }
+ 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
@@ -68,11 +73,11 @@
download(magnet)
end
end
# Downloading the subtitles
- # subs_t = @subs and Thread.new do
+ # subs_t = @config[:subs] and Thread.new do
# to_download.each { |show| @s.get_subs(show) }
# end
link_t.join
download_t.join
@@ -82,14 +87,48 @@
end
File.write("date", Date.today) unless dont_write_to_date_file
rescue InvalidLoginError
- puts "Wrong username/password combination"
+ warn "Wrong username/password combination"
end
+ ##
+ # 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
+ def get_link(t, show)
+ links = t.get_links(show)
+ return "" if links.empty?
+
+ if @config[: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 check_date
content = File.read("date")
last = Date.parse(content)
if last - @offset != Date.today
@@ -103,21 +142,43 @@
File.write("date", Date.today-1)
retry
end
+ ##
+ # Given a list of shows and episodes:
+ #
+ # * Removes ignored shows
+ # * Removes apostrophes, colons and parens
def fix_names(shows)
# Ignored shows
s = shows.reject do |i|
# Remove season+episode
- @config[:ignored].include?(i.split(" ")[0..-2].join(" "))
+ @config[:ignored].include?(i.split(" ")[0..-2].join(" ").downcase)
end
- # Removes apostrophes, colons and parens
- s.map { |t| t.gsub(/ \(.+\)|[':]/, "") }
+ s.map { |i| i.gsub(/ \(.+\)|[':]/, "") }
end
+ ##
+ # Iteratively applies filters until they've all been applied or applying the next filter would result in no results
+ # These filters are defined at @filters
+ def filter_shows(links)
+ @filters.each do |f| # Apply each filter
+ new_links = links.reject { |name, _link| f.(name) }
+ # Stop if the filter removes every release
+ break if new_links.size == 0
+ links = new_links
+ end
+
+ links
+ end
+
+
+ ##
+ # Spawns a silent process to download a given magnet link
+ # Uses xdg-open (not portable)
def download(link)
exec = "xdg-open \"#{link}\""
Process.detach(Process.spawn(exec, [:out, :err]=>"/dev/null"))