download_tv 2.2.1 → 2.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -2
- data/Rakefile +8 -8
- data/bin/tv +76 -76
- data/download_tv.gemspec +18 -17
- data/lib/download_tv.rb +13 -13
- data/lib/download_tv/configuration.rb +64 -64
- data/lib/download_tv/downloader.rb +184 -191
- data/lib/download_tv/grabbers/addic7ed.rb +48 -53
- data/lib/download_tv/grabbers/eztv.rb +19 -22
- data/lib/download_tv/grabbers/kat.rb +21 -25
- data/lib/download_tv/grabbers/torrentapi.rb +60 -66
- data/lib/download_tv/grabbers/tpb.rb +22 -26
- data/lib/download_tv/linkgrabber.rb +25 -31
- data/lib/download_tv/myepisodes.rb +78 -86
- data/lib/download_tv/subtitles.rb +14 -19
- data/lib/download_tv/torrent.rb +69 -83
- data/lib/download_tv/version.rb +1 -1
- data/test/config_test.rb +168 -170
- data/test/downloader_test.rb +166 -182
- data/test/grabbers_test.rb +38 -44
- data/test/test_helper.rb +15 -15
- data/test/torrent_test.rb +22 -25
- metadata +2 -2
@@ -1,67 +1,62 @@
|
|
1
1
|
module DownloadTV
|
2
|
+
##
|
3
|
+
# Addic7ed prototype (WIP)
|
4
|
+
class Addic7ed < LinkGrabber
|
5
|
+
def initialize
|
6
|
+
super('http://www.addic7ed.com/search.php?search=%s&Submit=Search')
|
7
|
+
end
|
2
8
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
9
|
+
def get_subs(show)
|
10
|
+
url = get_url(show)
|
11
|
+
download_file(url)
|
12
|
+
end
|
7
13
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_url(show)
|
14
|
-
# Change spaces for the separator
|
15
|
-
s = show.gsub(" ", @sep)
|
14
|
+
def get_url(show)
|
15
|
+
# Change spaces for the separator
|
16
|
+
s = show.gsub(' ', @sep)
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
# Format the url
|
19
|
+
search = Format(@url, s)
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
agent = Mechanize.new
|
22
|
+
res = agent.get(search)
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
# No redirection means no subtitle found
|
25
|
+
raise NoSubtitlesError if res.uri.to_s == search
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
##########
|
28
|
+
# DO OPENSUBTITLES FIRST (see subtitles.rb)
|
29
|
+
#####
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
# We now have an URL like:
|
32
|
+
# http://www.addic7ed.com/serie/Mr._Robot/2/3/eps2.1k3rnel-pan1c.ksd
|
32
33
|
|
33
|
-
|
34
|
-
|
34
|
+
# To find the real links:
|
35
|
+
# see comments at the end of file
|
36
|
+
end
|
35
37
|
|
38
|
+
def download_file(url)
|
39
|
+
# Url must be like 'http://www.addic7ed.com/updated/1/115337/0'
|
36
40
|
|
37
|
-
|
41
|
+
# ADDIC7ED PROVIDES RSS
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
agent = Mechanize.new
|
45
|
-
page = agent.get(url, [], @url)
|
46
|
-
puts page.save("Hi")
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
43
|
+
agent = Mechanize.new
|
44
|
+
page = agent.get(url, [], @url)
|
45
|
+
puts page.save('Hi')
|
46
|
+
end
|
47
|
+
end
|
51
48
|
end
|
52
|
-
|
53
|
-
|
54
49
|
# subtitles = {}
|
55
|
-
# html.css(
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
50
|
+
# html.css('.tabel95 .newsDate').each do |td|
|
51
|
+
# if downloads = td.text.match(/\s(\d*)\sDownloads/i)
|
52
|
+
# done = false
|
53
|
+
# td.parent.parent.xpath('./tr/td/a[@class='buttonDownload']/@href').each do |link|
|
54
|
+
# if md = link.value.match(/updated/i)
|
55
|
+
# subtitles[downloads[1].to_i] = link.value
|
56
|
+
# done = true
|
57
|
+
# elsif link.value.match(/original/i) && done == false
|
58
|
+
# subtitles[downloads[1].to_i] = link.value
|
59
|
+
# done = true
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
# end
|
@@ -1,30 +1,27 @@
|
|
1
1
|
module DownloadTV
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
##
|
3
|
+
# EZTV.ag grabber
|
4
|
+
class Eztv < LinkGrabber
|
5
|
+
def initialize
|
6
|
+
super('https://eztv.ag/search/%s')
|
7
|
+
end
|
6
8
|
|
7
|
-
|
9
|
+
def get_links(s)
|
10
|
+
# Format the url
|
11
|
+
search = format(@url, s)
|
8
12
|
|
9
|
-
|
10
|
-
search = @url % [s]
|
13
|
+
data = @agent.get(search).search('a.magnet')
|
11
14
|
|
12
|
-
|
15
|
+
# Torrent name in data[i].attribute 'title'
|
16
|
+
# 'Suits S04E01 HDTV x264-LOL Torrent: Magnet Link'
|
13
17
|
|
14
|
-
|
15
|
-
|
18
|
+
# EZTV shows 50 latest releases if it can't find the torrent
|
19
|
+
raise NoTorrentsError if data.size == 50
|
16
20
|
|
17
|
-
|
18
|
-
|
21
|
+
names = data.collect { |i| i.attribute('title').text.chomp(' Magnet Link') }
|
22
|
+
links = data.collect { |i| i.attribute('href').text }
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
names.zip(links)
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
|
24
|
+
names.zip(links)
|
25
|
+
end
|
26
|
+
end
|
30
27
|
end
|
@@ -1,34 +1,30 @@
|
|
1
1
|
module DownloadTV
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
##
|
3
|
+
# KATcr.co grabber
|
4
|
+
class KAT < LinkGrabber
|
5
|
+
def initialize
|
6
|
+
super('https://katcr.co/new/search-torrents.php?search="%s"&sort=seeders&order=desc')
|
7
|
+
end
|
6
8
|
|
7
|
-
|
9
|
+
def get_links(s)
|
10
|
+
# Format the url
|
11
|
+
search = format(@url, s)
|
8
12
|
|
9
|
-
|
10
|
-
search = @url % [s]
|
13
|
+
data = @agent.get(search).links.select { |i| i.href.include? 'torrents-details.php?' }
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
raise NoTorrentsError if data == []
|
15
|
+
raise NoTorrentsError if data == []
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
# Remove duplicates
|
18
|
+
data.keep_if { |i| i.text != '' }
|
18
19
|
|
19
|
-
|
20
|
-
|
20
|
+
names = data.collect(&:text)
|
21
|
+
links = []
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
23
|
+
data.each do |res|
|
24
|
+
links << res.click.search('a.kaGiantButton[title="Magnet link"]').attribute('href').text
|
25
|
+
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
|
27
|
+
names.zip(links)
|
28
|
+
end
|
29
|
+
end
|
34
30
|
end
|
@@ -1,68 +1,62 @@
|
|
1
1
|
module DownloadTV
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
63
|
-
|
2
|
+
##
|
3
|
+
# TorrentAPI.org grabber
|
4
|
+
class TorrentAPI < LinkGrabber
|
5
|
+
attr_accessor :token
|
6
|
+
attr_reader :wait
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super('https://torrentapi.org/pubapi_v2.php?mode=search&search_string=%s&token=%s&app_id=DownloadTV')
|
10
|
+
@wait = 2.1
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Connects to Torrentapi.org and requests a token.
|
15
|
+
# Returns said token.
|
16
|
+
def renew_token
|
17
|
+
page = @agent.get('https://torrentapi.org/pubapi_v2.php?get_token=get_token&app_id=DownloadTV').content
|
18
|
+
|
19
|
+
obj = JSON.parse(page)
|
20
|
+
|
21
|
+
@token = obj['token']
|
22
|
+
# Tokens automaticly expire in 15 minutes.
|
23
|
+
# The api has a 1req/2s limit.
|
24
|
+
# http://torrentapi.org/apidocs_v2.txt
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_links(s)
|
28
|
+
@token ||= renew_token
|
29
|
+
|
30
|
+
# Format the url
|
31
|
+
search = format(@url, s, @token)
|
32
|
+
|
33
|
+
page = @agent.get(search).content
|
34
|
+
obj = JSON.parse(page)
|
35
|
+
|
36
|
+
if obj['error_code'] == 4 # Token expired
|
37
|
+
renew_token
|
38
|
+
search = format(@url, s, @token)
|
39
|
+
page = @agent.get(search).content
|
40
|
+
obj = JSON.parse(page)
|
41
|
+
end
|
42
|
+
|
43
|
+
while obj['error_code'] == 5 # Violate 1req/2s limit
|
44
|
+
# puts 'Torrentapi request limit hit. Wait a few seconds...'
|
45
|
+
sleep(@wait)
|
46
|
+
page = @agent.get(search).content
|
47
|
+
obj = JSON.parse(page)
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
raise NoTorrentsError if obj['error']
|
52
|
+
|
53
|
+
names = obj['torrent_results'].collect { |i| i['filename'] }
|
54
|
+
links = obj['torrent_results'].collect { |i| i['download'] }
|
55
|
+
|
56
|
+
names.zip(links)
|
57
|
+
# Temporary solution for Cloudflare being obnoxious
|
58
|
+
rescue Mechanize::ResponseCodeError
|
59
|
+
raise NoTorrentsError
|
60
|
+
end
|
61
|
+
end
|
64
62
|
end
|
65
|
-
|
66
|
-
# Tokens automaticly expire in 15 minutes.
|
67
|
-
# The api has a 1req/2s limit.
|
68
|
-
# http://torrentapi.org/apidocs_v2.txt
|
@@ -1,34 +1,30 @@
|
|
1
1
|
module DownloadTV
|
2
|
+
##
|
3
|
+
# ThePirateBay grabber
|
4
|
+
class ThePirateBay < LinkGrabber
|
5
|
+
def initialize(tpb_proxy = 'https://pirateproxy.cc')
|
6
|
+
proxy = tpb_proxy.gsub(%r{/+$}, '') || 'https://thepiratebay.cr'
|
2
7
|
|
3
|
-
|
8
|
+
super("#{proxy}/search/%s/0/7/0")
|
9
|
+
end
|
4
10
|
|
5
|
-
|
6
|
-
|
11
|
+
def get_links(s)
|
12
|
+
# Format the url
|
13
|
+
search = format(@url, s)
|
7
14
|
|
8
|
-
|
9
|
-
|
10
|
-
|
15
|
+
data = @agent.get(search).search('#searchResult tr')
|
16
|
+
# Skip the header
|
17
|
+
data = data.drop 1
|
11
18
|
|
12
|
-
|
19
|
+
raise NoTorrentsError if data.empty?
|
13
20
|
|
14
|
-
|
15
|
-
|
21
|
+
# Second cell of each row contains links and name
|
22
|
+
results = data.map { |d| d.search('td')[1] }
|
16
23
|
|
17
|
-
|
18
|
-
|
19
|
-
data = data.drop 1
|
24
|
+
names = results.collect { |i| i.search('.detName').text.strip }
|
25
|
+
links = results.collect { |i| i.search('a')[1].attribute('href').text }
|
20
26
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
names = results.collect {|i| i.search(".detName").text.strip }
|
27
|
-
links = results.collect {|i| i.search("a")[1].attribute("href").text }
|
28
|
-
|
29
|
-
names.zip(links)
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
end
|
27
|
+
names.zip(links)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,32 +1,26 @@
|
|
1
1
|
module DownloadTV
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
class NoSubtitlesError < StandardError
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
2
|
+
##
|
3
|
+
# Interface for the grabbers
|
4
|
+
class LinkGrabber
|
5
|
+
attr_reader :url
|
6
|
+
|
7
|
+
def initialize(url)
|
8
|
+
@url = url
|
9
|
+
@agent = Mechanize.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_connection
|
13
|
+
agent = Mechanize.new
|
14
|
+
agent.read_timeout = 2
|
15
|
+
agent.get(@url)
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_links(_s)
|
19
|
+
raise NotImplementedError
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class NoTorrentsError < StandardError; end
|
24
|
+
|
25
|
+
class NoSubtitlesError < StandardError; end
|
26
|
+
end
|