addic7ed 0.3.4 → 0.4.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.rb +1 -1
- data/lib/addic7ed/episode.rb +10 -9
- data/lib/addic7ed/parser.rb +9 -8
- data/lib/addic7ed/subtitle.rb +38 -33
- data/lib/addic7ed/version.rb +1 -1
- data/lib/addic7ed/{filename.rb → video_file.rb} +4 -4
- data/spec/{addic7ed-common_spec.rb → lib/addic7ed/common_spec.rb} +0 -0
- data/spec/{addic7ed-episode_spec.rb → lib/addic7ed/episode_spec.rb} +24 -13
- data/spec/lib/addic7ed/subtitle_spec.rb +167 -0
- data/spec/lib/addic7ed/video_file_spec.rb +189 -0
- data/spec/spec_helper.rb +2 -0
- metadata +26 -12
- data/spec/addic7ed-filename_spec.rb +0 -309
- data/spec/addic7ed-subtitle_spec.rb +0 -155
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7ec6d7d5e15148f20ab37ecd8c1fa41de36bbf3
|
4
|
+
data.tar.gz: 1f676080c6d49804e7607b952a62cb3a8e412b31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d7613da70d67bbca0e9fc10698ce6856b8c5bf121e092614f4308141fdc324014d2d4977ca3dc83786a01eab1adb5088e42bf35bb8ea4ab65aece13cb58ffe6
|
7
|
+
data.tar.gz: 0d27c90a45c3d3c5beb71cf3da12e57a01139e14bc893f488b6a2ed589e6fda1d0f80b5f94b811e05f7410614581102be6a1defcb40cc36481343004fe9d8876
|
data/bin/addic7ed
CHANGED
@@ -33,6 +33,10 @@ OptionParser.new do |opts|
|
|
33
33
|
options[:force] = f
|
34
34
|
end
|
35
35
|
|
36
|
+
opts.on("-u", "--untagged", "Do not include language code in subtitle filename") do |u|
|
37
|
+
options[:untagged] = u
|
38
|
+
end
|
39
|
+
|
36
40
|
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
37
41
|
options[:verbose] = v
|
38
42
|
end
|
@@ -77,7 +81,7 @@ options[:filenames].each do |filename|
|
|
77
81
|
end
|
78
82
|
|
79
83
|
begin
|
80
|
-
ep = Addic7ed::Episode.new(filename)
|
84
|
+
ep = Addic7ed::Episode.new(filename, options[:untagged])
|
81
85
|
puts "Searching subtitles for #{ep.filename.basename}" if options[:verbose]
|
82
86
|
if File.file?(filename.gsub(/\.\w{3}$/, '.srt')) and not options[:force]
|
83
87
|
puts "A subtitle already exists (#{filename.gsub(/\.\w{3}$/, '.srt')}). Skipping.".gsub(/^/, options[:verbose] ? ' ' : '') unless options[:quiet]
|
@@ -98,7 +102,7 @@ options[:filenames].each do |filename|
|
|
98
102
|
puts " #{ep.best_subtitle(options[:language])}"
|
99
103
|
end
|
100
104
|
unless options[:nodownload]
|
101
|
-
ep.download_best_subtitle!(options[:language])
|
105
|
+
ep.download_best_subtitle!(options[:language], options[:untagged])
|
102
106
|
puts "New subtitle downloaded for #{filename}.\nEnjoy your show :-)".gsub(/^/, options[:verbose] ? ' ' : '') unless options[:quiet]
|
103
107
|
end
|
104
108
|
rescue Addic7ed::InvalidFilename
|
data/lib/addic7ed.rb
CHANGED
data/lib/addic7ed/episode.rb
CHANGED
@@ -4,16 +4,17 @@ require 'open-uri'
|
|
4
4
|
module Addic7ed
|
5
5
|
class Episode
|
6
6
|
|
7
|
-
attr_reader :
|
7
|
+
attr_reader :file, :untagged
|
8
8
|
|
9
|
-
def initialize(filename)
|
10
|
-
@
|
9
|
+
def initialize(filename, untagged = false)
|
10
|
+
@file = Addic7ed::VideoFile.new(filename)
|
11
|
+
@untagged = untagged
|
11
12
|
end
|
12
13
|
|
13
14
|
def url(lang = 'fr')
|
14
15
|
check_language_availability(lang)
|
15
16
|
@localized_urls ||= {}
|
16
|
-
@localized_urls[lang] ||= "http://www.addic7ed.com/serie/#{
|
17
|
+
@localized_urls[lang] ||= "http://www.addic7ed.com/serie/#{file.encoded_showname}/#{file.season}/#{file.episode}/#{LANGUAGES[lang][:id]}"
|
17
18
|
end
|
18
19
|
|
19
20
|
def subtitles(lang = 'fr')
|
@@ -35,11 +36,11 @@ module Addic7ed
|
|
35
36
|
if response.kind_of?(Net::HTTPRedirection)
|
36
37
|
follow_redirection(lang, response['location'], http_redirect_limit)
|
37
38
|
else
|
38
|
-
save_subtitle
|
39
|
+
save_subtitle(response.body, lang)
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
42
|
-
|
43
|
+
protected
|
43
44
|
|
44
45
|
def find_subtitles(lang)
|
45
46
|
initialize_language(lang)
|
@@ -50,7 +51,7 @@ module Addic7ed
|
|
50
51
|
def find_best_subtitle(lang)
|
51
52
|
@best_subtitle ||= {}
|
52
53
|
subtitles(lang).each do |sub|
|
53
|
-
@best_subtitle[lang] = sub if sub.works_for?
|
54
|
+
@best_subtitle[lang] = sub if sub.works_for? file.group and sub.can_replace? @best_subtitle[lang]
|
54
55
|
end
|
55
56
|
raise NoSubtitleFound unless @best_subtitle[lang]
|
56
57
|
end
|
@@ -83,8 +84,8 @@ module Addic7ed
|
|
83
84
|
download_best_subtitle!(lang, http_redirect_limit - 1)
|
84
85
|
end
|
85
86
|
|
86
|
-
def save_subtitle(content)
|
87
|
-
Kernel.open "#{
|
87
|
+
def save_subtitle(content, lang)
|
88
|
+
Kernel.open "#{file}".gsub(/\.\w{3}$/, untagged ? ".srt" : ".#{lang}.srt"), 'w' do |f|
|
88
89
|
f << content
|
89
90
|
end
|
90
91
|
rescue
|
data/lib/addic7ed/parser.rb
CHANGED
@@ -17,7 +17,7 @@ module Addic7ed
|
|
17
17
|
@subtitles
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
protected
|
21
21
|
|
22
22
|
def subtitles_page_dom
|
23
23
|
response = Net::HTTP.get_response(URI(@episode.url(@lang)))
|
@@ -38,13 +38,14 @@ module Addic7ed
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def parse_subtitle_node(sub_node)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
Addic7ed::Subtitle.new(
|
42
|
+
version: extract_version(sub_node),
|
43
|
+
language: extract_language(sub_node),
|
44
|
+
status: extract_status(sub_node),
|
45
|
+
url: extract_url(sub_node),
|
46
|
+
source: extract_source(sub_node),
|
47
|
+
downloads: extract_downloads(sub_node)
|
48
|
+
)
|
48
49
|
end
|
49
50
|
|
50
51
|
def extract_version(sub_node)
|
data/lib/addic7ed/subtitle.rb
CHANGED
@@ -4,60 +4,65 @@ module Addic7ed
|
|
4
4
|
attr_reader :version, :language, :status, :via, :downloads
|
5
5
|
attr_accessor :url
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@version =
|
9
|
-
@language = language
|
10
|
-
@status = status
|
11
|
-
@url = url
|
12
|
-
@via = via
|
13
|
-
@downloads = downloads.to_i
|
7
|
+
def initialize(options = {})
|
8
|
+
@version = options[:version]
|
9
|
+
@language = options[:language]
|
10
|
+
@status = options[:status]
|
11
|
+
@url = options[:url]
|
12
|
+
@via = options[:via]
|
13
|
+
@downloads = options[:downloads].to_i || 0
|
14
|
+
normalize_version!
|
14
15
|
end
|
15
16
|
|
16
17
|
def to_s
|
17
|
-
"#{url}\t->\t#{
|
18
|
+
"#{url}\t->\t#{version} (#{language}, #{status}) [#{downloads} downloads]#{" (via #{via})" if via}"
|
18
19
|
end
|
19
20
|
|
20
21
|
def works_for?(version = '')
|
21
22
|
is_completed? and is_compatible_with? version
|
22
23
|
end
|
23
24
|
|
24
|
-
def can_replace?(
|
25
|
+
def can_replace?(other_subtitle)
|
25
26
|
return false unless is_completed?
|
26
|
-
return true if
|
27
|
-
language ==
|
28
|
-
is_compatible_with?
|
29
|
-
is_more_popular_than?
|
27
|
+
return true if other_subtitle.nil?
|
28
|
+
language == other_subtitle.language &&
|
29
|
+
is_compatible_with?(other_subtitle.version) &&
|
30
|
+
is_more_popular_than?(other_subtitle)
|
30
31
|
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
def normalized_version(version)
|
35
|
-
version.
|
36
|
-
gsub(/^Version */i, '').
|
37
|
-
gsub(/720p/i, '').
|
38
|
-
gsub(/hdtv/i, '').
|
39
|
-
gsub(/proper/i, '').
|
40
|
-
gsub(/rerip/i, '').
|
41
|
-
gsub(/x\.?264/i, '').
|
42
|
-
gsub(/^[- \.]*/, '').
|
43
|
-
gsub(/[- \.]*$/, '').
|
44
|
-
upcase
|
33
|
+
def is_featured?
|
34
|
+
via == "http://addic7ed.com"
|
45
35
|
end
|
46
36
|
|
47
37
|
def is_completed?
|
48
38
|
status == 'Completed'
|
49
39
|
end
|
50
40
|
|
41
|
+
protected
|
42
|
+
|
43
|
+
def normalize_version!
|
44
|
+
@version ||= ""
|
45
|
+
@version.gsub!(/^Version */i, '')
|
46
|
+
@version.gsub!(/720p/i, '')
|
47
|
+
@version.gsub!(/hdtv/i, '')
|
48
|
+
@version.gsub!(/proper/i, '')
|
49
|
+
@version.gsub!(/rerip/i, '')
|
50
|
+
@version.gsub!(/x\.?264/i, '')
|
51
|
+
@version.gsub!(/^[- \.]*/, '')
|
52
|
+
@version.gsub!(/[- \.]*$/, '')
|
53
|
+
@version.upcase!
|
54
|
+
end
|
55
|
+
|
51
56
|
def is_compatible_with?(other_version)
|
52
|
-
version == other_version
|
53
|
-
COMPATIBILITY_720P[version] == other_version
|
54
|
-
COMPATIBILITY_720P[other_version] == version
|
57
|
+
self.version == other_version ||
|
58
|
+
COMPATIBILITY_720P[self.version] == other_version ||
|
59
|
+
COMPATIBILITY_720P[other_version] == self.version
|
55
60
|
end
|
56
61
|
|
57
|
-
def is_more_popular_than?(
|
58
|
-
return true
|
59
|
-
return false
|
60
|
-
return downloads >
|
62
|
+
def is_more_popular_than?(other_subtitle)
|
63
|
+
return true if other_subtitle.nil?
|
64
|
+
return false if other_subtitle.is_featured?
|
65
|
+
return self.downloads > other_subtitle.downloads
|
61
66
|
end
|
62
67
|
|
63
68
|
end
|
data/lib/addic7ed/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Addic7ed
|
2
|
-
class
|
2
|
+
class VideoFile
|
3
3
|
|
4
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
|
5
5
|
|
@@ -32,15 +32,15 @@ module Addic7ed
|
|
32
32
|
# Lazy getters
|
33
33
|
|
34
34
|
def basename
|
35
|
-
@basename ||= File.basename(@filename)
|
35
|
+
@basename ||= ::File.basename(@filename)
|
36
36
|
end
|
37
37
|
|
38
38
|
def dirname
|
39
|
-
@dirname ||= File.dirname(@filename)
|
39
|
+
@dirname ||= ::File.dirname(@filename)
|
40
40
|
end
|
41
41
|
|
42
42
|
def extname
|
43
|
-
@extname ||= File.extname(@filename)
|
43
|
+
@extname ||= ::File.extname(@filename)
|
44
44
|
end
|
45
45
|
|
46
46
|
def to_s
|
File without changes
|
@@ -94,53 +94,64 @@ describe Addic7ed::Episode do
|
|
94
94
|
end
|
95
95
|
|
96
96
|
describe '#download_best_subtitle!' do
|
97
|
-
|
97
|
+
let(:episode) { Addic7ed::Episode.new(@filename) }
|
98
|
+
|
99
|
+
before do
|
98
100
|
WebMock.reset!
|
99
101
|
@page_stub = stub_request(:get, 'http://www.addic7ed.com/serie/The_Walking_Dead/3/2/8')
|
100
102
|
.to_return File.new('spec/responses/walking-dead-3-2-8.http')
|
101
103
|
@sub_stub = stub_request(:get, 'http://www.addic7ed.com/original/68018/4')
|
102
104
|
.to_return File.new('spec/responses/walking-dead-3-2-8_best_subtitle.http')
|
103
|
-
# The Episode object must be re-created between every test, since redirection may modify its URI
|
104
|
-
@reset_episode = Addic7ed::Episode.new(@filename)
|
105
105
|
# Prevent actual disk writing
|
106
106
|
allow(Kernel).to receive(:open)
|
107
107
|
end
|
108
108
|
|
109
109
|
it 'gets the best subtitle candidate with a network request' do
|
110
|
-
expect(
|
111
|
-
|
110
|
+
expect(episode).to receive(:best_subtitle).once.and_call_original
|
111
|
+
episode.download_best_subtitle!('fr')
|
112
112
|
expect(@page_stub).to have_been_requested
|
113
113
|
expect(@sub_stub).to have_been_requested
|
114
114
|
end
|
115
115
|
|
116
116
|
it 'raises DownloadError when a network error happens' do
|
117
117
|
stub_request(:get, 'http://www.addic7ed.com/original/68018/4').to_timeout
|
118
|
-
expect{
|
118
|
+
expect{ episode.download_best_subtitle!('fr') }.to raise_error Addic7ed::DownloadError
|
119
119
|
end
|
120
120
|
|
121
121
|
it 'is called recursively' do
|
122
122
|
stub_request(:get, 'http://www.addic7ed.com/original/68018/4').to_return File.new('spec/responses/basic_redirection.http')
|
123
123
|
stub_request(:get, 'http://www.addic7ed.com/original/68018/4.redirected').to_return File.new('spec/responses/walking-dead-3-2-8_best_subtitle.http')
|
124
|
-
expect(
|
125
|
-
|
124
|
+
expect(episode).to receive(:download_best_subtitle!).twice.and_call_original
|
125
|
+
episode.download_best_subtitle!('fr')
|
126
126
|
end
|
127
127
|
|
128
128
|
it 'raises HTTPError when stuck in a HTTP redirections loop' do
|
129
129
|
stub_request(:get, 'http://www.addic7ed.com/original/68018/4')
|
130
130
|
.to_return File.new('spec/responses/redirection_loop.http')
|
131
|
-
expect{
|
131
|
+
expect{ episode.download_best_subtitle!('fr') }.to raise_error Addic7ed::HTTPError
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'creates a new file on disk' do
|
135
135
|
file = double('file')
|
136
|
-
expect(Kernel).to receive(:open).with('The.Walking.Dead.S03E02.720p.HDTV.x264-EVOLVE.srt', 'w').and_yield(file)
|
136
|
+
expect(Kernel).to receive(:open).with('The.Walking.Dead.S03E02.720p.HDTV.x264-EVOLVE.fr.srt', 'w').and_yield(file)
|
137
137
|
expect(file).to receive(:<<)
|
138
|
-
|
138
|
+
episode.download_best_subtitle!('fr')
|
139
|
+
end
|
140
|
+
|
141
|
+
context "when untagged option is set" do
|
142
|
+
let(:episode) { Addic7ed::Episode.new(@filename, true) }
|
143
|
+
|
144
|
+
it "does not include language code in subtitle filename" do
|
145
|
+
file = double('file')
|
146
|
+
expect(Kernel).to receive(:open).with('The.Walking.Dead.S03E02.720p.HDTV.x264-EVOLVE.srt', 'w').and_yield(file)
|
147
|
+
expect(file).to receive(:<<)
|
148
|
+
episode.download_best_subtitle!('fr')
|
149
|
+
end
|
139
150
|
end
|
140
151
|
|
141
152
|
it 'raises SubtitleCannotBeSaved when a disk error happens' do
|
142
|
-
expect(Kernel).to receive(:open).with('The.Walking.Dead.S03E02.720p.HDTV.x264-EVOLVE.srt', 'w').and_raise('Persmission denied')
|
143
|
-
expect{
|
153
|
+
expect(Kernel).to receive(:open).with('The.Walking.Dead.S03E02.720p.HDTV.x264-EVOLVE.fr.srt', 'w').and_raise('Persmission denied')
|
154
|
+
expect{ episode.download_best_subtitle!('fr') }.to raise_error Addic7ed::SubtitleCannotBeSaved
|
144
155
|
end
|
145
156
|
end
|
146
157
|
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "./lib/addic7ed"
|
3
|
+
|
4
|
+
describe Addic7ed::Subtitle, "#normalize_version!" do
|
5
|
+
def normalized_version(version)
|
6
|
+
Addic7ed::Subtitle.new(version: version).version
|
7
|
+
end
|
8
|
+
|
9
|
+
it "upcases everything" do
|
10
|
+
expect(normalized_version("DiMENSiON")).to eq 'DIMENSION'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "removes heading or trailing dots" do
|
14
|
+
expect(normalized_version(".DIMENSION.")).to eq 'DIMENSION'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "removes heading or trailing whitespaces" do
|
18
|
+
expect(normalized_version(" DIMENSION ")).to eq 'DIMENSION'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "removes heading or trailing dashes" do
|
22
|
+
expect(normalized_version("-DIMENSION-")).to eq 'DIMENSION'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "removes '720p' tag" do
|
26
|
+
expect(normalized_version("720P DIMENSION")).to eq 'DIMENSION'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "removes 'HDTV' tag" do
|
30
|
+
expect(normalized_version("HDTV DIMENSION")).to eq 'DIMENSION'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "removes 'x264' tag" do
|
34
|
+
expect(normalized_version("X264 DIMENSION")).to eq 'DIMENSION'
|
35
|
+
expect(normalized_version("X.264 DIMENSION")).to eq 'DIMENSION'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "removes 'PROPER' tag" do
|
39
|
+
expect(normalized_version("PROPER DIMENSION")).to eq 'DIMENSION'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "removes 'RERIP' tag" do
|
43
|
+
expect(normalized_version("RERIP DIMENSION")).to eq 'DIMENSION'
|
44
|
+
end
|
45
|
+
|
46
|
+
it "removes the 'Version' prefix" do
|
47
|
+
expect(normalized_version("Version DIMENSION")).to eq 'DIMENSION'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe Addic7ed::Subtitle, "#to_s" do
|
52
|
+
let(:subtitle) { Addic7ed::Subtitle.new(version: "DIMENSION", language: "fr", status: "Completed", url: "http://some.fancy.url", via: "http://addic7ed.com", downloads: "42") }
|
53
|
+
|
54
|
+
it "prints a human readable version" do
|
55
|
+
expect(subtitle.to_s).to eq "http://some.fancy.url\t->\tDIMENSION (fr, Completed) [42 downloads] (via http://addic7ed.com)"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe Addic7ed::Subtitle, "#works_for?" do
|
60
|
+
let(:subtitle) { Addic7ed::Subtitle.new(version: "DIMENSION") }
|
61
|
+
|
62
|
+
context "when it is incomplete" do
|
63
|
+
before { allow(subtitle).to receive(:is_completed?).and_return(false) }
|
64
|
+
|
65
|
+
it "returns false" do
|
66
|
+
expect(subtitle.works_for? "DIMENSION").to be false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when it is completed" do
|
71
|
+
before { allow(subtitle).to receive(:is_completed?).and_return(true) }
|
72
|
+
|
73
|
+
it "returns true given the exact same version" do
|
74
|
+
expect(subtitle.works_for? "DIMENSION").to be true
|
75
|
+
end
|
76
|
+
|
77
|
+
it "returns true given a compatible version" do
|
78
|
+
expect(subtitle.works_for? "LOL").to be true
|
79
|
+
end
|
80
|
+
|
81
|
+
it "returns false given an incompatible version" do
|
82
|
+
expect(subtitle.works_for? "EVOLVE").to be false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe Addic7ed::Subtitle, "#can_replace?" do
|
88
|
+
let(:defaults) { {version: "DIMENSION", language: "fr", status: "Completed", downloads: "10"} }
|
89
|
+
let(:subtitle) { Addic7ed::Subtitle.new(defaults) }
|
90
|
+
let(:other_subtitle) { Addic7ed::Subtitle.new(defaults) }
|
91
|
+
|
92
|
+
context "when it is incomplete" do
|
93
|
+
before { allow(subtitle).to receive(:is_completed?).and_return(false) }
|
94
|
+
|
95
|
+
it "returns false" do
|
96
|
+
expect(subtitle.can_replace? other_subtitle).to be false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "when it is completed" do
|
101
|
+
before { allow(subtitle).to receive(:is_completed?).and_return(true) }
|
102
|
+
|
103
|
+
it "returns true given no other_subtitle" do
|
104
|
+
expect(subtitle.can_replace? nil).to be true
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when other_subtitle has a different language" do
|
108
|
+
before { allow(other_subtitle).to receive(:language).and_return("en") }
|
109
|
+
|
110
|
+
it "returns false" do
|
111
|
+
expect(subtitle.can_replace? other_subtitle).to be false
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "when other_subtitle has an incompatible version" do
|
116
|
+
before { allow(subtitle).to receive(:is_compatible_with?).with(other_subtitle.version).and_return(false) }
|
117
|
+
|
118
|
+
it "returns false" do
|
119
|
+
expect(subtitle.can_replace? other_subtitle).to be false
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "when other_subtitle is featured by Addic7ed" do
|
124
|
+
before { allow(other_subtitle).to receive(:is_featured?).and_return(true) }
|
125
|
+
|
126
|
+
it "returns false" do
|
127
|
+
expect(subtitle.can_replace? other_subtitle).to be false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "when other_subtitle has more downloads" do
|
132
|
+
before { allow(other_subtitle).to receive(:downloads).and_return(subtitle.downloads + 1) }
|
133
|
+
|
134
|
+
it "returns false" do
|
135
|
+
expect(subtitle.can_replace? other_subtitle).to be false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "when other_subtitle has less downloads" do
|
140
|
+
before { allow(other_subtitle).to receive(:downloads).and_return(subtitle.downloads - 1) }
|
141
|
+
|
142
|
+
it "returns true" do
|
143
|
+
expect(subtitle.can_replace? other_subtitle).to be true
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe Addic7ed::Subtitle, "#is_featured?" do
|
150
|
+
it "returns true when 'via' is 'http://addic7ed.com'" do
|
151
|
+
expect(Addic7ed::Subtitle.new(via: 'http://addic7ed.com').is_featured?).to be true
|
152
|
+
end
|
153
|
+
|
154
|
+
it "returns false otherwise" do
|
155
|
+
expect(Addic7ed::Subtitle.new(via: 'anything else').is_featured?).to be false
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe Addic7ed::Subtitle, "#is_completed?" do
|
160
|
+
it "returns true when 'status' is 'Completed'" do
|
161
|
+
expect(Addic7ed::Subtitle.new(status: 'Completed').is_completed?).to be true
|
162
|
+
end
|
163
|
+
|
164
|
+
it "returns false otherwise" do
|
165
|
+
expect(Addic7ed::Subtitle.new(status: '80%').is_completed?).to be false
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require './lib/addic7ed'
|
3
|
+
|
4
|
+
describe Addic7ed::VideoFile do
|
5
|
+
let(:file) { Addic7ed::VideoFile.new(filename) }
|
6
|
+
|
7
|
+
shared_examples "a media file" do |filename, expected_show_name|
|
8
|
+
let(:filename) { filename }
|
9
|
+
|
10
|
+
it "it detects successfully" do
|
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
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
shared_examples "an unknown file" do |filename|
|
20
|
+
let(:filename) { filename }
|
21
|
+
|
22
|
+
it "raises an error" do
|
23
|
+
expect{file}.to raise_error Addic7ed::InvalidFilename
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#initialize" do
|
28
|
+
context "with regular notation" do
|
29
|
+
it_behaves_like "a media file", "Showname.S02E01.720p.HDTV.x264-GROUP.mkv"
|
30
|
+
end
|
31
|
+
|
32
|
+
context "with x notation" do
|
33
|
+
it_behaves_like "a media file", "Showname.02x01.720p.HDTV.x264-GROUP.mkv"
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with 3-digits notation' do
|
37
|
+
it_behaves_like "a media file", "Showname.201.720p.HDTV.x264-GROUP.mkv"
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with brackets notation' do
|
41
|
+
it_behaves_like "a media file", "Showname.[S02E01].720p.HDTV.x264-GROUP.mkv"
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'with brackets and x notation' do
|
45
|
+
it_behaves_like "a media file", "Showname.[2x01].720p.HDTV.x264-GROUP.mkv"
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with brackets and 3-digits notation' do
|
49
|
+
it_behaves_like "a media file", "Showname.[201].720p.HDTV.x264-GROUP.mkv"
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with brackets and x notation and space separator' do
|
53
|
+
it_behaves_like "a media file", "Showname [2x01] 720p.HDTV.x264-GROUP.mkv"
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with brackets and 3-digits notation and space separator' do
|
57
|
+
it_behaves_like "a media file", "Showname [201] 720p.HDTV.x264-GROUP.mkv"
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with lowercase filename' do
|
61
|
+
it_behaves_like "a media file", "showname.s02e01.720p.HDTV.x264-group.mkv", "showname"
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'with multiple words in show name' do
|
65
|
+
it_behaves_like "a media file", "Show.Name.S02E01.720p.HDTV.x264-GROUP.mkv", "Show Name"
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'with multiple words in show name separated by spaces' do
|
69
|
+
it_behaves_like "a media file", "Show Name.S02E01.720p.HDTV.x264-GROUP.mkv", "Show Name"
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'with only numbers in show name' do
|
73
|
+
it_behaves_like "a media file", "42.S02E01.720p.HDTV.x264-GROUP.mkv", "42"
|
74
|
+
end
|
75
|
+
|
76
|
+
context "with production year" do
|
77
|
+
it_behaves_like "a media file", "Showname.2014.S02E01.720p.HDTV.x264-GROUP.mkv", "Showname 2014"
|
78
|
+
end
|
79
|
+
|
80
|
+
context "with a full path" do
|
81
|
+
it_behaves_like "a media file", "/full/path/to/Showname.S02E01.720p.HDTV.x264-GROUP.mkv"
|
82
|
+
end
|
83
|
+
|
84
|
+
context "with a relative path" do
|
85
|
+
it_behaves_like "a media file", "../path/to/Showname.S02E01.720p.HDTV.x264-GROUP.mkv"
|
86
|
+
end
|
87
|
+
|
88
|
+
context "without extension" do
|
89
|
+
it_behaves_like "a media file", "Showname.S02E01.720p.HDTV.x264-GROUP"
|
90
|
+
end
|
91
|
+
|
92
|
+
context "with a double episode" do
|
93
|
+
it_behaves_like "a media file", "Showname.S02E0102.720p.HDTV.x264-GROUP.mkv"
|
94
|
+
end
|
95
|
+
|
96
|
+
context "with a double episode" do
|
97
|
+
it_behaves_like "a media file", "Showname.S02E01E02.720p.HDTV.x264-GROUP.mkv"
|
98
|
+
end
|
99
|
+
|
100
|
+
context "with a double episode with dash separator" do
|
101
|
+
it_behaves_like "a media file", "Showname.S02E01-02.720p.HDTV.x264-GROUP.mkv"
|
102
|
+
end
|
103
|
+
|
104
|
+
context "with no showname" do
|
105
|
+
it_behaves_like "an unknown file", ".S02E01.720p.HDTV.x264-GROUP.mkv"
|
106
|
+
end
|
107
|
+
|
108
|
+
context "with no season number" do
|
109
|
+
it_behaves_like "an unknown file", "Showname.E01.720p.HDTV.x264-GROUP.mkv"
|
110
|
+
end
|
111
|
+
|
112
|
+
context "with no episode number" do
|
113
|
+
it_behaves_like "an unknown file", "Showname.S02.720p.HDTV.x264-GROUP.mkv"
|
114
|
+
end
|
115
|
+
|
116
|
+
context "with no tag" do
|
117
|
+
it_behaves_like "an unknown file", "Showname.S02E01-GROUP.mkv"
|
118
|
+
end
|
119
|
+
|
120
|
+
context "with no group" do
|
121
|
+
it_behaves_like "an unknown file", "Showname.S02E01.720p.HDTV.x264.mkv"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#encoded_filename' do
|
126
|
+
it 'changes all spaces to underscores' do
|
127
|
+
expect(Addic7ed::VideoFile.new("Show Name.S02E01.720p.HDTV.x264-GROUP.mkv").encoded_showname).to eq 'Show_Name'
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'wraps country code with parenthesis' do
|
131
|
+
expect(Addic7ed::VideoFile.new("Showname.US.S02E01.720p.HDTV.x264-GROUP.mkv").encoded_showname).to eq 'Showname_(US)'
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'detects country code even in lowercase' do
|
135
|
+
expect(Addic7ed::VideoFile.new("showname.us.S02E01.720p.HDTV.x264-GROUP.mkv").encoded_showname).to eq 'showname_(us)'
|
136
|
+
end
|
137
|
+
|
138
|
+
it "removes country code for the original show when it's UK" do
|
139
|
+
expect(Addic7ed::VideoFile.new("Showname.UK.S02E01.720p.HDTV.x264-GROUP.mkv").encoded_showname).to eq 'Showname'
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'removes production year' do
|
143
|
+
expect(Addic7ed::VideoFile.new("Showname.2014.S02E01.720p.HDTV.x264-GROUP.mkv").encoded_showname).to eq 'Showname'
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'handles when both country code and production year are present' do
|
147
|
+
expect(Addic7ed::VideoFile.new("Showname.2014.UK.S02E01.720p.HDTV.x264-GROUP.mkv").encoded_showname).to eq 'Showname'
|
148
|
+
expect(Addic7ed::VideoFile.new("Showname.UK.2014.S02E01.720p.HDTV.x264-GROUP.mkv").encoded_showname).to eq 'Showname'
|
149
|
+
expect(Addic7ed::VideoFile.new("Showname.2014.US.S02E01.720p.HDTV.x264-GROUP.mkv").encoded_showname).to eq 'Showname_(US)'
|
150
|
+
expect(Addic7ed::VideoFile.new("Showname.US.2014.S02E01.720p.HDTV.x264-GROUP.mkv").encoded_showname).to eq 'Showname_(US)'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#basename' do
|
155
|
+
it 'returns only file name given a full path' do
|
156
|
+
expect(Addic7ed::VideoFile.new("/full/path/to/Showname.S02E01.720p.HDTV.x264-GROUP.mkv").basename).to eq "Showname.S02E01.720p.HDTV.x264-GROUP.mkv"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '#dirname' do
|
161
|
+
it 'returns only path given a full path' do
|
162
|
+
expect(Addic7ed::VideoFile.new("/full/path/to/Showname.S02E01.720p.HDTV.x264-GROUP.mkv").dirname).to eq '/full/path/to'
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#extname' do
|
167
|
+
it 'returns only file extension given a full path' do
|
168
|
+
expect(Addic7ed::VideoFile.new("/full/path/to/Showname.S02E01.720p.HDTV.x264-GROUP.mkv").extname).to eq '.mkv'
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe '#to_s' do
|
173
|
+
it 'returns file name as a string' do
|
174
|
+
expect(Addic7ed::VideoFile.new("/full/path/to/Showname.S02E01.720p.HDTV.x264-GROUP.mkv").to_s).to eq "/full/path/to/Showname.S02E01.720p.HDTV.x264-GROUP.mkv"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe '#inspect' do
|
179
|
+
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: Showname
|
183
|
+
season: 2
|
184
|
+
episode: 1
|
185
|
+
tags: ["720P", "HDTV", "X264"]
|
186
|
+
group: GROUP')
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
data/spec/spec_helper.rb
CHANGED
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.4.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:
|
11
|
+
date: 2015-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: nokogiri
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -79,14 +93,14 @@ files:
|
|
79
93
|
- lib/addic7ed/common.rb
|
80
94
|
- lib/addic7ed/episode.rb
|
81
95
|
- lib/addic7ed/errors.rb
|
82
|
-
- lib/addic7ed/filename.rb
|
83
96
|
- lib/addic7ed/parser.rb
|
84
97
|
- lib/addic7ed/subtitle.rb
|
85
98
|
- lib/addic7ed/version.rb
|
86
|
-
-
|
87
|
-
- spec/addic7ed
|
88
|
-
- spec/addic7ed
|
89
|
-
- spec/addic7ed
|
99
|
+
- lib/addic7ed/video_file.rb
|
100
|
+
- spec/lib/addic7ed/common_spec.rb
|
101
|
+
- spec/lib/addic7ed/episode_spec.rb
|
102
|
+
- spec/lib/addic7ed/subtitle_spec.rb
|
103
|
+
- spec/lib/addic7ed/video_file_spec.rb
|
90
104
|
- spec/responses/basic_redirection.http
|
91
105
|
- spec/responses/redirection_loop.http
|
92
106
|
- spec/responses/walking-dead-3-2-1.http
|
@@ -117,15 +131,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
131
|
version: '0'
|
118
132
|
requirements: []
|
119
133
|
rubyforge_project:
|
120
|
-
rubygems_version: 2.
|
134
|
+
rubygems_version: 2.4.5
|
121
135
|
signing_key:
|
122
136
|
specification_version: 4
|
123
137
|
summary: Addic7ed auto-downloader
|
124
138
|
test_files:
|
125
|
-
- spec/addic7ed
|
126
|
-
- spec/addic7ed
|
127
|
-
- spec/addic7ed
|
128
|
-
- spec/addic7ed
|
139
|
+
- spec/lib/addic7ed/common_spec.rb
|
140
|
+
- spec/lib/addic7ed/episode_spec.rb
|
141
|
+
- spec/lib/addic7ed/subtitle_spec.rb
|
142
|
+
- spec/lib/addic7ed/video_file_spec.rb
|
129
143
|
- spec/responses/basic_redirection.http
|
130
144
|
- spec/responses/redirection_loop.http
|
131
145
|
- spec/responses/walking-dead-3-2-1.http
|
@@ -1,309 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require './lib/addic7ed'
|
3
|
-
|
4
|
-
describe Addic7ed::Filename do
|
5
|
-
before :all do
|
6
|
-
# Valid filenames
|
7
|
-
@filename = 'Californication.S06E07.720p.HDTV.x264-2HD.mkv'
|
8
|
-
@filename_x = 'Californication.06x07.720p.HDTV.x264-2HD.mkv'
|
9
|
-
@filename_3digits = 'Californication.607.720p.HDTV.x264-2HD.mkv'
|
10
|
-
@filename_brackets = 'Californication.[S06E07].720p.HDTV.x264-2HD.mkv'
|
11
|
-
@filename_x_brackets = 'Californication.[6x07].720p.HDTV.x264-2HD.mkv'
|
12
|
-
@filename_3digits_brackets = 'Californication.[607].720p.HDTV.x264-2HD.mkv'
|
13
|
-
@filename_brackets_spaces = 'Californication [607] 720p.HDTV.x264-2HD.mkv'
|
14
|
-
@filename_x_brackets_spaces = 'Californication [6x07] 720p.HDTV.x264-2HD.mkv'
|
15
|
-
@filename_3digits_brackets_spaces = 'Californication [607] 720p.HDTV.x264-2HD.mkv'
|
16
|
-
@filename_lowercase = 'californication.s06e07.720p.hdtv.x264-2hd.mkv'
|
17
|
-
@filename_lowercase_x = 'californication.6x07.720p.hdtv.x264-2hd.mkv'
|
18
|
-
@filename_multiple_words = 'The.Walking.Dead.S03E11.720p.HDTV.x264-EVOLVE.mkv'
|
19
|
-
@filename_multiple_words_spaces = 'The Walking Dead S03E11 720p.HDTV.x264-EVOLVE.mkv'
|
20
|
-
@filename_numbers_only = '90210.S05E12.720p.HDTV.X264-DIMENSION.mkv'
|
21
|
-
@filename_showname_year = 'The.Americans.2013.S01E04.720p.HDTV.X264-DIMENSION.mkv'
|
22
|
-
@filename_full_path = '/data/public/Series/Californication/Saison 06/Californication.S06E07.720p.HDTV.x264-2HD.mkv'
|
23
|
-
@filename_relative_path = '../Saison 06/Californication.S06E07.720p.HDTV.x264-2HD.mkv'
|
24
|
-
@filename_no_extension = 'Californication.S06E07.720p.HDTV.x264-2HD'
|
25
|
-
@filename_double_episode = 'Revenge.S02E21E22.720p.HDTV.X264-DIMENSION.mkv'
|
26
|
-
@filename_double_episode_with_dash = 'Revenge.S02E21-22.720p.HDTV.X264-DIMENSION.mkv'
|
27
|
-
# Invalid filenames
|
28
|
-
@filename_no_showname = '.S06E07.720p.HDTV.x264-2HD.mkv'
|
29
|
-
@filename_no_season = 'Californication.E07.720p.HDTV.x264-2HD.mkv'
|
30
|
-
@filename_no_episode = 'Californication.S06.720p.HDTV.x264-2HD.mkv'
|
31
|
-
@filename_no_tags = 'Californication.S06E07.2HD.mkv'
|
32
|
-
@filename_no_group = 'Californication.S06E07.720p.HDTV.x264.mkv'
|
33
|
-
# Filename with special tags
|
34
|
-
@filename_showname_US = 'Shameless.US.S03E06.720p.HDTV.x264-IMMERSE.mkv'
|
35
|
-
@filename_showname_UK = 'Shameless.UK.S09E11.720p.HDTV.x264-TLA.mkv'
|
36
|
-
@filename_showname_US_lowercase = 'shameless.us.s04e01.720p.hdtv.x264-2hd.mkv'
|
37
|
-
@filename_showname_UK_year = 'The.Hour.UK.2011.S01E03.REPACK.HDTV.XviD-FoV.avi'
|
38
|
-
@filename_showname_year_UK = 'The.Hour.2011.UK.S01E03.REPACK.HDTV.XviD-FoV.avi'
|
39
|
-
@filename_showname_US_year = 'The.Hour.US.2011.S01E03.REPACK.HDTV.XviD-FoV.avi'
|
40
|
-
@filename_showname_year_US = 'The.Hour.2011.US.S01E03.REPACK.HDTV.XviD-FoV.avi'
|
41
|
-
end
|
42
|
-
|
43
|
-
describe '#initialize' do
|
44
|
-
it 'succeeds given valid argument' do
|
45
|
-
expect{ @file = Addic7ed::Filename.new(@filename) }.to_not raise_error
|
46
|
-
expect(@file.showname).to eq 'Californication'
|
47
|
-
expect(@file.season ).to eq 6
|
48
|
-
expect(@file.episode ).to eq 7
|
49
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
50
|
-
expect(@file.group ).to eq '2HD'
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'succeeds given filename with x notation' do
|
54
|
-
expect{ @file = Addic7ed::Filename.new(@filename_x) }.to_not raise_error
|
55
|
-
expect(@file.showname).to eq 'Californication'
|
56
|
-
expect(@file.season ).to eq 6
|
57
|
-
expect(@file.episode ).to eq 7
|
58
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
59
|
-
expect(@file.group ).to eq '2HD'
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'succeeds given filename with 3-digits notation' do
|
63
|
-
expect{ @file = Addic7ed::Filename.new(@filename_3digits) }.to_not raise_error
|
64
|
-
expect(@file.showname).to eq 'Californication'
|
65
|
-
expect(@file.season ).to eq 6
|
66
|
-
expect(@file.episode ).to eq 7
|
67
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
68
|
-
expect(@file.group ).to eq '2HD'
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'succeeds given filename with brackets notation' do
|
72
|
-
expect{ @file = Addic7ed::Filename.new(@filename_brackets) }.to_not raise_error
|
73
|
-
expect(@file.showname).to eq 'Californication'
|
74
|
-
expect(@file.season ).to eq 6
|
75
|
-
expect(@file.episode ).to eq 7
|
76
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
77
|
-
expect(@file.group ).to eq '2HD'
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'succeeds given filename with brackets and x notation' do
|
81
|
-
expect{ @file = Addic7ed::Filename.new(@filename_x_brackets) }.to_not raise_error
|
82
|
-
expect(@file.showname).to eq 'Californication'
|
83
|
-
expect(@file.season ).to eq 6
|
84
|
-
expect(@file.episode ).to eq 7
|
85
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
86
|
-
expect(@file.group ).to eq '2HD'
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'succeeds given filename with brackets and 3-digits notation' do
|
90
|
-
expect{ @file = Addic7ed::Filename.new(@filename_3digits_brackets) }.to_not raise_error
|
91
|
-
expect(@file.showname).to eq 'Californication'
|
92
|
-
expect(@file.season ).to eq 6
|
93
|
-
expect(@file.episode ).to eq 7
|
94
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
95
|
-
expect(@file.group ).to eq '2HD'
|
96
|
-
end
|
97
|
-
|
98
|
-
it 'succeeds given filename with brackets notation and space separator' do
|
99
|
-
expect{ @file = Addic7ed::Filename.new(@filename_brackets_spaces) }.to_not raise_error
|
100
|
-
expect(@file.showname).to eq 'Californication'
|
101
|
-
expect(@file.season ).to eq 6
|
102
|
-
expect(@file.episode ).to eq 7
|
103
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
104
|
-
expect(@file.group ).to eq '2HD'
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'succeeds given filename with brackets and x notation and space separator' do
|
108
|
-
expect{ @file = Addic7ed::Filename.new(@filename_x_brackets_spaces) }.to_not raise_error
|
109
|
-
expect(@file.showname).to eq 'Californication'
|
110
|
-
expect(@file.season ).to eq 6
|
111
|
-
expect(@file.episode ).to eq 7
|
112
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
113
|
-
expect(@file.group ).to eq '2HD'
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'succeeds given filename with brackets and 3-digits notation and space separator' do
|
117
|
-
expect{ @file = Addic7ed::Filename.new(@filename_3digits_brackets_spaces) }.to_not raise_error
|
118
|
-
expect(@file.showname).to eq 'Californication'
|
119
|
-
expect(@file.season ).to eq 6
|
120
|
-
expect(@file.episode ).to eq 7
|
121
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
122
|
-
expect(@file.group ).to eq '2HD'
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'succeeds given lowercase filename' do
|
126
|
-
expect{ @file = Addic7ed::Filename.new(@filename_lowercase) }.to_not raise_error
|
127
|
-
expect(@file.showname).to eq 'californication'
|
128
|
-
expect(@file.season ).to eq 6
|
129
|
-
expect(@file.episode ).to eq 7
|
130
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
131
|
-
expect(@file.group ).to eq '2HD'
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'succeeds given lowercase filename with x notation' do
|
135
|
-
expect{ @file = Addic7ed::Filename.new(@filename_lowercase_x) }.to_not raise_error
|
136
|
-
expect(@file.showname).to eq 'californication'
|
137
|
-
expect(@file.season ).to eq 6
|
138
|
-
expect(@file.episode ).to eq 7
|
139
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
140
|
-
expect(@file.group ).to eq '2HD'
|
141
|
-
end
|
142
|
-
|
143
|
-
it 'succeeds given filename with showname containing multiple words' do
|
144
|
-
expect{ @file = Addic7ed::Filename.new(@filename_multiple_words) }.to_not raise_error
|
145
|
-
expect(@file.showname).to eq 'The Walking Dead'
|
146
|
-
expect(@file.season ).to eq 3
|
147
|
-
expect(@file.episode ).to eq 11
|
148
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
149
|
-
expect(@file.group ).to eq 'EVOLVE'
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'succeeds given filename with showname containing multiple words with space separator' do
|
153
|
-
expect{ @file = Addic7ed::Filename.new(@filename_multiple_words_spaces) }.to_not raise_error
|
154
|
-
expect(@file.showname).to eq 'The Walking Dead'
|
155
|
-
expect(@file.season ).to eq 3
|
156
|
-
expect(@file.episode ).to eq 11
|
157
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
158
|
-
expect(@file.group ).to eq 'EVOLVE'
|
159
|
-
end
|
160
|
-
|
161
|
-
it 'succeeds given filename with showname containing only numbers' do
|
162
|
-
expect{ @file = Addic7ed::Filename.new(@filename_numbers_only) }.to_not raise_error
|
163
|
-
expect(@file.showname).to eq '90210'
|
164
|
-
expect(@file.season ).to eq 5
|
165
|
-
expect(@file.episode ).to eq 12
|
166
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
167
|
-
expect(@file.group ).to eq 'DIMENSION'
|
168
|
-
end
|
169
|
-
|
170
|
-
it 'succeeds given filename with showname containing production year' do
|
171
|
-
expect{ @file = Addic7ed::Filename.new(@filename_showname_year) }.to_not raise_error
|
172
|
-
expect(@file.showname).to eq 'The Americans 2013'
|
173
|
-
expect(@file.season ).to eq 1
|
174
|
-
expect(@file.episode ).to eq 4
|
175
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
176
|
-
expect(@file.group ).to eq 'DIMENSION'
|
177
|
-
end
|
178
|
-
|
179
|
-
it 'succeeds given filename containing full path' do
|
180
|
-
expect{ @file = Addic7ed::Filename.new(@filename_full_path) }.to_not raise_error
|
181
|
-
expect(@file.showname).to eq 'Californication'
|
182
|
-
expect(@file.season ).to eq 6
|
183
|
-
expect(@file.episode ).to eq 7
|
184
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
185
|
-
expect(@file.group ).to eq '2HD'
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'succeeds given filename containing relative path' do
|
189
|
-
expect{ @file = Addic7ed::Filename.new(@filename_relative_path) }.to_not raise_error
|
190
|
-
expect(@file.showname).to eq 'Californication'
|
191
|
-
expect(@file.season ).to eq 6
|
192
|
-
expect(@file.episode ).to eq 7
|
193
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
194
|
-
expect(@file.group ).to eq '2HD'
|
195
|
-
end
|
196
|
-
|
197
|
-
it 'succeeds given filename containing no extension' do
|
198
|
-
expect{ @file = Addic7ed::Filename.new(@filename_no_extension) }.to_not raise_error
|
199
|
-
expect(@file.showname).to eq 'Californication'
|
200
|
-
expect(@file.season ).to eq 6
|
201
|
-
expect(@file.episode ).to eq 7
|
202
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
203
|
-
expect(@file.group ).to eq '2HD'
|
204
|
-
end
|
205
|
-
|
206
|
-
it 'succeeds given filename which is a double episode' do
|
207
|
-
expect{ @file = Addic7ed::Filename.new(@filename_double_episode) }.to_not raise_error
|
208
|
-
expect(@file.showname).to eq 'Revenge'
|
209
|
-
expect(@file.season ).to eq 2
|
210
|
-
expect(@file.episode ).to eq 21
|
211
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
212
|
-
expect(@file.group ).to eq 'DIMENSION'
|
213
|
-
end
|
214
|
-
|
215
|
-
it 'succeeds given filename which is a double episode (with a dash)' do
|
216
|
-
expect{ @file = Addic7ed::Filename.new(@filename_double_episode_with_dash) }.to_not raise_error
|
217
|
-
expect(@file.showname).to eq 'Revenge'
|
218
|
-
expect(@file.season ).to eq 2
|
219
|
-
expect(@file.episode ).to eq 21
|
220
|
-
expect(@file.tags ).to eq ['720P', 'HDTV', 'X264']
|
221
|
-
expect(@file.group ).to eq 'DIMENSION'
|
222
|
-
end
|
223
|
-
|
224
|
-
it 'fails given filename with no showname' do
|
225
|
-
expect{ Addic7ed::Filename.new(@filename_no_showname) }.to raise_error Addic7ed::InvalidFilename
|
226
|
-
end
|
227
|
-
|
228
|
-
it 'fails given filename with no season number' do
|
229
|
-
expect{ Addic7ed::Filename.new(@filename_no_season) }.to raise_error Addic7ed::InvalidFilename
|
230
|
-
end
|
231
|
-
|
232
|
-
it 'raises InvalidFilename given filename with no episode number' do
|
233
|
-
expect{ Addic7ed::Filename.new(@filename_no_episode) }.to raise_error Addic7ed::InvalidFilename
|
234
|
-
end
|
235
|
-
|
236
|
-
it 'raises InvalidFilename given filename with no tags' do
|
237
|
-
expect{ Addic7ed::Filename.new(@filename_no_tags) }.to raise_error Addic7ed::InvalidFilename
|
238
|
-
end
|
239
|
-
|
240
|
-
it 'raises InvalidFilename given filename with no group' do
|
241
|
-
expect{ Addic7ed::Filename.new(@filename_no_group) }.to raise_error Addic7ed::InvalidFilename
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
describe '#encoded_filename' do
|
246
|
-
it 'changes all spaces to underscores' do
|
247
|
-
expect(Addic7ed::Filename.new(@filename_multiple_words).encoded_showname).to eq 'The_Walking_Dead'
|
248
|
-
end
|
249
|
-
|
250
|
-
it 'wraps country code with parenthesis' do
|
251
|
-
expect(Addic7ed::Filename.new(@filename_showname_US).encoded_showname).to eq 'Shameless_(US)'
|
252
|
-
end
|
253
|
-
|
254
|
-
it 'detects country code even in lowercase' do
|
255
|
-
expect(Addic7ed::Filename.new(@filename_showname_US_lowercase).encoded_showname).to eq 'shameless_(us)'
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'removes country code for the original show (usually UK)' do
|
259
|
-
expect(Addic7ed::Filename.new(@filename_showname_UK).encoded_showname).to eq 'Shameless'
|
260
|
-
end
|
261
|
-
|
262
|
-
it 'removes production year' do
|
263
|
-
expect(Addic7ed::Filename.new(@filename_showname_year).encoded_showname).to eq 'The_Americans'
|
264
|
-
end
|
265
|
-
|
266
|
-
it 'handles when both country code and production year are present' do
|
267
|
-
expect(Addic7ed::Filename.new(@filename_showname_UK_year).encoded_showname).to eq 'The_Hour'
|
268
|
-
expect(Addic7ed::Filename.new(@filename_showname_year_UK).encoded_showname).to eq 'The_Hour'
|
269
|
-
expect(Addic7ed::Filename.new(@filename_showname_US_year).encoded_showname).to eq 'The_Hour_(US)'
|
270
|
-
expect(Addic7ed::Filename.new(@filename_showname_year_US).encoded_showname).to eq 'The_Hour_(US)'
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
describe '#basename' do
|
275
|
-
it 'returns only file name given a full path' do
|
276
|
-
expect(Addic7ed::Filename.new(@filename_full_path).basename).to eq 'Californication.S06E07.720p.HDTV.x264-2HD.mkv'
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
describe '#dirname' do
|
281
|
-
it 'returns only path given a full path' do
|
282
|
-
expect(Addic7ed::Filename.new(@filename_full_path).dirname).to eq '/data/public/Series/Californication/Saison 06'
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
describe '#extname' do
|
287
|
-
it 'returns only file extension given a full path' do
|
288
|
-
expect(Addic7ed::Filename.new(@filename_full_path).extname).to eq '.mkv'
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
describe '#to_s' do
|
293
|
-
it 'returns file name as a string' do
|
294
|
-
expect(Addic7ed::Filename.new(@filename_full_path).to_s).to eq '/data/public/Series/Californication/Saison 06/Californication.S06E07.720p.HDTV.x264-2HD.mkv'
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
describe '#inspect' do
|
299
|
-
it 'prints a human-readable detailed version' do
|
300
|
-
expect(Addic7ed::Filename.new(@filename).inspect).to eq(
|
301
|
-
'Guesses for Californication.S06E07.720p.HDTV.x264-2HD.mkv:
|
302
|
-
show: Californication
|
303
|
-
season: 6
|
304
|
-
episode: 7
|
305
|
-
tags: ["720P", "HDTV", "X264"]
|
306
|
-
group: 2HD')
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
@@ -1,155 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require './lib/addic7ed'
|
3
|
-
|
4
|
-
describe Addic7ed::Subtitle do
|
5
|
-
describe '#normalized_version' do
|
6
|
-
it 'upcases the version string' do
|
7
|
-
expect(Addic7ed::Subtitle.new('DiMENSiON', '', '', '', '', '0').version).to eq 'DIMENSION'
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'removes heading and trailing dots' do
|
11
|
-
expect(Addic7ed::Subtitle.new('.DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
12
|
-
expect(Addic7ed::Subtitle.new('DIMENSION.', '', '', '', '', '0').version).to eq 'DIMENSION'
|
13
|
-
expect(Addic7ed::Subtitle.new('.DIMENSION.', '', '', '', '', '0').version).to eq 'DIMENSION'
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'removes heading and trailing whitespaces' do
|
17
|
-
expect(Addic7ed::Subtitle.new(' DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
18
|
-
expect(Addic7ed::Subtitle.new('DIMENSION ', '', '', '', '', '0').version).to eq 'DIMENSION'
|
19
|
-
expect(Addic7ed::Subtitle.new(' DIMENSION ', '', '', '', '', '0').version).to eq 'DIMENSION'
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'removes heading and trailing dashes' do
|
23
|
-
expect(Addic7ed::Subtitle.new('-DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
24
|
-
expect(Addic7ed::Subtitle.new('DIMENSION-', '', '', '', '', '0').version).to eq 'DIMENSION'
|
25
|
-
expect(Addic7ed::Subtitle.new('-DIMENSION-', '', '', '', '', '0').version).to eq 'DIMENSION'
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'automatically removes "720p" in version string' do
|
29
|
-
expect(Addic7ed::Subtitle.new('720p DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
30
|
-
expect(Addic7ed::Subtitle.new('720P DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
31
|
-
expect(Addic7ed::Subtitle.new('DIMENSION 720p', '', '', '', '', '0').version).to eq 'DIMENSION'
|
32
|
-
expect(Addic7ed::Subtitle.new('DIMENSION 720P', '', '', '', '', '0').version).to eq 'DIMENSION'
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'automatically removes "HDTV" in version string' do
|
36
|
-
expect(Addic7ed::Subtitle.new('hdtv DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
37
|
-
expect(Addic7ed::Subtitle.new('HDTV DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
38
|
-
expect(Addic7ed::Subtitle.new('DIMENSION hdtv', '', '', '', '', '0').version).to eq 'DIMENSION'
|
39
|
-
expect(Addic7ed::Subtitle.new('DIMENSION HDTV', '', '', '', '', '0').version).to eq 'DIMENSION'
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'automatically removes "x264" in version string' do
|
43
|
-
expect(Addic7ed::Subtitle.new('x264 DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
44
|
-
expect(Addic7ed::Subtitle.new('X264 DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
45
|
-
expect(Addic7ed::Subtitle.new('x.264 DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
46
|
-
expect(Addic7ed::Subtitle.new('X.264 DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
47
|
-
expect(Addic7ed::Subtitle.new('DIMENSION x264', '', '', '', '', '0').version).to eq 'DIMENSION'
|
48
|
-
expect(Addic7ed::Subtitle.new('DIMENSION X264', '', '', '', '', '0').version).to eq 'DIMENSION'
|
49
|
-
expect(Addic7ed::Subtitle.new('DIMENSION x.264', '', '', '', '', '0').version).to eq 'DIMENSION'
|
50
|
-
expect(Addic7ed::Subtitle.new('DIMENSION X.264', '', '', '', '', '0').version).to eq 'DIMENSION'
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'automatically removes "PROPER" in version string' do
|
54
|
-
expect(Addic7ed::Subtitle.new('PROPER DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
55
|
-
expect(Addic7ed::Subtitle.new('Proper DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
56
|
-
expect(Addic7ed::Subtitle.new('DIMENSION PROPER', '', '', '', '', '0').version).to eq 'DIMENSION'
|
57
|
-
expect(Addic7ed::Subtitle.new('DIMENSION Proper', '', '', '', '', '0').version).to eq 'DIMENSION'
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'automatically removes "RERIP" in version string' do
|
61
|
-
expect(Addic7ed::Subtitle.new('RERIP DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
62
|
-
expect(Addic7ed::Subtitle.new('Rerip DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
63
|
-
expect(Addic7ed::Subtitle.new('DIMENSION RERIP', '', '', '', '', '0').version).to eq 'DIMENSION'
|
64
|
-
expect(Addic7ed::Subtitle.new('DIMENSION Rerip', '', '', '', '', '0').version).to eq 'DIMENSION'
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'automatically removes "Version" prefix in version string' do
|
68
|
-
expect(Addic7ed::Subtitle.new('Version DIMENSION', '', '', '', '', '0').version).to eq 'DIMENSION'
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
describe '#to_s' do
|
73
|
-
it 'prints a human readable version' do
|
74
|
-
sub = Addic7ed::Subtitle.new('DIMENSION', 'fr', 'Completed', 'http://some.fancy.url', 'http://addic7ed.com', '42')
|
75
|
-
expect(sub.to_s).to eq "http://some.fancy.url\t->\tDIMENSION (fr, Completed) [42 downloads] (via http://addic7ed.com)"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe '#works_for?' do
|
80
|
-
context 'when incomplete' do
|
81
|
-
before(:all) { @sub = Addic7ed::Subtitle.new('', '', '80%', '', '', '10') }
|
82
|
-
|
83
|
-
it 'returns false' do
|
84
|
-
expect(@sub.works_for?).to be false
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
context 'when completed' do
|
89
|
-
before(:all) { @sub = Addic7ed::Subtitle.new('DIMENSION', '', 'Completed', '', '', '10') }
|
90
|
-
|
91
|
-
it 'returns true given the exact same version' do
|
92
|
-
expect(@sub.works_for? 'DIMENSION').to be true
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'returns true given a compatible version' do
|
96
|
-
expect(@sub.works_for? 'LOL').to be true
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'returns true when the subtitle is for a PROPER version' do
|
100
|
-
sub = Addic7ed::Subtitle.new('PROPER DIMENSION', '', 'Completed', '', '', '10')
|
101
|
-
expect(sub.works_for? 'DIMENSION').to be true
|
102
|
-
expect(sub.works_for? 'LOL').to be true
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'returns false given an incompatible version' do
|
106
|
-
expect(@sub.works_for? 'EVOLVE').to be false
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
describe '#can_replace?' do
|
112
|
-
context 'when incomplete' do
|
113
|
-
it 'returns false' do
|
114
|
-
sub = Addic7ed::Subtitle.new('', '', '80%', '', '', '10')
|
115
|
-
any_other_sub = Addic7ed::Subtitle.new('', '', '', '', '', '0')
|
116
|
-
expect(sub.can_replace? any_other_sub).to be false
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
context 'when completed' do
|
121
|
-
before(:all) { @sub = Addic7ed::Subtitle.new('DIMENSION', 'fr', 'Completed', '', '', '10') }
|
122
|
-
|
123
|
-
it 'returns true given no other_sub' do
|
124
|
-
expect(@sub.can_replace? nil).to be true
|
125
|
-
end
|
126
|
-
|
127
|
-
it 'returns false given other_sub for another language' do
|
128
|
-
other_sub = Addic7ed::Subtitle.new('DIMENSION', 'en', 'Completed', '', '', '10')
|
129
|
-
expect(@sub.can_replace? other_sub).to be false
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'returns false given other_sub for incompatible version' do
|
133
|
-
other_sub = Addic7ed::Subtitle.new('EVOLVE', 'fr', 'Completed', '', '', '10')
|
134
|
-
expect(@sub.can_replace? other_sub).to be false
|
135
|
-
end
|
136
|
-
|
137
|
-
context 'given other_sub language & version compatible' do
|
138
|
-
it 'returns false given other_sub featured by Addic7ed' do
|
139
|
-
other_sub = Addic7ed::Subtitle.new('DIMENSION', 'fr', 'Completed', '', 'http://addic7ed.com', '10')
|
140
|
-
expect(@sub.can_replace? other_sub).to be false
|
141
|
-
end
|
142
|
-
|
143
|
-
it 'returns false given other_sub with more downloads' do
|
144
|
-
other_sub = Addic7ed::Subtitle.new('DIMENSION', 'fr', 'Completed', '', '', '20')
|
145
|
-
expect(@sub.can_replace? other_sub).to be false
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'returns true given other_sub with less downloads' do
|
149
|
-
other_sub = Addic7ed::Subtitle.new('DIMENSION', 'fr', 'Completed', '', '', '5')
|
150
|
-
expect(@sub.can_replace? other_sub).to be true
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|