addic7ed 3.0.0 → 4.0.0.pre.beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|