download_tv 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/bin/tv +9 -9
- data/download_tv.gemspec +2 -3
- data/lib/download_tv/configuration.rb +16 -7
- data/lib/download_tv/downloader.rb +89 -28
- data/lib/download_tv/grabbers/addic7ed.rb +1 -1
- data/lib/download_tv/grabbers/kat.rb +1 -1
- data/lib/download_tv/linkgrabber.rb +1 -1
- data/lib/download_tv/myepisodes.rb +1 -1
- data/lib/download_tv/torrent.rb +10 -56
- data/lib/download_tv/version.rb +1 -1
- data/test/config_test.rb +52 -0
- data/test/downloader_test.rb +111 -33
- data/test/grabbers_test.rb +1 -8
- data/test/test_helper.rb +4 -0
- data/test/torrent_test.rb +0 -2
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 358854a4a50e549541b64dfa8e3279998a3c7a12
|
4
|
+
data.tar.gz: 643f9a41e0c91866228469a26371c35cfda7be82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5ae32db31ab5bd149b5c8d1165142b61a7a2df3b41d91c96e9cbbe31f8846333de4b9a5d01b6b34f7f162c68623d0382b7e94dd55e6e1a20a239fa486bbac4d
|
7
|
+
data.tar.gz: 8b6423716c1bc322aed18bb778160cc5bd1a618a31cfcd3a984f788959c76009f7db80d78c44bf548a25646149f493476a2f16bdbf5e23410356902812457989
|
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/guille/download_tv.svg?branch=master)](https://travis-ci.org/guille/download_tv)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/download_tv.svg)](https://badge.fury.io/rb/download_tv)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/guille/download_tv.svg)](https://codeclimate.com/github/guille/download_tv)
|
5
6
|
|
6
7
|
download_tv is a Ruby command line application that automatically downloads the new episodes from the shows you follow. It grabs the list of shows from your MyEpisodes account.
|
7
8
|
|
@@ -21,10 +22,13 @@ Specific options:
|
|
21
22
|
-f, --file PATH Download shows from a file
|
22
23
|
-d, --download SHOW Downloads given show
|
23
24
|
-c, --configure Configures defaults
|
24
|
-
|
25
|
-
|
25
|
+
--show-config Show current configuration values
|
26
|
+
--dry-run Don't write to the date file
|
26
27
|
-a, --[no-]auto Automatically find links
|
27
28
|
-s, --[no-]subtitles Download subtitles
|
29
|
+
-g, --grabber GRABBER Use given grabber as first option
|
30
|
+
--show-grabbers List available grabbers
|
31
|
+
-v Print version
|
28
32
|
-h, --help Show this message
|
29
33
|
|
30
34
|
```
|
data/bin/tv
CHANGED
@@ -5,10 +5,9 @@ require 'download_tv'
|
|
5
5
|
|
6
6
|
options = {}
|
7
7
|
options[:offset] = 0
|
8
|
-
options[:auto] = true
|
9
|
-
options[:subs] = true
|
10
8
|
options[:dry] = false
|
11
9
|
options[:cmd] = "run"
|
10
|
+
config = {}
|
12
11
|
|
13
12
|
opt_parser = OptionParser.new do |opts|
|
14
13
|
opts.banner = "Usage: tv [options]"
|
@@ -43,15 +42,15 @@ opt_parser = OptionParser.new do |opts|
|
|
43
42
|
end
|
44
43
|
|
45
44
|
opts.on("-a", "--[no-]auto", "Automatically find links") do |n|
|
46
|
-
|
45
|
+
config[:auto] = n
|
47
46
|
end
|
48
47
|
|
49
48
|
opts.on("-s", "--[no-]subtitles", "Download subtitles") do |n|
|
50
|
-
|
49
|
+
config[:subs] = n
|
51
50
|
end
|
52
51
|
|
53
52
|
opts.on("-g", "--grabber GRABBER", "Use given grabber as first option") do |g|
|
54
|
-
|
53
|
+
config[:grabber] = g
|
55
54
|
end
|
56
55
|
|
57
56
|
opts.on("--show-grabbers", "List available grabbers") do
|
@@ -73,19 +72,20 @@ end
|
|
73
72
|
opt_parser.parse!(ARGV)
|
74
73
|
|
75
74
|
begin
|
76
|
-
dl = DownloadTV::Downloader.new(options[:offset], options[:auto], options[:subs], options[:grabber])
|
77
75
|
case options[:cmd]
|
78
76
|
when "run"
|
77
|
+
dl = DownloadTV::Downloader.new(options[:offset], config)
|
79
78
|
dl.run(options[:dry])
|
80
79
|
when "dl"
|
80
|
+
dl = DownloadTV::Downloader.new(options[:offset], config)
|
81
81
|
dl.download_single_show(options[:arg])
|
82
82
|
when "file"
|
83
|
+
dl = DownloadTV::Downloader.new(options[:offset], config)
|
83
84
|
dl.download_from_file(options[:arg])
|
84
85
|
when "config"
|
85
|
-
DownloadTV::Configuration.new true
|
86
|
+
DownloadTV::Configuration.new(config, true)
|
86
87
|
when "showconfig"
|
87
|
-
DownloadTV::Configuration.new.print_config
|
88
|
-
|
88
|
+
DownloadTV::Configuration.new(config).print_config
|
89
89
|
end
|
90
90
|
rescue Interrupt
|
91
91
|
puts "Interrupt signal detected. Exiting..."
|
data/download_tv.gemspec
CHANGED
@@ -9,17 +9,16 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["guille"]
|
10
10
|
s.email = ["guillerg96@gmail.com"]
|
11
11
|
|
12
|
-
s.summary = %q{DownloadTV
|
12
|
+
s.summary = %q{DownloadTV is a tool that allows the user to find magnet links for tv show episodes. It accepts shows as arguments, from a file or it can integrate with your MyEpisodes account.}
|
13
13
|
s.homepage = "https://github.com/guille/download_tv"
|
14
14
|
|
15
15
|
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
16
|
f.match(%r{^(test)/})
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
s.test_files = `git ls-files -- test/*`.split($/)
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
# s.bindir = "exe"
|
23
22
|
s.executables = ["tv"]
|
24
23
|
s.default_executable = 'tv'
|
25
24
|
|
@@ -1,15 +1,18 @@
|
|
1
1
|
module DownloadTV
|
2
2
|
class Configuration
|
3
|
-
attr_reader :content
|
3
|
+
attr_reader :content, :config_path
|
4
4
|
|
5
|
-
def initialize(force_change=false)
|
5
|
+
def initialize(content={}, force_change=false)
|
6
6
|
Dir.chdir(__dir__)
|
7
|
+
|
8
|
+
@config_path = content[:path] || "config"
|
7
9
|
|
8
|
-
if File.
|
9
|
-
@content = File.open(
|
10
|
+
if File.exist? @config_path
|
11
|
+
@content = File.open(@config_path, "rb") { |f| Marshal.load(f) }
|
12
|
+
@content.merge!(content) unless content.empty?
|
10
13
|
change_configuration if force_change
|
11
14
|
else
|
12
|
-
@content =
|
15
|
+
@content = content
|
13
16
|
change_configuration
|
14
17
|
end
|
15
18
|
end
|
@@ -32,15 +35,21 @@ module DownloadTV
|
|
32
35
|
puts "Enter a comma-separated list of shows to ignore: "
|
33
36
|
end
|
34
37
|
|
35
|
-
@content[:ignored] = STDIN.gets.chomp.split(",").map(&:strip)
|
38
|
+
@content[:ignored] = STDIN.gets.chomp.split(",").map(&:strip).map(&:downcase)
|
36
39
|
STDOUT.flush
|
37
40
|
|
41
|
+
# When modifying existing config, keeps previous values
|
42
|
+
# When creating new one, sets defaults
|
43
|
+
@content[:auto] ||= true
|
44
|
+
@content[:subs] ||= true
|
45
|
+
@content[:grabber] ||= "TorrentAPI"
|
46
|
+
|
38
47
|
serialize()
|
39
48
|
end
|
40
49
|
|
41
50
|
|
42
51
|
def serialize
|
43
|
-
File.open(
|
52
|
+
File.open(@config_path, "wb") { |f| Marshal.dump(@content, f) }
|
44
53
|
end
|
45
54
|
|
46
55
|
|
@@ -2,43 +2,48 @@ module DownloadTV
|
|
2
2
|
|
3
3
|
class Downloader
|
4
4
|
|
5
|
-
attr_reader :offset, :
|
6
|
-
|
5
|
+
attr_reader :offset, :config
|
6
|
+
|
7
|
+
def initialize(offset=0, config={})
|
8
|
+
# Change to installation directory
|
9
|
+
Dir.chdir(__dir__)
|
7
10
|
|
8
|
-
def initialize(offset, auto, subs, grabber, config={})
|
9
11
|
@offset = offset.abs
|
10
|
-
@
|
11
|
-
|
12
|
-
@
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
@config = Configuration.new(config).content # Load configuration
|
13
|
+
|
14
|
+
@filters = [
|
15
|
+
->(n){ n.include?("2160p") },
|
16
|
+
->(n){ n.include?("1080p") },
|
17
|
+
->(n){ n.include?("720p") },
|
18
|
+
->(n){ n.include?("WEB") },
|
19
|
+
->(n){ !n.include?("PROPER") && !n.include?("REPACK") },
|
20
|
+
]
|
18
21
|
|
19
22
|
Thread.abort_on_exception = true
|
20
23
|
end
|
21
24
|
|
22
25
|
def download_single_show(show)
|
23
|
-
t = Torrent.new(@grabber)
|
24
|
-
download(
|
26
|
+
t = Torrent.new(@config[:grabber])
|
27
|
+
download(get_link(t, show))
|
25
28
|
end
|
26
29
|
|
27
30
|
|
31
|
+
##
|
32
|
+
# Given a file containing a list of episodes (one per line), it tries to find download links for each
|
28
33
|
def download_from_file(filename)
|
34
|
+
if !File.exist? filename
|
35
|
+
puts "Error: #{filename} not found"
|
36
|
+
exit 1
|
37
|
+
end
|
29
38
|
filename = File.realpath(filename)
|
30
|
-
|
31
|
-
|
32
|
-
File.readlines(filename).each { |show| download(t.get_link(show, @auto)) }
|
33
|
-
|
39
|
+
t = Torrent.new(@config[:grabber])
|
40
|
+
File.readlines(filename).each { |show| download(get_link(t, show)) }
|
34
41
|
end
|
35
42
|
|
36
43
|
##
|
37
|
-
#
|
44
|
+
# Finds download links for all new episodes aired since the last run of the program
|
45
|
+
# It connects to MyEpisodes in order to find which shows to track and which new episodes aired.
|
38
46
|
def run(dont_write_to_date_file)
|
39
|
-
# Change to installation directory
|
40
|
-
Dir.chdir(__dir__)
|
41
|
-
|
42
47
|
date = check_date
|
43
48
|
|
44
49
|
myepisodes = MyEpisodes.new(@config[:myepisodes_user], @config[:cookie])
|
@@ -50,14 +55,14 @@ module DownloadTV
|
|
50
55
|
puts "Nothing to download"
|
51
56
|
|
52
57
|
else
|
53
|
-
t = Torrent.new(@grabber)
|
58
|
+
t = Torrent.new(@config[:grabber])
|
54
59
|
to_download = fix_names(shows)
|
55
60
|
|
56
61
|
queue = Queue.new
|
57
62
|
|
58
63
|
# Adds a link (or empty string to the queue)
|
59
64
|
link_t = Thread.new do
|
60
|
-
to_download.each { |show| queue <<
|
65
|
+
to_download.each { |show| queue << get_link(t, show) }
|
61
66
|
end
|
62
67
|
|
63
68
|
# Downloads the links as they are added
|
@@ -70,7 +75,7 @@ module DownloadTV
|
|
70
75
|
end
|
71
76
|
|
72
77
|
# Downloading the subtitles
|
73
|
-
# subs_t = @subs and Thread.new do
|
78
|
+
# subs_t = @config[:subs] and Thread.new do
|
74
79
|
# to_download.each { |show| @s.get_subs(show) }
|
75
80
|
# end
|
76
81
|
|
@@ -84,7 +89,41 @@ module DownloadTV
|
|
84
89
|
File.write("date", Date.today) unless dont_write_to_date_file
|
85
90
|
|
86
91
|
rescue InvalidLoginError
|
87
|
-
|
92
|
+
warn "Wrong username/password combination"
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Uses a Torrent object to obtain links to the given tv show
|
97
|
+
# When :auto is true it will try to find the best match based on a set of filters
|
98
|
+
# When it's false it will prompt the user to select the preferred result
|
99
|
+
# Returns either a magnet link or an emptry string
|
100
|
+
def get_link(t, show)
|
101
|
+
links = t.get_links(show)
|
102
|
+
|
103
|
+
return "" if links.empty?
|
104
|
+
|
105
|
+
if @config[:auto]
|
106
|
+
links = filter_shows(links)
|
107
|
+
links.first[1]
|
108
|
+
|
109
|
+
else
|
110
|
+
puts "Collecting links for #{show}"
|
111
|
+
links.each_with_index { |data, i| puts "#{i}\t\t#{data[0]}" }
|
112
|
+
|
113
|
+
puts
|
114
|
+
print "Select the torrent you want to download [-1 to skip]: "
|
115
|
+
|
116
|
+
i = $stdin.gets.chomp.to_i
|
117
|
+
|
118
|
+
while i >= links.size || i < -1
|
119
|
+
puts "Index out of bounds. Try again [-1 to skip]: "
|
120
|
+
i = $stdin.gets.chomp.to_i
|
121
|
+
end
|
122
|
+
|
123
|
+
# Use -1 to skip the download
|
124
|
+
i == -1 ? "" : links[i][1]
|
125
|
+
end
|
126
|
+
|
88
127
|
end
|
89
128
|
|
90
129
|
|
@@ -105,18 +144,40 @@ module DownloadTV
|
|
105
144
|
end
|
106
145
|
|
107
146
|
|
147
|
+
##
|
148
|
+
# Given a list of shows and episodes:
|
149
|
+
#
|
150
|
+
# * Removes ignored shows
|
151
|
+
# * Removes apostrophes, colons and parens
|
108
152
|
def fix_names(shows)
|
109
153
|
# Ignored shows
|
110
154
|
s = shows.reject do |i|
|
111
155
|
# Remove season+episode
|
112
|
-
@config[:ignored].include?(i.split(" ")[0..-2].join(" "))
|
156
|
+
@config[:ignored].include?(i.split(" ")[0..-2].join(" ").downcase)
|
113
157
|
end
|
114
158
|
|
115
|
-
|
116
|
-
s.map { |t| t.gsub(/ \(.+\)|[':]/, "") }
|
159
|
+
s.map { |i| i.gsub(/ \(.+\)|[':]/, "") }
|
117
160
|
end
|
118
161
|
|
162
|
+
##
|
163
|
+
# Iteratively applies filters until they've all been applied or applying the next filter would result in no results
|
164
|
+
# These filters are defined at @filters
|
165
|
+
def filter_shows(links)
|
166
|
+
@filters.each do |f| # Apply each filter
|
167
|
+
new_links = links.reject { |name, _link| f.(name) }
|
168
|
+
# Stop if the filter removes every release
|
169
|
+
break if new_links.size == 0
|
170
|
+
|
171
|
+
links = new_links
|
172
|
+
end
|
119
173
|
|
174
|
+
links
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
##
|
179
|
+
# Spawns a silent process to download a given magnet link
|
180
|
+
# Uses xdg-open (not portable)
|
120
181
|
def download(link)
|
121
182
|
exec = "xdg-open \"#{link}\""
|
122
183
|
|
data/lib/download_tv/torrent.rb
CHANGED
@@ -17,14 +17,6 @@ module DownloadTV
|
|
17
17
|
# Silently ignores bad names
|
18
18
|
@g_names.rotate! @g_names.find_index(default_grabber).to_i
|
19
19
|
|
20
|
-
@filters = [
|
21
|
-
->(n){n.include?("2160")},
|
22
|
-
->(n){n.include?("1080")},
|
23
|
-
->(n){n.include?("720")},
|
24
|
-
->(n){n.include?("WEB")},
|
25
|
-
->(n){!n.include?("PROPER") || !n.include?("REPACK")},
|
26
|
-
]
|
27
|
-
|
28
20
|
change_grabbers
|
29
21
|
|
30
22
|
end
|
@@ -46,7 +38,7 @@ module DownloadTV
|
|
46
38
|
|
47
39
|
rescue Mechanize::ResponseCodeError, Net::HTTP::Persistent::Error
|
48
40
|
|
49
|
-
|
41
|
+
warn "Problem accessing #{newt.class.name}"
|
50
42
|
# We won't be using this grabber
|
51
43
|
@n_grabbers = @n_grabbers-1
|
52
44
|
@tries = @tries - 1
|
@@ -54,48 +46,19 @@ module DownloadTV
|
|
54
46
|
change_grabbers
|
55
47
|
|
56
48
|
rescue SocketError, Errno::ECONNRESET, Net::OpenTimeout
|
57
|
-
|
58
|
-
exit
|
49
|
+
warn "Connection error."
|
50
|
+
exit 1
|
59
51
|
|
60
52
|
end
|
61
53
|
|
62
54
|
|
63
|
-
def
|
55
|
+
def get_links(show)
|
64
56
|
links = @g_instances.first.get_links(show)
|
65
57
|
|
66
|
-
|
67
|
-
|
68
|
-
puts "#{i}\t\t#{data[0]}"
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
puts
|
73
|
-
print "Select the torrent you want to download [-1 to skip]: "
|
74
|
-
|
75
|
-
i = $stdin.gets.chomp.to_i
|
76
|
-
|
77
|
-
while i >= links.size || i < -1
|
78
|
-
puts "Index out of bounds. Try again: "
|
79
|
-
i = $stdin.gets.chomp.to_i
|
80
|
-
end
|
81
|
-
|
82
|
-
# Reset the counter
|
83
|
-
@tries = @n_grabbers - 1
|
84
|
-
|
85
|
-
# Use -1 to skip the download
|
86
|
-
i == -1 ? "" : links[i][1]
|
58
|
+
# Reset the counter
|
59
|
+
@tries = @n_grabbers - 1
|
87
60
|
|
88
|
-
|
89
|
-
|
90
|
-
links = filter_shows(links)
|
91
|
-
|
92
|
-
# Reset the counter
|
93
|
-
@tries = @n_grabbers - 1
|
94
|
-
|
95
|
-
# Get the first result left
|
96
|
-
links[0][1]
|
97
|
-
|
98
|
-
end
|
61
|
+
links
|
99
62
|
|
100
63
|
rescue NoTorrentsError
|
101
64
|
puts "No torrents found for #{show} using #{@g_instances.first.class.name}"
|
@@ -108,23 +71,14 @@ module DownloadTV
|
|
108
71
|
|
109
72
|
else # Reset the counter
|
110
73
|
@tries = @n_grabbers - 1
|
111
|
-
#
|
112
|
-
return
|
74
|
+
# Handle show not found here!!
|
75
|
+
return []
|
113
76
|
|
114
77
|
end
|
115
78
|
|
116
79
|
end
|
117
80
|
|
118
|
-
|
119
|
-
@filters.each do |f| # Apply each filter
|
120
|
-
new_links = links.reject {|name, link| f.(name)}
|
121
|
-
# Stop if the filter removes every release
|
122
|
-
break if new_links.size == 0
|
123
|
-
|
124
|
-
links = new_links
|
125
|
-
end
|
126
|
-
links
|
127
|
-
end
|
81
|
+
|
128
82
|
end
|
129
83
|
|
130
84
|
end
|
data/lib/download_tv/version.rb
CHANGED
data/test/config_test.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe DownloadTV::Configuration do
|
4
|
+
config_path = File.realdirpath("#{__dir__}/test_config")
|
5
|
+
|
6
|
+
before do
|
7
|
+
Dir.chdir(__dir__)
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
File.delete(config_path) if File.exist?(config_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "when the file already exists" do
|
15
|
+
it "will load the existing configuration (blank)" do
|
16
|
+
create_dummy_config(config_path)
|
17
|
+
|
18
|
+
c = DownloadTV::Configuration.new(path: config_path)
|
19
|
+
c.content.must_equal ({path: config_path})
|
20
|
+
end
|
21
|
+
|
22
|
+
it "will load the existing configuration (existing)" do
|
23
|
+
create_dummy_config(config_path, auto: false, myepisodes_user: "dummy")
|
24
|
+
|
25
|
+
c = DownloadTV::Configuration.new(path: config_path)
|
26
|
+
c.content.must_equal ({path: config_path, auto: false, myepisodes_user: "dummy"})
|
27
|
+
end
|
28
|
+
|
29
|
+
it "will get overwritten by the parameters given" do
|
30
|
+
create_dummy_config(config_path, myepisodes_user: "dummy")
|
31
|
+
|
32
|
+
c = DownloadTV::Configuration.new(path: config_path, myepisodes_user: "fake")
|
33
|
+
c.content.must_equal ({path: config_path, myepisodes_user: "fake"})
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# describe "when the file doesn't exist" do
|
38
|
+
# it "will create a new one" do
|
39
|
+
# # Send stuff to stdin
|
40
|
+
# flunk
|
41
|
+
# DownloadTV::Configuration.new(path: config_path)
|
42
|
+
# File.exist?(config_path).must_equal true
|
43
|
+
# end
|
44
|
+
|
45
|
+
# it "will trigger a configuration change when asked to" do
|
46
|
+
# DownloadTV::Configuration.new(path: config_path, true)
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
|
50
|
+
# test [:ignored] gets turned to lowercase
|
51
|
+
|
52
|
+
end
|
data/test/downloader_test.rb
CHANGED
@@ -1,75 +1,67 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
describe DownloadTV::Downloader do
|
4
|
+
config_path = File.realdirpath("#{__dir__}/test_config")
|
5
|
+
|
4
6
|
before do
|
5
|
-
Dir.chdir(
|
7
|
+
Dir.chdir(__dir__)
|
6
8
|
File.delete("date") if File.exist?("date")
|
9
|
+
create_dummy_config(config_path) unless File.exist?(config_path)
|
7
10
|
end
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
->{ DownloadTV::Downloader.new(0, true) }.must_raise ArgumentError
|
13
|
-
->{ DownloadTV::Downloader.new(0, true, true) }.must_raise ArgumentError
|
14
|
-
end
|
15
|
-
|
16
|
-
it "can receive an optional configuration hash" do
|
17
|
-
DownloadTV::Downloader.new(0, true, true, nil, {:hi => 1}).config.must_equal ({:hi => 1})
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should receive an integer for the offset" do
|
21
|
-
->{ DownloadTV::Downloader.new("foo", true, true, nil, {1=>1}) }.must_raise NoMethodError
|
22
|
-
end
|
12
|
+
after do
|
13
|
+
File.delete(config_path) if File.exist?(config_path)
|
14
|
+
end
|
23
15
|
|
16
|
+
describe "when creating the object" do
|
24
17
|
it "should store the first argument as @offset" do
|
25
|
-
DownloadTV::Downloader.new(3,
|
26
|
-
|
27
|
-
|
28
|
-
it "should store the second argument as @auto" do
|
29
|
-
DownloadTV::Downloader.new(3, true, true, nil, {1=>1}).auto.must_equal true
|
30
|
-
DownloadTV::Downloader.new(3, false, true, nil, {1=>1}).auto.must_equal false
|
18
|
+
DownloadTV::Downloader.new(3, path: config_path).offset.must_equal 3
|
19
|
+
DownloadTV::Downloader.new(-3, path: config_path).offset.must_equal 3
|
31
20
|
end
|
32
21
|
|
33
|
-
it "should
|
34
|
-
DownloadTV::Downloader.new(
|
35
|
-
DownloadTV::Downloader.new(3, true, false, nil, {1=>1}).subs.must_equal false
|
22
|
+
it "should receive an integer for the offset" do
|
23
|
+
->{ DownloadTV::Downloader.new("foo") }.must_raise NoMethodError
|
36
24
|
end
|
37
25
|
|
38
|
-
it "
|
39
|
-
DownloadTV::Downloader.new(
|
40
|
-
|
26
|
+
it "can receive an optional configuration hash" do
|
27
|
+
dl = DownloadTV::Downloader.new(0, auto: true, grabber: "KAT", path: config_path)
|
28
|
+
dl.config[:auto].must_equal true
|
29
|
+
dl.config[:grabber].must_equal "KAT"
|
41
30
|
end
|
42
31
|
|
43
32
|
end
|
44
33
|
|
45
|
-
describe "the fix_names
|
46
|
-
config = {:ignored => ["Ignored"]}
|
47
|
-
dl = DownloadTV::Downloader.new(0, true, true, nil, config)
|
48
|
-
|
34
|
+
describe "the fix_names method" do
|
49
35
|
it "should remove apostrophes, colons and parens" do
|
50
36
|
shows = ["Mr. Foo S01E02", "Bar (UK) S00E22", "Let's S05E03", "Baz: The Story S05E22"]
|
51
37
|
result = ["Mr. Foo S01E02", "Bar S00E22", "Lets S05E03", "Baz The Story S05E22"]
|
38
|
+
|
39
|
+
dl = DownloadTV::Downloader.new(0, ignored: [], path: config_path)
|
52
40
|
dl.fix_names(shows).must_equal result
|
53
41
|
end
|
54
42
|
|
55
43
|
it "should remove ignored shows" do
|
56
|
-
|
57
44
|
shows = ["Mr. Foo S01E02", "Bar (UK) S00E22", "Ignored S20E22", "Let's S05E03"]
|
58
45
|
result = ["Mr. Foo S01E02", "Bar S00E22", "Lets S05E03"]
|
46
|
+
|
47
|
+
dl = DownloadTV::Downloader.new(0, ignored: ["Ignored"], path: config_path)
|
59
48
|
dl.fix_names(shows).must_equal result
|
60
49
|
end
|
61
50
|
end
|
62
51
|
|
63
52
|
|
64
53
|
describe "the date file" do
|
65
|
-
dl = DownloadTV::Downloader.new(0, true, true, nil, {1=>1})
|
66
54
|
|
67
55
|
it "should be created if it doesn't exist" do
|
56
|
+
dl = DownloadTV::Downloader.new(0, path: config_path)
|
57
|
+
Dir.chdir(__dir__) # Use date file in test directory
|
68
58
|
dl.check_date
|
69
59
|
File.exist?("date").must_equal true
|
70
60
|
end
|
71
61
|
|
72
62
|
it "contains a date after running the method" do
|
63
|
+
dl = DownloadTV::Downloader.new(0, path: config_path)
|
64
|
+
Dir.chdir(__dir__)
|
73
65
|
date = dl.check_date
|
74
66
|
date.must_equal (Date.today-1)
|
75
67
|
Date.parse(File.read("date")).must_equal Date.today-1
|
@@ -78,13 +70,99 @@ describe DownloadTV::Downloader do
|
|
78
70
|
it "exits the script when up to date" do
|
79
71
|
File.write("date", Date.today)
|
80
72
|
begin
|
73
|
+
dl = DownloadTV::Downloader.new(0, path: config_path)
|
74
|
+
Dir.chdir(__dir__)
|
81
75
|
dl.check_date
|
82
76
|
flunk
|
83
77
|
rescue SystemExit
|
84
78
|
|
85
79
|
end
|
86
80
|
end
|
81
|
+
|
82
|
+
it "uses the offset to adjust the date" do
|
83
|
+
File.write("date", Date.today)
|
84
|
+
|
85
|
+
# Would exit with offset 0
|
86
|
+
dl = DownloadTV::Downloader.new(1, path: config_path)
|
87
|
+
|
88
|
+
Dir.chdir(__dir__)
|
89
|
+
date = dl.check_date
|
90
|
+
|
91
|
+
date.must_equal (Date.today-1)
|
92
|
+
Date.parse(File.read("date")).must_equal Date.today
|
93
|
+
end
|
87
94
|
|
88
95
|
end
|
89
96
|
|
97
|
+
describe "the filter_shows method" do
|
98
|
+
it "removes names with 2160p in them" do
|
99
|
+
dl = DownloadTV::Downloader.new(0, path: config_path)
|
100
|
+
links = [["Link 1", ""], ["Link 2 2160p", ""], ["Link 3", ""]]
|
101
|
+
res = [["Link 1", ""], ["Link 3", ""]]
|
102
|
+
dl.filter_shows(links).must_equal res
|
103
|
+
end
|
104
|
+
|
105
|
+
it "removes names with 1080p in them" do
|
106
|
+
dl = DownloadTV::Downloader.new(0, path: config_path)
|
107
|
+
links = [["Link.1080p", ""], ["Link 2 2160p", ""], ["Link 3", ""]]
|
108
|
+
res = [["Link 3", ""]]
|
109
|
+
dl.filter_shows(links).must_equal res
|
110
|
+
end
|
111
|
+
|
112
|
+
it "removes names with 720p in them" do
|
113
|
+
dl = DownloadTV::Downloader.new(0, path: config_path)
|
114
|
+
links = [["Link 1", ""], ["Link 2 720p", ""], ["Link.720p.rip", ""]]
|
115
|
+
res = [["Link 1", ""]]
|
116
|
+
dl.filter_shows(links).must_equal res
|
117
|
+
end
|
118
|
+
|
119
|
+
it "removes names with WEB in them" do
|
120
|
+
dl = DownloadTV::Downloader.new(0, path: config_path)
|
121
|
+
links = [["Link 1 WEBRIP", ""], ["Link 2 rip", ""], ["Link.720p.rip", ""]]
|
122
|
+
res = [["Link 2 rip", ""]]
|
123
|
+
dl.filter_shows(links).must_equal res
|
124
|
+
end
|
125
|
+
|
126
|
+
it "removes names without PROPER or REPACK in them" do
|
127
|
+
dl = DownloadTV::Downloader.new(0, path: config_path)
|
128
|
+
links = [["Link 1", ""], ["Link 2 2160p", ""], ["Link 3", ""], ["Link 4 PROPER", ""], ["Link REPACK 5", ""]]
|
129
|
+
res = [["Link 4 PROPER", ""], ["Link REPACK 5", ""]]
|
130
|
+
dl.filter_shows(links).must_equal res
|
131
|
+
end
|
132
|
+
|
133
|
+
it "doesn't apply a filter if it would reject every option" do
|
134
|
+
dl = DownloadTV::Downloader.new(0, path: config_path)
|
135
|
+
links = [["Link 1 720p", ""], ["Link 2 2160p", ""], ["Link 720p 3", ""]]
|
136
|
+
res = [["Link 1 720p", ""], ["Link 720p 3", ""]]
|
137
|
+
dl.filter_shows(links).must_equal res
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "the get_link method" do
|
142
|
+
it "returns an empty string when it can't find links" do
|
143
|
+
t = Minitest::Mock.new
|
144
|
+
show = "Example Show S01E01"
|
145
|
+
|
146
|
+
t.expect(:get_links, [], [show])
|
147
|
+
dl = DownloadTV::Downloader.new(0, auto: true, path: config_path)
|
148
|
+
dl.get_link(t, show).must_equal ""
|
149
|
+
t.expect(:get_links, [], [show])
|
150
|
+
dl = DownloadTV::Downloader.new(0, auto: false, path: config_path)
|
151
|
+
dl.get_link(t, show).must_equal ""
|
152
|
+
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
it "returns the first link when auto is set to true" do
|
157
|
+
t = Minitest::Mock.new
|
158
|
+
show = "Example Show S01E01"
|
159
|
+
|
160
|
+
t.expect(:get_links, [["Name 1", "Link 1"], ["Name 2", "Link 2"]], [show])
|
161
|
+
dl = DownloadTV::Downloader.new(0, auto: true, path: config_path)
|
162
|
+
dl.get_link(t, show).must_equal "Link 1"
|
163
|
+
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
90
168
|
end
|
data/test/grabbers_test.rb
CHANGED
@@ -7,28 +7,20 @@ describe DownloadTV::LinkGrabber do
|
|
7
7
|
|
8
8
|
instances.each do |grabber|
|
9
9
|
describe grabber do
|
10
|
-
# grabber = g#(Object.const_get "DownloadTV::#{g}").new
|
11
|
-
|
12
10
|
it "will have a url attribute on creation" do
|
13
|
-
# instance_eval("#{g}.new")
|
14
|
-
|
15
11
|
grabber.url.wont_be_nil
|
16
12
|
end
|
17
13
|
|
18
14
|
it "should get a 200 code response" do
|
19
|
-
# grabber = (Object.const_get g).new
|
20
15
|
grabber.test_connection.code.must_equal "200"
|
21
16
|
end
|
22
17
|
|
23
18
|
it "will raise NoTorrentsError when torrent can't be found" do
|
24
|
-
# grabber = (Object.const_get g).new
|
25
19
|
notfound = ->{ grabber.get_links("Totally Fake Show askjdgsaudas") }
|
26
20
|
notfound.must_raise DownloadTV::NoTorrentsError
|
27
|
-
|
28
21
|
end
|
29
22
|
|
30
23
|
it "will return an array with names and links of results when a torrent can be found" do
|
31
|
-
# grabber = (Object.const_get g).new
|
32
24
|
result = grabber.get_links("Game Of Thrones S04E01")
|
33
25
|
result.must_be_instance_of Array
|
34
26
|
result.wont_be :empty?
|
@@ -37,6 +29,7 @@ describe DownloadTV::LinkGrabber do
|
|
37
29
|
r[0].must_be_instance_of String
|
38
30
|
r[0].upcase.must_include "THRONES"
|
39
31
|
r[1].must_be_instance_of String
|
32
|
+
r[1].must_include "magnet:"
|
40
33
|
end
|
41
34
|
|
42
35
|
end
|
data/test/test_helper.rb
CHANGED
data/test/torrent_test.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: download_tv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- guille
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-07-
|
11
|
+
date: 2017-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -136,6 +136,7 @@ files:
|
|
136
136
|
- lib/download_tv/subtitles.rb
|
137
137
|
- lib/download_tv/torrent.rb
|
138
138
|
- lib/download_tv/version.rb
|
139
|
+
- test/config_test.rb
|
139
140
|
- test/downloader_test.rb
|
140
141
|
- test/grabbers_test.rb
|
141
142
|
- test/test_helper.rb
|
@@ -162,9 +163,11 @@ rubyforge_project:
|
|
162
163
|
rubygems_version: 2.6.12
|
163
164
|
signing_key:
|
164
165
|
specification_version: 4
|
165
|
-
summary: DownloadTV
|
166
|
-
|
166
|
+
summary: DownloadTV is a tool that allows the user to find magnet links for tv show
|
167
|
+
episodes. It accepts shows as arguments, from a file or it can integrate with your
|
168
|
+
MyEpisodes account.
|
167
169
|
test_files:
|
170
|
+
- test/config_test.rb
|
168
171
|
- test/downloader_test.rb
|
169
172
|
- test/grabbers_test.rb
|
170
173
|
- test/test_helper.rb
|