addic7ed 3.0.0 → 4.0.0.pre.beta.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/addic7ed.rb +5 -10
- data/lib/addic7ed/common.rb +13 -1285
- data/lib/addic7ed/config.json +1417 -0
- data/lib/addic7ed/errors.rb +8 -7
- data/lib/addic7ed/models/episode.rb +112 -0
- data/lib/addic7ed/models/search.rb +90 -0
- data/lib/addic7ed/models/subtitle.rb +109 -0
- data/lib/addic7ed/models/subtitles_collection.rb +63 -0
- data/lib/addic7ed/models/video_file.rb +147 -0
- data/lib/addic7ed/service.rb +13 -0
- data/lib/addic7ed/services/check_compatibility.rb +44 -0
- data/lib/addic7ed/services/download_subtitle.rb +53 -0
- data/lib/addic7ed/services/get_shows_list.rb +29 -0
- data/lib/addic7ed/services/{addic7ed_comment_normalizer.rb → normalize_comment.rb} +4 -8
- data/lib/addic7ed/services/normalize_version.rb +22 -0
- data/lib/addic7ed/services/parse_page.rb +43 -0
- data/lib/addic7ed/services/parse_subtitle.rb +79 -0
- data/lib/addic7ed/services/url_encode_show_name.rb +46 -0
- data/lib/addic7ed/version.rb +1 -1
- metadata +63 -50
- data/bin/addic7ed +0 -144
- data/lib/addic7ed/episode.rb +0 -95
- data/lib/addic7ed/parser.rb +0 -105
- data/lib/addic7ed/services/addic7ed_version_normalizer.rb +0 -24
- data/lib/addic7ed/show_list.rb +0 -61
- data/lib/addic7ed/subtitle.rb +0 -72
- data/lib/addic7ed/video_file.rb +0 -41
- data/spec/lib/addic7ed/common_spec.rb +0 -21
- data/spec/lib/addic7ed/episode_spec.rb +0 -165
- data/spec/lib/addic7ed/services/addic7ed_comment_normalizer_spec.rb +0 -12
- data/spec/lib/addic7ed/services/addic7ed_version_normalizer_spec.rb +0 -73
- data/spec/lib/addic7ed/show_list_spec.rb +0 -42
- data/spec/lib/addic7ed/subtitle_spec.rb +0 -182
- data/spec/lib/addic7ed/video_file_spec.rb +0 -159
- data/spec/responses/basic_redirection.http +0 -13
- data/spec/responses/homepage.http +0 -921
- data/spec/responses/redirection_loop.http +0 -12
- data/spec/responses/walking-dead-3-2-1.http +0 -770
- data/spec/responses/walking-dead-3-2-48.http +0 -2117
- data/spec/responses/walking-dead-3-2-7.http +0 -659
- data/spec/responses/walking-dead-3-2-8.http +0 -815
- data/spec/responses/walking-dead-3-2-8_best_subtitle.http +0 -1928
- data/spec/responses/walking-dead-3-4-8.http +0 -732
- data/spec/responses/walking-dead-3-42-8.http +0 -13
- data/spec/spec_helper.rb +0 -26
data/lib/addic7ed/errors.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module Addic7ed
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
2
|
+
class InvalidFilename < StandardError; end
|
3
|
+
class ShowNotFound < StandardError; end
|
4
|
+
class EpisodeNotFound < StandardError; end
|
5
|
+
class LanguageNotSupported < StandardError; end
|
6
|
+
class ParsingError < StandardError; end
|
7
|
+
class NoSubtitleFound < StandardError; end
|
8
|
+
class DownloadError < StandardError; end
|
9
|
+
class DailyLimitExceeded < DownloadError; end
|
9
10
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "open-uri"
|
3
|
+
|
4
|
+
module Addic7ed
|
5
|
+
# Represents a TV show episode.
|
6
|
+
#
|
7
|
+
# @attr showname [String] TV show name.
|
8
|
+
# @attr season [Numeric] Season number.
|
9
|
+
# @attr episode [Numeric] Episode number in the season.
|
10
|
+
|
11
|
+
class Episode
|
12
|
+
attr_reader :showname, :season, :episode
|
13
|
+
|
14
|
+
# Creates a new instance of {Episode}.
|
15
|
+
#
|
16
|
+
# @param showname [String] TV show name, as extracted from the video file name
|
17
|
+
# (_e.g._ both +"Game.of.Thrones"+ and +"Game of Thrones"+ are valid)
|
18
|
+
# @param season [Numeric] Season number
|
19
|
+
# @param episode [Numeric] Episode number in the season
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# Addic7ed::Episode.new("Game of Thrones", 6, 9)
|
23
|
+
# #=> #<Addic7ed::Episode
|
24
|
+
# # @episode=9,
|
25
|
+
# # @season=6,
|
26
|
+
# # @showname="Game.of.Thrones",
|
27
|
+
# # @subtitles={:fr=>nil, :ar=>nil, :az=>nil, ..., :th=>nil, :tr=>nil, :vi=>nil}
|
28
|
+
# # >
|
29
|
+
|
30
|
+
def initialize(showname, season, episode)
|
31
|
+
@showname = showname
|
32
|
+
@season = season
|
33
|
+
@episode = episode
|
34
|
+
@subtitles = languages_hash { |code, _| { code => nil } }
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns a list of all available {Subtitle}s for this {Episode} in the given +language+.
|
38
|
+
#
|
39
|
+
# @param language [String] Language code we want returned {Subtitle}s to be in.
|
40
|
+
#
|
41
|
+
# @return [Array<Subtitle>] List of {Subtitle}s available on Addic7ed for the given +language+.
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# Addic7ed::Episode.new("Game.of.Thrones", 3, 9).subtitles(:fr)
|
45
|
+
# #=> [
|
46
|
+
# # #<Addic7ed::Subtitle
|
47
|
+
# # @comment="works with ctrlhd",
|
48
|
+
# # @downloads=28130,
|
49
|
+
# # @hi=false,
|
50
|
+
# # @language="French",
|
51
|
+
# # @source="http://addic7ed.com",
|
52
|
+
# # @status="Completed",
|
53
|
+
# # @url="http://www.addic7ed.com/updated/8/76081/0",
|
54
|
+
# # @version="EVOLVE">,
|
55
|
+
# # #<Addic7ed::Subtitle
|
56
|
+
# # @comment="la fabrique",
|
57
|
+
# # @downloads=1515,
|
58
|
+
# # @hi=false,
|
59
|
+
# # @language="French",
|
60
|
+
# # @source="http://sous-titres.eu",
|
61
|
+
# # @status="Completed",
|
62
|
+
# # @url="http://www.addic7ed.com/original/76081/11",
|
63
|
+
# # @version="EVOLVE">,
|
64
|
+
# # #<Addic7ed::Subtitle
|
65
|
+
# # @comment="la fabrique",
|
66
|
+
# # @downloads=917,
|
67
|
+
# # @hi=false,
|
68
|
+
# # @language="French",
|
69
|
+
# # @source="http://sous-titres.eu",
|
70
|
+
# # @status="Completed",
|
71
|
+
# # @url="http://www.addic7ed.com/original/76081/12",
|
72
|
+
# # @version="WEB,DL,NTB,&,YFN">
|
73
|
+
# # ]
|
74
|
+
|
75
|
+
def subtitles(language)
|
76
|
+
@subtitles[language] ||= Addic7ed::ParsePage.call(page_url(language))
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns the URL of the Addic7ed webpage listing subtitles for this {Episode}
|
80
|
+
# in the given +language+.
|
81
|
+
#
|
82
|
+
# @param language [String] Language code we want the webpage to list subtitles in.
|
83
|
+
#
|
84
|
+
# @return [String] Fully qualified URL of the webpage on Addic7ed.
|
85
|
+
#
|
86
|
+
# @example
|
87
|
+
# Addic7ed::Episode.new("Game of Thrones", 6, 9).page_url
|
88
|
+
# #=> "http://www.addic7ed.com/serie/Game_of_Thrones/6/9/8"
|
89
|
+
|
90
|
+
def page_url(language)
|
91
|
+
localized_urls[language]
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def localized_urls
|
97
|
+
@localized_urls ||= languages_hash { |code, lang| { code => localized_url(lang[:id]) } }
|
98
|
+
end
|
99
|
+
|
100
|
+
def url_encoded_showname
|
101
|
+
@url_encoded_showname ||= URLEncodeShowName.call(showname)
|
102
|
+
end
|
103
|
+
|
104
|
+
def localized_url(lang)
|
105
|
+
"http://www.addic7ed.com/serie/#{url_encoded_showname}/#{season}/#{episode}/#{lang}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def languages_hash(&block)
|
109
|
+
Hash.new { raise LanguageNotSupported }.merge(LANGUAGES.map(&block).reduce(&:merge))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Addic7ed
|
2
|
+
# Represents a subtitle search for a +video_filename+ in a +language+ with
|
3
|
+
# multiple search +criterias+.
|
4
|
+
#
|
5
|
+
# @attr video_filename [String] Video file name we're searching subtitles for.
|
6
|
+
# @attr language [String] ISO code of language (_e.g._ "en", "fr", "es").
|
7
|
+
# @attr criterias [Hash] List of search criterias as a {Hash}.
|
8
|
+
|
9
|
+
class Search
|
10
|
+
attr_reader :video_filename, :language, :criterias
|
11
|
+
|
12
|
+
# Creates a new instance of {Search}.
|
13
|
+
#
|
14
|
+
# Currently supported search criterias are:
|
15
|
+
# * +no_hi+: do not include hearing impaired subtitles (defaults to +false+)
|
16
|
+
#
|
17
|
+
# @param video_filename [String] Path to the video file for which we search subtitles
|
18
|
+
# (either relative or absolute path)
|
19
|
+
# @param language [String] ISO code of target subtitles language
|
20
|
+
# @param criterias [Hash] List of search criterias the subtitles must match
|
21
|
+
# (will be merged with default criterias as described above)
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# Addic7ed::Search.new("Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv", :fr)
|
25
|
+
# #=> #<Addic7ed::Search
|
26
|
+
# # @criterias={:no_hi=>false},
|
27
|
+
# # @language=:fr,
|
28
|
+
# # @video_filename="Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv"
|
29
|
+
# # >
|
30
|
+
|
31
|
+
def initialize(video_filename, language, criterias = {})
|
32
|
+
@video_filename = video_filename
|
33
|
+
@language = language
|
34
|
+
@criterias = default_criterias.merge(criterias)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the {VideoFile} object representing the video file we're searching subtitles for.
|
38
|
+
#
|
39
|
+
# @return [VideoFile] the {VideoFile} associated with this {Search}
|
40
|
+
|
41
|
+
def video_file
|
42
|
+
@video_file ||= VideoFile.new(video_filename)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the {Episode} object we're searching subtitles for.
|
46
|
+
#
|
47
|
+
# @return [Episode] the {Episode} associated with this {Search}
|
48
|
+
|
49
|
+
def episode
|
50
|
+
@episode ||= Episode.new(video_file.showname, video_file.season, video_file.episode)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the list of all available subtitles for this search,
|
54
|
+
# regardless of completeness, compatibility or search +criterias+.
|
55
|
+
#
|
56
|
+
# @return [SubtitlesCollection] all subtitles for the searched episode
|
57
|
+
|
58
|
+
def all_subtitles
|
59
|
+
@all_subtitles ||= SubtitlesCollection.new(episode.subtitles(language))
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the list of subtitles completed and compatible with the episode we're searching
|
63
|
+
# subtitles for, regardless of search +criterias+.
|
64
|
+
#
|
65
|
+
# @return [SubtitlesCollection] subtitles completed and compatible with the searched episode
|
66
|
+
|
67
|
+
def matching_subtitles
|
68
|
+
@matching_subtitles ||= all_subtitles.completed.compatible_with(video_file.group)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the best subtitle for the episode we're searching subtitles for.
|
72
|
+
#
|
73
|
+
# The best subtitle means the more popular (_i.e._ most downloaded) subtitle among completed,
|
74
|
+
# compatible subtitles for the episode we're searching subtitles for.
|
75
|
+
#
|
76
|
+
# @return [SubtitlesCollection] subtitles completed and compatible with the searched episode
|
77
|
+
|
78
|
+
def best_subtitle
|
79
|
+
@best_subtitle ||= matching_subtitles.most_popular
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def default_criterias
|
85
|
+
{
|
86
|
+
no_hi: false
|
87
|
+
}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Addic7ed
|
2
|
+
# Represents a subtitle on Addic7ed.
|
3
|
+
#
|
4
|
+
# This model contains as much information as possible for a subtitle
|
5
|
+
# as parsed on Addic7ed website.
|
6
|
+
#
|
7
|
+
# @attr version [String] Main compatible release group(s)
|
8
|
+
# (evenually as a comma-separated list).
|
9
|
+
# @attr language [String] Language the subtitle is written in
|
10
|
+
# (_e.g._: "French", "English").
|
11
|
+
# @attr status [String] Translation/synchronization advancement status
|
12
|
+
# (_e.g._: "60%"" or "Completed").
|
13
|
+
# @attr source [String] URL of website the subtitle was first published on.
|
14
|
+
# @attr downloads [Numeric] Number of times this subtitle has been downloaded.
|
15
|
+
# @attr comment [String] Comment manually added by the subtitle author/publisher
|
16
|
+
# (usually related to extra-compatibilities or resync source).
|
17
|
+
# @attr hi [Boolean] Hearing-impaired support.
|
18
|
+
# @attr url [String] Download URL of actual subtitle file (warning: Addic7ed servers
|
19
|
+
# won't serve a subtite file without a proper +Referer+ HTTP header which can be
|
20
|
+
# retrieved from +episode.page_url+).
|
21
|
+
|
22
|
+
class Subtitle
|
23
|
+
attr_reader :version, :language, :status, :source, :downloads, :comment, :hi
|
24
|
+
attr_accessor :url
|
25
|
+
|
26
|
+
# Creates a new instance of {Subtitle} created using +options+,
|
27
|
+
# usually from data parsed from an Addic7ed page.
|
28
|
+
#
|
29
|
+
# The +options+ hash can have the following keys as symbols:
|
30
|
+
# * +version+: main compatible release group(s) as parsed on the Addic7ed website
|
31
|
+
# * +language+: language full name
|
32
|
+
# * +status+: full-text advancement status
|
33
|
+
# * +source+: URL of website the subtitle was originally published on
|
34
|
+
# * +downloads+: number of times the subtitle has been downloaded
|
35
|
+
# * +comment+: manually added comment from the author or publisher
|
36
|
+
# * +hi+: hearing-impaired support
|
37
|
+
# * +url+: download URL for the subtitle file
|
38
|
+
#
|
39
|
+
# @param options [Hash] subtitle information as a {Hash}
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# Addic7ed::Subtitle.new(
|
43
|
+
# version: "Version KILLERS, 720p AVS, 0.00 MBs",
|
44
|
+
# language: "French",
|
45
|
+
# status: "Completed",
|
46
|
+
# source: "http://sous-titres.eu",
|
47
|
+
# downloads: 10335,
|
48
|
+
# comment: "works with 1080p.BATV",
|
49
|
+
# hi: false,
|
50
|
+
# url: "http://www.addic7ed.com/original/113643/4"
|
51
|
+
# )
|
52
|
+
# #=> #<Addic7ed::Subtitle
|
53
|
+
# # @version="KILLERS,AVS",
|
54
|
+
# # @language="French"
|
55
|
+
# # @status="Completed"
|
56
|
+
# # @url="http://www.addic7ed.com/original/113643/4"
|
57
|
+
# # @source="http://sous-titres.eu"
|
58
|
+
# # @hi=false
|
59
|
+
# # @downloads=10335
|
60
|
+
# # @comment="works with 1080p.batv"
|
61
|
+
# # >
|
62
|
+
|
63
|
+
def initialize(options = {})
|
64
|
+
@version = NormalizeVersion.call(options[:version])
|
65
|
+
@language = options[:language]
|
66
|
+
@status = options[:status]
|
67
|
+
@url = options[:url]
|
68
|
+
@source = options[:source]
|
69
|
+
@hi = options[:hi]
|
70
|
+
@downloads = options[:downloads].to_i || 0
|
71
|
+
@comment = NormalizeComment.call(options[:comment])
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns a human-friendly readable string representing the {Subtitle}
|
75
|
+
#
|
76
|
+
# TODO: move to the CLI codebase
|
77
|
+
#
|
78
|
+
# @return [String]
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# Addic7ed::Subtitle.new(
|
82
|
+
# version: "Version 720p AVS, 0.00 MBs",
|
83
|
+
# language: "French",
|
84
|
+
# status: "Completed",
|
85
|
+
# downloads: 42,
|
86
|
+
# url: "http://www.addic7ed.com/original/113643/4"
|
87
|
+
# ).to_s
|
88
|
+
# #=> "http://www.addic7ed.com/original/113643/4\t->\tAVS (French, Completed) [42 downloads]"
|
89
|
+
|
90
|
+
def to_s
|
91
|
+
str = "#{url}\t->\t#{version} (#{language}, #{status}) [#{downloads} downloads]"
|
92
|
+
str += " (source #{source})" if source
|
93
|
+
str
|
94
|
+
end
|
95
|
+
|
96
|
+
# Completeness status of the {Subtitle}.
|
97
|
+
#
|
98
|
+
# @return [Boolean] Returns +true+ if {Subtitle} is complete,
|
99
|
+
# +false+ otherwise (partially complete)
|
100
|
+
#
|
101
|
+
# @example
|
102
|
+
# Addic7ed::Subtitle.new(status: "50%").completed? #=> false
|
103
|
+
# Addic7ed::Subtitle.new(status: "Completed").completed? #=> true
|
104
|
+
|
105
|
+
def completed?
|
106
|
+
status == "Completed"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Addic7ed
|
2
|
+
# Represents a collection of {Subtitle} objects.
|
3
|
+
#
|
4
|
+
# This collection inherits from {Array} so it behaves exaclty like it,
|
5
|
+
# but it also provides some methods to filter, order and choose the best subtitle.
|
6
|
+
class SubtitlesCollection < Array
|
7
|
+
# Returns only subtitles that are compatible with +group+.
|
8
|
+
# @param group [String] Release group we want the returned subtitles to be compatible with
|
9
|
+
#
|
10
|
+
# @return [SubtitleCollection] Copy of collection with subtitles compatible with +group+ only
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# fov = Addic7ed::Subtitle.new(version: "FOV")
|
14
|
+
# lol = Addic7ed::Subtitle.new(version: "LOL")
|
15
|
+
# dimension = Addic7ed::Subtitle.new(version: "DIMENSION")
|
16
|
+
# collection = Addic7ed::SubtitlesCollection.new([fov, lol, dimension])
|
17
|
+
#
|
18
|
+
# collection.compatible_with("DIMENSION")
|
19
|
+
# #=> [#<Addic7ed::Subtitle @version="LOL">, #<Addic7ed::Subtitle @version="DIMENSION">]
|
20
|
+
|
21
|
+
def compatible_with(group)
|
22
|
+
select { |subtitle| CheckCompatibility.call(subtitle, group) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns only completed subtitles.
|
26
|
+
#
|
27
|
+
# @return [SubtitleCollection] Copy of collection with completed subtitles only
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# complete = Addic7ed::Subtitle.new(status: "Completed")
|
31
|
+
# wip = Addic7ed::Subtitle.new(status: "50%")
|
32
|
+
# collection = Addic7ed::SubtitlesCollection.new([complete, wip])
|
33
|
+
#
|
34
|
+
# collection.completed
|
35
|
+
# #=> [#<Addic7ed::Subtitle @status="Completed">]
|
36
|
+
|
37
|
+
def completed
|
38
|
+
select(&:completed?)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the most downloaded subtitle.
|
42
|
+
#
|
43
|
+
# @return [Subtitle] Subtitle of the collection with the more downloads
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# popular = Addic7ed::Subtitle.new(downloads: 1000)
|
47
|
+
# unpopular = Addic7ed::Subtitle.new(downloads: 3)
|
48
|
+
# collection = Addic7ed::SubtitlesCollection.new([popular, unpopular])
|
49
|
+
#
|
50
|
+
# collection.most_popular
|
51
|
+
# #=> #<Addic7ed::Subtitle @downloads=1000>
|
52
|
+
|
53
|
+
def most_popular
|
54
|
+
sort_by(&:downloads).last
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def select
|
60
|
+
SubtitlesCollection.new(super)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module Addic7ed
|
2
|
+
# Represents the video file you're looking a subtitle for.
|
3
|
+
#
|
4
|
+
# This class will extract from the video file name the show name, season, episode, group, etc.
|
5
|
+
#
|
6
|
+
# It expects the file to be named according to The Scene rules,
|
7
|
+
# but actually supports a wide variety of common naming schemes.
|
8
|
+
class VideoFile
|
9
|
+
# @!visibility private
|
10
|
+
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 # rubocop:disable Metrics/LineLength
|
11
|
+
|
12
|
+
# @!visibility private
|
13
|
+
attr_reader :filename, :regexp_matches
|
14
|
+
|
15
|
+
# Returns a new instance of {VideoFile}.
|
16
|
+
# It expects a video file name, either with or without path and
|
17
|
+
# either absolute or relative.
|
18
|
+
#
|
19
|
+
# @param filename [String] File name of the video file on disk
|
20
|
+
# (either relative or absolute).
|
21
|
+
#
|
22
|
+
# @return [String] Distribution group name
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Addic7ed::VideoFile.new("Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
26
|
+
# Addic7ed::VideoFile.new("/home/mike/Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
27
|
+
# Addic7ed::VideoFile.new("../Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
28
|
+
|
29
|
+
def initialize(filename)
|
30
|
+
@filename = filename
|
31
|
+
@regexp_matches = TVSHOW_REGEX.match(basename)
|
32
|
+
raise InvalidFilename if regexp_matches.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the TV show name extracted from the file name.
|
36
|
+
#
|
37
|
+
# @return [String] TV show name
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# video_file = Addic7ed::VideoFile.new("Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
41
|
+
# video_file.showname #=> "Game.of.Thrones"
|
42
|
+
|
43
|
+
def showname
|
44
|
+
@showname ||= regexp_matches[:showname]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the TV show season number extracted from the file name.
|
48
|
+
#
|
49
|
+
# @return [Integer] TV show season number
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
# video_file = Addic7ed::VideoFile.new("Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
53
|
+
# video_file.season #=> 6
|
54
|
+
|
55
|
+
def season
|
56
|
+
@season ||= regexp_matches[:season].to_i
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the TV show episode number extracted from the file name.
|
60
|
+
#
|
61
|
+
# @return [Integer] TV show episode number
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# video_file = Addic7ed::VideoFile.new("Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
65
|
+
# video_file.episode #=> 9
|
66
|
+
|
67
|
+
def episode
|
68
|
+
@episode ||= regexp_matches[:episode].to_i
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the upcased release tags extracted from the file name
|
72
|
+
# (like +HDTV+, +720P+, +XviD+, +PROPER+, ...).
|
73
|
+
#
|
74
|
+
# @return [Array<String>] Release video, audio or packaging tags
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# video_file = Addic7ed::VideoFile.new("Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
78
|
+
# video_file.tags #=> ["720P", "HDTV", "X264"]
|
79
|
+
|
80
|
+
def tags
|
81
|
+
@tags ||= regexp_matches[:tags].upcase.split(/[\. ]/)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the upcased release group extracted from the file name.
|
85
|
+
#
|
86
|
+
# @return [String] Release group name
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# video_file = Addic7ed::VideoFile.new("Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
90
|
+
# video_file.group #=> "AVS"
|
91
|
+
|
92
|
+
def group
|
93
|
+
@group ||= regexp_matches[:group].upcase
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the upcased distribution group extracted from the file name.
|
97
|
+
#
|
98
|
+
# @return [String] Distribution group name
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# video_file = Addic7ed::VideoFile.new("Game.of.Thrones.S06E09.720p.HDTV.x264-AVS[eztv].mkv")
|
102
|
+
# video_file.distribution #=> "EZTV"
|
103
|
+
|
104
|
+
def distribution
|
105
|
+
@distribution ||= regexp_matches[:distribution].upcase
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns the base file name (without path).
|
109
|
+
#
|
110
|
+
# @return [String] Base file name
|
111
|
+
#
|
112
|
+
# @example
|
113
|
+
# video_file = Addic7ed::VideoFile.new("../Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
114
|
+
# video_file.basename #=> "Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv"
|
115
|
+
|
116
|
+
def basename
|
117
|
+
@basename ||= File.basename(filename)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns the video file name as passed to {#initialize}.
|
121
|
+
#
|
122
|
+
# @return [String] File name
|
123
|
+
#
|
124
|
+
# @example
|
125
|
+
# video_file = Addic7ed::VideoFile.new("../Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv")
|
126
|
+
# video_file.to_s #=> "../Game.of.Thrones.S06E09.720p.HDTV.x264-AVS.mkv"
|
127
|
+
|
128
|
+
def to_s
|
129
|
+
filename
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns a multiline, human-readable breakdown of the file name
|
133
|
+
# including all detected attributes (show name, season, episode, tags, ...).
|
134
|
+
#
|
135
|
+
# @return [String] a human-readable breakdown of the file name
|
136
|
+
|
137
|
+
def inspect
|
138
|
+
"Guesses for #{filename}:\n" \
|
139
|
+
" show: #{showname}\n" \
|
140
|
+
" season: #{season}\n" \
|
141
|
+
" episode: #{episode}\n" \
|
142
|
+
" tags: #{tags}\n" \
|
143
|
+
" group: #{group}\n" \
|
144
|
+
" distribution: #{distribution}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|