addic7ed 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/addic7ed +6 -2
- data/lib/addic7ed/episode.rb +9 -9
- data/lib/addic7ed/parser.rb +7 -0
- data/lib/addic7ed/subtitle.rb +6 -2
- data/lib/addic7ed/version.rb +1 -1
- data/lib/addic7ed/video_file.rb +14 -12
- data/spec/lib/addic7ed/episode_spec.rb +8 -0
- data/spec/lib/addic7ed/subtitle_spec.rb +27 -7
- data/spec/lib/addic7ed/video_file_spec.rb +23 -12
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31b2fe4ded0361b2b026b14726c480224ab5244a
|
4
|
+
data.tar.gz: aa80369c98fa0c5d69bf69ce6aa9ea6946f76a49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1b988d4a1177cfda71df10c16a0948aab0119f59a68a1033cc4abe1bdb8ad30d21822593a57488546e507e49a07b6fc5f91b116f27424d2a3be70eade8ba8b9
|
7
|
+
data.tar.gz: 17f09e0086fa85b5a7fb7973ecc0d3df0d2af9dc1a11fd1b706d55e51579a84ac08ee6e7dc8c218ed82be02cc1c49cb32698b74dfd128c87997632f1990ed835
|
data/bin/addic7ed
CHANGED
@@ -21,6 +21,10 @@ OptionParser.new do |opts|
|
|
21
21
|
options[:language] = l
|
22
22
|
end
|
23
23
|
|
24
|
+
opts.on("--no-hi", "Only download subtitles without Hearing Impaired lines") do |hi|
|
25
|
+
options[:no_hi] = !hi
|
26
|
+
end
|
27
|
+
|
24
28
|
opts.on("-a", "--all-subtitles", "Display all available subtitles") do |a|
|
25
29
|
options[:all] = a
|
26
30
|
end
|
@@ -96,13 +100,13 @@ options[:filenames].each do |filename|
|
|
96
100
|
end
|
97
101
|
next if options[:all]
|
98
102
|
end
|
99
|
-
ep.best_subtitle(options[:language])
|
103
|
+
ep.best_subtitle(options[:language], options[:no_hi])
|
100
104
|
if options[:verbose]
|
101
105
|
puts ' Best subtitle:'
|
102
106
|
puts " #{ep.best_subtitle(options[:language])}"
|
103
107
|
end
|
104
108
|
unless options[:nodownload]
|
105
|
-
ep.download_best_subtitle!(options[:language])
|
109
|
+
ep.download_best_subtitle!(options[:language], options[:no_hi])
|
106
110
|
puts "New subtitle downloaded for #{filename}.\nEnjoy your show :-)".gsub(/^/, options[:verbose] ? ' ' : '') unless options[:quiet]
|
107
111
|
end
|
108
112
|
rescue Addic7ed::InvalidFilename
|
data/lib/addic7ed/episode.rb
CHANGED
@@ -23,18 +23,18 @@ module Addic7ed
|
|
23
23
|
return @subtitles[lang]
|
24
24
|
end
|
25
25
|
|
26
|
-
def best_subtitle(lang = 'fr')
|
26
|
+
def best_subtitle(lang = 'fr', no_hi = false)
|
27
27
|
check_language_availability(lang)
|
28
|
-
find_best_subtitle(lang) unless @best_subtitle and @best_subtitle[lang]
|
28
|
+
find_best_subtitle(lang, no_hi) unless @best_subtitle and @best_subtitle[lang]
|
29
29
|
return @best_subtitle[lang]
|
30
30
|
end
|
31
31
|
|
32
|
-
def download_best_subtitle!(lang, http_redirect_limit = 8)
|
32
|
+
def download_best_subtitle!(lang, no_hi = false, http_redirect_limit = 8)
|
33
33
|
raise HTTPError.new('Too many HTTP redirects') unless http_redirect_limit > 0
|
34
|
-
uri = URI(best_subtitle(lang).url)
|
34
|
+
uri = URI(best_subtitle(lang, no_hi).url)
|
35
35
|
response = get_http_response(uri, url(lang))
|
36
36
|
if response.kind_of?(Net::HTTPRedirection)
|
37
|
-
follow_redirection(lang, response['location'], http_redirect_limit)
|
37
|
+
follow_redirection(lang, no_hi, response['location'], http_redirect_limit)
|
38
38
|
else
|
39
39
|
save_subtitle(response.body, lang)
|
40
40
|
end
|
@@ -48,10 +48,10 @@ module Addic7ed
|
|
48
48
|
@subtitles[lang] = parser.extract_subtitles
|
49
49
|
end
|
50
50
|
|
51
|
-
def find_best_subtitle(lang)
|
51
|
+
def find_best_subtitle(lang, no_hi = false)
|
52
52
|
@best_subtitle ||= {}
|
53
53
|
subtitles(lang).each do |sub|
|
54
|
-
@best_subtitle[lang] = sub if sub.works_for?
|
54
|
+
@best_subtitle[lang] = sub if sub.works_for?(video_file.group, no_hi) and sub.can_replace? @best_subtitle[lang]
|
55
55
|
end
|
56
56
|
raise NoSubtitleFound unless @best_subtitle[lang]
|
57
57
|
end
|
@@ -77,11 +77,11 @@ module Addic7ed
|
|
77
77
|
raise DownloadError
|
78
78
|
end
|
79
79
|
|
80
|
-
def follow_redirection(lang, new_uri, http_redirect_limit)
|
80
|
+
def follow_redirection(lang, no_hi, new_uri, http_redirect_limit)
|
81
81
|
# Addic7ed is serving redirection URL not-encoded, but Ruby does not support it (see http://bugs.ruby-lang.org/issues/7396)
|
82
82
|
best_subtitle(lang).url = URI.escape(new_uri)
|
83
83
|
raise DownloadLimitReached if /^\/downloadexceeded.php/.match best_subtitle(lang).url
|
84
|
-
download_best_subtitle!(lang, http_redirect_limit - 1)
|
84
|
+
download_best_subtitle!(lang, no_hi, http_redirect_limit - 1)
|
85
85
|
end
|
86
86
|
|
87
87
|
def save_subtitle(content, lang)
|
data/lib/addic7ed/parser.rb
CHANGED
@@ -44,6 +44,7 @@ module Addic7ed
|
|
44
44
|
status: extract_status(sub_node),
|
45
45
|
url: extract_url(sub_node),
|
46
46
|
source: extract_source(sub_node),
|
47
|
+
hi: extract_hi(sub_node),
|
47
48
|
downloads: extract_downloads(sub_node),
|
48
49
|
comment: extract_comment(sub_node)
|
49
50
|
)
|
@@ -78,6 +79,12 @@ module Addic7ed
|
|
78
79
|
source_node['href'] if source_node
|
79
80
|
end
|
80
81
|
|
82
|
+
def extract_hi(sub_node)
|
83
|
+
hi_node = sub_node.css('tr:nth-child(4) td.newsDate').children[1]
|
84
|
+
raise Addic7ed::ParsingError unless hi_node
|
85
|
+
!hi_node.attribute("title").nil?
|
86
|
+
end
|
87
|
+
|
81
88
|
def extract_downloads(sub_node)
|
82
89
|
downloads_node = sub_node.css('tr:nth-child(4) td.newsDate').first
|
83
90
|
raise Addic7ed::ParsingError unless downloads_node
|
data/lib/addic7ed/subtitle.rb
CHANGED
@@ -10,6 +10,7 @@ module Addic7ed
|
|
10
10
|
@status = options[:status]
|
11
11
|
@url = options[:url]
|
12
12
|
@via = options[:via]
|
13
|
+
@hi = options[:hi]
|
13
14
|
@downloads = options[:downloads].to_i || 0
|
14
15
|
@comment = normalize_comment(options[:comment])
|
15
16
|
end
|
@@ -18,8 +19,9 @@ module Addic7ed
|
|
18
19
|
"#{url}\t->\t#{version} (#{language}, #{status}) [#{downloads} downloads]#{" (via #{via})" if via}"
|
19
20
|
end
|
20
21
|
|
21
|
-
def works_for?(version = '')
|
22
|
-
|
22
|
+
def works_for?(version = '', no_hi = false)
|
23
|
+
hi_works = !@hi || !no_hi
|
24
|
+
is_completed? and is_compatible_with? version and hi_works
|
23
25
|
end
|
24
26
|
|
25
27
|
def can_replace?(other_subtitle)
|
@@ -60,6 +62,8 @@ module Addic7ed
|
|
60
62
|
end
|
61
63
|
|
62
64
|
def commented_as_compatible_with?(other_version)
|
65
|
+
return false if /(won't|doesn't|not) +work/i.match comment
|
66
|
+
return false if /resync +(from|of)/i.match comment
|
63
67
|
res = comment.include? other_version.downcase
|
64
68
|
res ||= comment.include? COMPATIBILITY_720P[other_version].downcase if COMPATIBILITY_720P[other_version]
|
65
69
|
res ||= comment.include? COMPATIBILITY_720P[version].downcase if COMPATIBILITY_720P[version]
|
data/lib/addic7ed/version.rb
CHANGED
data/lib/addic7ed/video_file.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
module Addic7ed
|
2
2
|
class VideoFile
|
3
3
|
|
4
|
-
TVSHOW_REGEX = /\A(?<showname>.*\w)[\[\. ]+S?(?<season>\d{1,2})[-\. ]?[EX]?(?<episode>\d{2})([-\. ]?[EX]?\d{2})*[\]\. ]+(?<tags>.*)-(?<group>\w*)(\.\w{3})?\z/i
|
4
|
+
TVSHOW_REGEX = /\A(?<showname>.*\w)[\[\. ]+S?(?<season>\d{1,2})[-\. ]?[EX]?(?<episode>\d{2})([-\. ]?[EX]?\d{2})*[\]\. ]+(?<tags>.*)-(?<group>\w*)\[?(?<distribution>\w*)\]?(\.\w{3})?\z/i
|
5
5
|
|
6
|
-
attr_reader :filename, :showname, :season, :episode, :tags, :group
|
6
|
+
attr_reader :filename, :showname, :season, :episode, :tags, :group, :distribution
|
7
7
|
|
8
8
|
def initialize(filename)
|
9
9
|
@filename = filename
|
10
10
|
if match = TVSHOW_REGEX.match(basename)
|
11
|
-
@showname
|
12
|
-
@season
|
13
|
-
@episode
|
14
|
-
@tags
|
15
|
-
@group
|
11
|
+
@showname = match[:showname].gsub('.', ' ')
|
12
|
+
@season = match[:season].to_i
|
13
|
+
@episode = match[:episode].to_i
|
14
|
+
@tags = match[:tags].upcase.split(/[\. ]/)
|
15
|
+
@group = match[:group].upcase
|
16
|
+
@distribution = match[:distribution].upcase
|
16
17
|
else
|
17
18
|
raise InvalidFilename
|
18
19
|
end
|
@@ -49,11 +50,12 @@ module Addic7ed
|
|
49
50
|
|
50
51
|
def inspect
|
51
52
|
"Guesses for #{@filename}:
|
52
|
-
show:
|
53
|
-
season:
|
54
|
-
episode:
|
55
|
-
tags:
|
56
|
-
group:
|
53
|
+
show: #{@showname}
|
54
|
+
season: #{@season}
|
55
|
+
episode: #{@episode}
|
56
|
+
tags: #{@tags}
|
57
|
+
group: #{@group}
|
58
|
+
distribution: #{@distribution}"
|
57
59
|
end
|
58
60
|
|
59
61
|
end
|
@@ -7,6 +7,7 @@ describe Addic7ed::Episode do
|
|
7
7
|
@filename_show_not_found = 'Show.Not.Found.S03E02.720p.HDTV.x264-EVOLVE.mkv'
|
8
8
|
@filename_episode_not_found = 'The.Walking.Dead.S03E42.720p.HDTV.x264-EVOLVE.mkv'
|
9
9
|
@filename_compatible_group = 'The.Walking.Dead.S03E04.HDTV.XviD-ASAP.mkv'
|
10
|
+
@filename_no_hi = 'The.Walking.Dead.S03E02.720p.HDTV.x264-KILLERS.mkv'
|
10
11
|
@episode = Addic7ed::Episode.new(@filename)
|
11
12
|
end
|
12
13
|
|
@@ -78,6 +79,13 @@ describe Addic7ed::Episode do
|
|
78
79
|
expect(compatible_episode.best_subtitle('fr').url).to eq 'http://www.addic7ed.com/updated/8/68508/3'
|
79
80
|
end
|
80
81
|
|
82
|
+
it 'finds the subtitle with status completed, same group name and not hearing impaired' do
|
83
|
+
stub_request(:get, 'http://www.addic7ed.com/serie/The_Walking_Dead/3/2/1')
|
84
|
+
.to_return File.new('spec/responses/walking-dead-3-2-1.http')
|
85
|
+
episode = Addic7ed::Episode.new(@filename_no_hi)
|
86
|
+
expect(episode.best_subtitle('en', true).url).to eq 'http://www.addic7ed.com/updated/1/68018/0'
|
87
|
+
end
|
88
|
+
|
81
89
|
it 'uses French as default language' do
|
82
90
|
expect(@episode.best_subtitle).to eq @episode.best_subtitle('fr')
|
83
91
|
end
|
@@ -65,7 +65,7 @@ describe Addic7ed::Subtitle, "#to_s" do
|
|
65
65
|
end
|
66
66
|
|
67
67
|
describe Addic7ed::Subtitle, "#works_for?" do
|
68
|
-
let(:subtitle) { Addic7ed::Subtitle.new(version: "DIMENSION"
|
68
|
+
let(:subtitle) { Addic7ed::Subtitle.new(version: "DIMENSION") }
|
69
69
|
|
70
70
|
context "when it is incomplete" do
|
71
71
|
before { allow(subtitle).to receive(:is_completed?).and_return(false) }
|
@@ -90,16 +90,36 @@ describe Addic7ed::Subtitle, "#works_for?" do
|
|
90
90
|
expect(subtitle.works_for? "EVOLVE").to be false
|
91
91
|
end
|
92
92
|
|
93
|
-
|
94
|
-
|
93
|
+
context "when is has a compatibility comment" do
|
94
|
+
let(:subtitle) { Addic7ed::Subtitle.new(version: "DIMENSION", comment: "Works with IMMERSE") }
|
95
|
+
|
96
|
+
it "returns true given the same version as comment" do
|
97
|
+
expect(subtitle.works_for? "IMMERSE").to be true
|
98
|
+
end
|
99
|
+
|
100
|
+
it "returns true given a compatible version as comment" do
|
101
|
+
expect(subtitle.works_for? "ASAP").to be true
|
102
|
+
end
|
103
|
+
|
104
|
+
it "returns false given an incompatible version as comment" do
|
105
|
+
expect(subtitle.works_for? "KILLERS").to be false
|
106
|
+
end
|
95
107
|
end
|
96
108
|
|
97
|
-
|
98
|
-
|
109
|
+
context "when is has an incompatibility comment" do
|
110
|
+
let(:subtitle) { Addic7ed::Subtitle.new(version: "DIMENSION", comment: "Doesn't work with IMMERSE") }
|
111
|
+
|
112
|
+
it "returns false" do
|
113
|
+
expect(subtitle.works_for? "IMMERSE").to be false
|
114
|
+
end
|
99
115
|
end
|
100
116
|
|
101
|
-
|
102
|
-
|
117
|
+
context "when is has an ambiguous comment" do
|
118
|
+
let(:subtitle) { Addic7ed::Subtitle.new(version: "DIMENSION", comment: "Resync from IMMERSE") }
|
119
|
+
|
120
|
+
it "returns false" do
|
121
|
+
expect(subtitle.works_for? "IMMERSE").to be false
|
122
|
+
end
|
103
123
|
end
|
104
124
|
end
|
105
125
|
end
|
@@ -8,11 +8,12 @@ describe Addic7ed::VideoFile do
|
|
8
8
|
let(:filename) { filename }
|
9
9
|
|
10
10
|
it "it detects successfully" do
|
11
|
-
expect(file.showname).to eq (expected_show_name || 'Showname')
|
12
|
-
expect(file.season
|
13
|
-
expect(file.episode
|
14
|
-
expect(file.tags
|
15
|
-
expect(file.group
|
11
|
+
expect(file.showname ).to eq (expected_show_name || 'Showname')
|
12
|
+
expect(file.season ).to eq 2
|
13
|
+
expect(file.episode ).to eq 1
|
14
|
+
expect(file.tags ).to eq ['720P', 'HDTV', 'X264']
|
15
|
+
expect(file.group ).to eq 'GROUP'
|
16
|
+
expect(file.distribution).to satisfy { |d| ['', 'DISTRIBUTION'].include?(d) }
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -77,6 +78,10 @@ describe Addic7ed::VideoFile do
|
|
77
78
|
it_behaves_like "a media file", "Showname.2014.S02E01.720p.HDTV.x264-GROUP.mkv", "Showname 2014"
|
78
79
|
end
|
79
80
|
|
81
|
+
context "with an optional distribution group name" do
|
82
|
+
it_behaves_like "a media file", "Showname.2014.S02E01.720p.HDTV.x264-GROUP[DISTRIBUTION].mkv", "Showname 2014"
|
83
|
+
end
|
84
|
+
|
80
85
|
context "with a full path" do
|
81
86
|
it_behaves_like "a media file", "/full/path/to/Showname.S02E01.720p.HDTV.x264-GROUP.mkv"
|
82
87
|
end
|
@@ -120,6 +125,11 @@ describe Addic7ed::VideoFile do
|
|
120
125
|
context "with no group" do
|
121
126
|
it_behaves_like "an unknown file", "Showname.S02E01.720p.HDTV.x264.mkv"
|
122
127
|
end
|
128
|
+
|
129
|
+
context "with no distribution" do
|
130
|
+
it_behaves_like "a media file", "Showname.S02E01.720p.HDTV.x264-GROUP.mkv"
|
131
|
+
end
|
132
|
+
|
123
133
|
end
|
124
134
|
|
125
135
|
describe '#encoded_filename' do
|
@@ -177,13 +187,14 @@ describe Addic7ed::VideoFile do
|
|
177
187
|
|
178
188
|
describe '#inspect' do
|
179
189
|
it 'prints a human-readable detailed version' do
|
180
|
-
expect(Addic7ed::VideoFile.new("Showname.S02E01.720p.HDTV.x264-GROUP.mkv").inspect).to eq(
|
181
|
-
'Guesses for Showname.S02E01.720p.HDTV.x264-GROUP.mkv:
|
182
|
-
show:
|
183
|
-
season:
|
184
|
-
episode:
|
185
|
-
tags:
|
186
|
-
group:
|
190
|
+
expect(Addic7ed::VideoFile.new("Showname.S02E01.720p.HDTV.x264-GROUP[DISTRIBUTION].mkv").inspect).to eq(
|
191
|
+
'Guesses for Showname.S02E01.720p.HDTV.x264-GROUP[DISTRIBUTION].mkv:
|
192
|
+
show: Showname
|
193
|
+
season: 2
|
194
|
+
episode: 1
|
195
|
+
tags: ["720P", "HDTV", "X264"]
|
196
|
+
group: GROUP
|
197
|
+
distribution: DISTRIBUTION')
|
187
198
|
end
|
188
199
|
end
|
189
200
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: addic7ed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Baudino
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -70,16 +70,30 @@ dependencies:
|
|
70
70
|
name: nokogiri
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 1.6.7.2
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 1.6.7.2
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: json
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.7.7
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.7.7
|
83
97
|
description: Ruby script (cli) to fetch subtitles on Addic7ed
|
84
98
|
email: michael.baudino@alpine-lab.com
|
85
99
|
executables:
|