autosub 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ pkg
23
+ doc
24
+ tasks
25
+ test
26
+ rep
27
+ fixtures
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Pirate
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,38 @@
1
+ # AutoSub
2
+
3
+ Ruby tool to automatically download subtitles (srt) inside your TV Shows folder.
4
+ Currently only english and french subtitles are supported.
5
+
6
+ ## Install
7
+
8
+ sudo gem install pirate-autosub --source http://gems.github.com
9
+
10
+ ## Usage
11
+
12
+ In your terminal:
13
+
14
+ autosub -p /path/of/your/TV Shows/folder -lang fr,en
15
+
16
+ more details with:
17
+
18
+ autosub -h
19
+
20
+ ## Folder Name Convention
21
+
22
+ AutoNZB use (and needs) specific folders/episodes name for your TV Shows:
23
+
24
+ + TV Shows
25
+ + Dexter (TV Show's name needs to be 'clean')
26
+ + Season 01
27
+ - Dexter S01E01.mkv (.mkv for 720p HD episode)
28
+ - Dexter 1x02.avi (.avi for SD episode)
29
+ - S01E03.mkv (TV Show's name in episode file's name not needed)
30
+ - S01E03.fr.srt (.fr.srt used to define subtitle's language)
31
+ + Fringe
32
+ - (season folder not needed)
33
+ - Fringe S01E01.mkv
34
+ - 1x01.avi
35
+
36
+ ## Copyright
37
+
38
+ Copyright (c) 2009 Pirate
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "autosub"
8
+ gem.summary = "Automatically download srt for your TV Shows"
9
+ gem.description = "Ruby tool to automatically download subtitles (srt) inside your TV Shows folder"
10
+ gem.email = "pirate.2061@gmail.com"
11
+ gem.homepage = "http://github.com/pirate/autosub"
12
+ gem.authors = ["Pirate"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ gem.add_dependency "hpricot", ">= 0.8.1"
16
+ gem.add_dependency "httparty", ">= 0.4.5"
17
+ gem.add_dependency "optiflag", ">= 0.7"
18
+ gem.add_dependency "rubyzip", ">= 0.9.1"
19
+ gem.add_dependency "mechanize", ">= 0.9.3"
20
+ gem.add_dependency "simple-rss", ">= 1.2.2"
21
+ gem.default_executable = "bin/autosub"
22
+ end
23
+ Jeweler::GemcutterTasks.new
24
+ rescue LoadError
25
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
26
+ end
27
+
28
+ require 'spec/rake/spectask'
29
+ Spec::Rake::SpecTask.new(:spec) do |spec|
30
+ spec.libs << 'lib' << 'spec'
31
+ spec.spec_files = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
35
+ spec.libs << 'lib' << 'spec'
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :spec => :check_dependencies
41
+
42
+ task :default => :spec
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "autosub #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
53
+
54
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.0
Binary file
Binary file
@@ -0,0 +1,75 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{autosub}
8
+ s.version = "0.4.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Pirate"]
12
+ s.date = %q{2009-11-06}
13
+ s.default_executable = %q{bin/autosub}
14
+ s.description = %q{Ruby tool to automatically download subtitles (srt) inside your TV Shows folder}
15
+ s.email = %q{pirate.2061@gmail.com}
16
+ s.executables = ["autosub"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.markdown"
20
+ ]
21
+ s.files = [
22
+ ".gitignore",
23
+ "LICENSE",
24
+ "README.markdown",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "asset/failure.png",
28
+ "asset/srt.png",
29
+ "autosub.gemspec",
30
+ "bin/autosub",
31
+ "lib/episode.rb",
32
+ "lib/inspector.rb",
33
+ "lib/sites/betaseries.rb",
34
+ "lib/sites/podnapisi.rb",
35
+ "lib/sites/seriessub.rb",
36
+ "lib/sites/tvsubtitle.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/pirate/autosub}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.5}
42
+ s.summary = %q{Automatically download srt for your TV Shows}
43
+
44
+ if s.respond_to? :specification_version then
45
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
50
+ s.add_runtime_dependency(%q<hpricot>, [">= 0.8.1"])
51
+ s.add_runtime_dependency(%q<httparty>, [">= 0.4.5"])
52
+ s.add_runtime_dependency(%q<optiflag>, [">= 0.7"])
53
+ s.add_runtime_dependency(%q<rubyzip>, [">= 0.9.1"])
54
+ s.add_runtime_dependency(%q<mechanize>, [">= 0.9.3"])
55
+ s.add_runtime_dependency(%q<simple-rss>, [">= 1.2.2"])
56
+ else
57
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
58
+ s.add_dependency(%q<hpricot>, [">= 0.8.1"])
59
+ s.add_dependency(%q<httparty>, [">= 0.4.5"])
60
+ s.add_dependency(%q<optiflag>, [">= 0.7"])
61
+ s.add_dependency(%q<rubyzip>, [">= 0.9.1"])
62
+ s.add_dependency(%q<mechanize>, [">= 0.9.3"])
63
+ s.add_dependency(%q<simple-rss>, [">= 1.2.2"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
67
+ s.add_dependency(%q<hpricot>, [">= 0.8.1"])
68
+ s.add_dependency(%q<httparty>, [">= 0.4.5"])
69
+ s.add_dependency(%q<optiflag>, [">= 0.7"])
70
+ s.add_dependency(%q<rubyzip>, [">= 0.9.1"])
71
+ s.add_dependency(%q<mechanize>, [">= 0.9.3"])
72
+ s.add_dependency(%q<simple-rss>, [">= 1.2.2"])
73
+ end
74
+ end
75
+
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optiflag'
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'inspector')
5
+
6
+ module AutoSub extend OptiFlagSet
7
+ flag "p" do
8
+ description "Directory path with many TV Shows directories"
9
+ end
10
+ optional_flag "lang" do
11
+ description "Language(s) you want for your subtitles, default: fr,en
12
+ (Order is important to define if a srt is needed)"
13
+ end
14
+ optional_flag "log" do
15
+ description "path for log file"
16
+ end
17
+
18
+ and_process!
19
+ end
20
+
21
+ begin
22
+ inspector = Inspector.new(ARGV.flags.p, :lang => ARGV.flags.lang, :log_path => ARGV.flags.log)
23
+ rescue => e
24
+ p e.to_s
25
+ Inspector.growl("AutoSub Error!", 'look into the console log', 'failure.png')
26
+ end
@@ -0,0 +1,89 @@
1
+ class Episode
2
+
3
+ attr_accessor :path, :name, :ext, :format, :srt, :tv_show, :season, :number
4
+
5
+ def initialize(tv_show, path)
6
+ @path = path
7
+ @ext = File.extname(@path)
8
+ @name = File.basename(path, @ext)
9
+ @tv_show = tv_show.gsub(/\s\([0-9]{4}\)/,'').chomp(' ')
10
+ @srt = []
11
+
12
+ search_existing_srt
13
+ define_format
14
+ define_season_and_episode_number
15
+ end
16
+
17
+ def filename
18
+ @name + @ext
19
+ end
20
+
21
+ def episode_name
22
+ "#{@tv_show} S#{@season < 10 ? "0#{@season}" : @season}E#{@number < 10 ? "0#{@number}" : @number}"
23
+ end
24
+
25
+ def episode_name_with_format
26
+ episode_name + "#{format == 'hd' ? ' 720p' : ''}"
27
+ end
28
+
29
+ def need_srt?(langs)
30
+ need = -1
31
+ langs = langs.reverse
32
+ langs.each do |lang|
33
+ need = langs.index(lang) if @srt.include?(lang) && need < langs.index(lang)
34
+ end
35
+ need != langs.size - 1
36
+ end
37
+
38
+ def srt_filename(lang)
39
+ "#{File.dirname(path)}/#{name}.#{lang}.srt"
40
+ end
41
+
42
+ def self.valid?(filename)
43
+ filename.match(/.*(([0-9]{1,2}X[0-9]{1,2})|(S[0-9][0-9]E[0-9][0-9])).*((\.avi)|(\.mkv))$/i)
44
+ end
45
+
46
+ def good_format?(filename)
47
+ case @format
48
+ when 'hd'
49
+ filename.include?('720p') || filename.include?('720')
50
+ when 'sd'
51
+ !filename.include?('720p')
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def search_existing_srt
58
+ dir = Dir.new(File.dirname(@path))
59
+ dir.select { |el| File.extname(el) == '.srt' && el.include?(@name) && !el.include?('._') }.each do |srt|
60
+ case srt
61
+ when /\.(french|fr|fre|fra)\.srt/i
62
+ @srt << 'fr'
63
+ when /\.(english|en|eng)\.srt/i
64
+ @srt << 'en'
65
+ end
66
+ end
67
+ end
68
+
69
+ def define_format
70
+ case @ext
71
+ when '.mkv'
72
+ @format = 'hd'
73
+ when '.avi'
74
+ @format = 'sd'
75
+ end
76
+ end
77
+
78
+ def define_season_and_episode_number
79
+ case @name
80
+ when /S[0-9][0-9]E[0-9][0-9]/i # S02E03
81
+ @season = @name.match(/.*S([0-9]{1,2})E.*$/i)[1].to_i
82
+ @number = @name.match(/.*E([0-9]{1,2}).*$/i)[1].to_i
83
+ when /[0-9]{1,2}X[0-9]{1,2}/i # 2X03
84
+ @season = @name.match(/.*([0-9]{1,2})X[0-9]{1,2}.*$/i)[1].to_i
85
+ @number = @name.match(/.*[0-9]{1,2}X([0-9]{1,2}).*$/i)[1].to_i
86
+ end
87
+ end
88
+
89
+ end
@@ -0,0 +1,104 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'episode')
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sites', 'betaseries')
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sites', 'seriessub')
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sites', 'tvsubtitle')
5
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sites', 'podnapisi')
6
+ require 'logger'
7
+ require "pathname"
8
+
9
+ class Inspector
10
+
11
+ attr_accessor :tv_shows, :episodes, :langs, :log
12
+
13
+ def initialize(path , options = {})
14
+ @path = Pathname.new(path).realpath.to_s
15
+ @langs = options[:lang] ? options[:lang].split(',') : ['fr','en']
16
+
17
+ # Initialize Logger
18
+ @log = Logger.new(options[:log_path] || "#{@path}/_autosub_.log" )
19
+ @log.datetime_format = "%Y-%m-%d %H:%M:%S "
20
+ log.info "Begin searching for '#{langs.join(',')}' subtitles..."
21
+
22
+ $stdout.print "--- Searching for '#{langs.join(',')}' subtitles ---\n"
23
+ @tv_shows = [] # {:name => ..., :path => ...}
24
+ initialize_tv_shows
25
+ $stdout.print "Found #{@tv_shows.size} TV Show(s) in #{@path}\n"
26
+
27
+ @episodes = []
28
+ initialize_episodes
29
+ # keep only episodes who needs srt
30
+ $stdout.print "Found #{@episodes.select { |e| e.need_srt?(@langs) }.size} episode(s) who need(s) srt\n"
31
+
32
+ # Find new srt
33
+ begin
34
+ BetaSeries.new(self)
35
+ rescue => e
36
+ log.fatal "Problem with BetaSeries: #{e}"
37
+ end
38
+ # begin
39
+ # TVSubtitle.new(self)
40
+ # rescue => e
41
+ # log.fatal "Problem with TVSubtitle: #{e}"
42
+ # end
43
+ # begin
44
+ # SeriesSub.new(self)
45
+ # rescue => e
46
+ # log.fatal "Problem with SeriesSub: #{e}"
47
+ # end
48
+ # begin
49
+ # Podnapisi.new(self)
50
+ # rescue => e
51
+ # log.fatal "Problem with Podnapisi: #{e}"
52
+ # end
53
+ end
54
+
55
+ def growl_episode(episode, lang)
56
+ Inspector.growl episode.episode_name_with_format, "#{lang_name(lang)} srt added", "srt.png"
57
+ end
58
+
59
+ def self.growl(title, msg, icon, pri = 0)
60
+ system("/usr/local/bin/growlnotify -w -n autosub --image #{File.dirname(__FILE__) + "/../asset/#{icon}"} -p #{pri} -m #{msg.inspect} #{title} &")
61
+ end
62
+
63
+ private
64
+
65
+ def initialize_tv_shows
66
+ # path is a dir with many tv_shows dir
67
+ base_dir = clean_dir(Dir.new(@path))
68
+ base_dir.each do |tv_show_name|
69
+ @tv_shows << { :name => tv_show_name, :path => "#{@path}/#{tv_show_name}" }
70
+ end
71
+ end
72
+
73
+ def initialize_episodes
74
+ @tv_shows.each do |tv_show|
75
+ search_episodes(tv_show[:name], tv_show[:path])
76
+ end
77
+ end
78
+
79
+ def search_episodes(tv_show_name, path)
80
+ elements = clean_dir(Dir.new(path))
81
+ elements.each do |el|
82
+ el_path = "#{path}/#{el}"
83
+ if File.directory?(el_path)
84
+ search_episodes(tv_show_name, el_path)
85
+ elsif Episode.valid?(el)
86
+ episodes << Episode.new(tv_show_name, el_path)
87
+ end
88
+ end
89
+ end
90
+
91
+ def clean_dir(dir)
92
+ dir.select { |e| !["..", ".", ".DS_Store", ".com.apple.timemachine.supported", "Icon\r", "autosub.log", "_autosub_.log"].include?(e) }
93
+ end
94
+
95
+ def lang_name(lang)
96
+ case lang
97
+ when 'en'
98
+ 'English'
99
+ when 'fr'
100
+ 'French'
101
+ end
102
+ end
103
+
104
+ end
@@ -0,0 +1,140 @@
1
+ require 'hpricot'
2
+ require 'open-uri'
3
+ require 'zip/zip'
4
+
5
+ # http://www.betaseries.com/
6
+ class BetaSeries
7
+
8
+ def initialize(inspector)
9
+ @inspector = inspector
10
+ episodes = @inspector.episodes.select { |e| e.need_srt?(@inspector.langs) }
11
+
12
+ $stdout.print "------------------------------------------\n"
13
+ $stdout.print "Start srt searching from www.betaseries.com\n"
14
+ $stdout.print "------------------------------------------\n"
15
+ episodes.each do |e|
16
+ @inspector.langs.each do |l|
17
+ unless e.srt.include?(l)
18
+ $stdout.print "#{e.episode_name_with_format} [#{l}]: "
19
+ if get_srt(e, l)
20
+ inspector.log.info "#{e.episode_name_with_format} [#{l}] // BetaSeries // #{@srt_name}"
21
+ $stdout.print "FOUND\n"
22
+ e.srt << l
23
+ @inspector.growl_episode(e, l)
24
+ break
25
+ else
26
+ $stdout.print "NOT FOUND\n"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def get_srt(episode, lang)
36
+ found = false
37
+ agent = WWW::Mechanize.new
38
+ doc = Hpricot(open(url(episode)))
39
+ doc.search("div.episode").each do |el|
40
+ title = el.search("div.titreep").inner_text
41
+ if good_episode?(episode, title)
42
+ el.search("ul.srt li a") do |srt_link|
43
+ title = srt_link.inner_text
44
+ if !found && good_language?(title, lang) && good_format?(episode, title) && no_tag?(title)
45
+ Tempfile.open("tv.zip") do |tempfile|
46
+ tempfile.write(agent.get_file(srt_link[:href])) # download the zip
47
+ tempfile.close # tempfile need to be closed for unzip it
48
+ Zip::ZipFile.open(tempfile.path) do |zip_file|
49
+ if zip_file.size == 1
50
+ file = zip_file.first
51
+ else
52
+ zip_file.each do |f|
53
+ if f.size > 5000 && good_episode?(episode, f.name) && good_language?(f.name, lang) && episode.good_format?(f.name) && no_tag?(f.name)
54
+ file = f
55
+ end
56
+ end
57
+ end
58
+ if file
59
+ @srt_name = file.name
60
+ zip_file.extract(file, episode.srt_filename(lang))
61
+ found = true
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ rescue => e
70
+ @inspector.log.fatal "BetaSeries // #{episode.episode_name_with_format} [#{lang}] // #{e}"
71
+ found = false
72
+ else
73
+ found
74
+ end
75
+
76
+
77
+ def url(episode)
78
+ "http://www.betaseries.com/ajax/planning_serie.php?url=#{tv_show(episode)}&saison=#{episode.season}"
79
+ end
80
+
81
+ def tv_show(episode)
82
+ case episode.tv_show
83
+ when "Terminator The Sarah Connor Chronicles"
84
+ "thesarahconnorchronicles"
85
+ when "CSI New York"
86
+ "csiny"
87
+ when "The IT Crowd"
88
+ "itcrowd"
89
+ else
90
+ episode.tv_show
91
+ end.downcase.gsub(/\s/, '')
92
+ end
93
+
94
+ def lang_version(lang)
95
+ case lang
96
+ when 'fr'
97
+ "VF"
98
+ when 'en'
99
+ "VO"
100
+ end
101
+ end
102
+
103
+ def num(episode)
104
+ "#{episode.season}#{episode.number < 10 ? "0#{episode.number}" : episode.number}"
105
+ end
106
+
107
+ def good_episode?(episode, name)
108
+ num2 = "S#{episode.season < 10 ? "0#{episode.season}" : episode.season}E#{episode.number < 10 ? "0#{episode.number}" : episode.number}"
109
+ name.include?(num(episode)) || name.include?(num2)
110
+ end
111
+
112
+ def good_language?(name, lang)
113
+ case lang
114
+ when 'fr'
115
+ name.include?("VF") || name.include?("fr")
116
+ when 'en'
117
+ name.include?("VO") || name.include?("en")
118
+ end
119
+ end
120
+
121
+ def good_format?(episode, name)
122
+ if name.include?("VO") || name.include?("VF")
123
+ true
124
+ else
125
+ episode.good_format?(name)
126
+ end
127
+ end
128
+
129
+ def no_tag?(filename)
130
+ case filename
131
+ when /no.?tag/i
132
+ true
133
+ when /tag/i
134
+ false
135
+ else
136
+ true
137
+ end
138
+ end
139
+
140
+ end
@@ -0,0 +1,101 @@
1
+ require 'hpricot'
2
+ require 'open-uri'
3
+ require 'zip/zip'
4
+ require 'cgi'
5
+
6
+ # http://www.podnapisi.net/ | http://www.sub-titles.net/
7
+ class Podnapisi
8
+
9
+ def initialize(inspector)
10
+ @inspector = inspector
11
+ episodes = @inspector.episodes.select { |e| e.need_srt?(@inspector.langs) }
12
+
13
+ $stdout.print "------------------------------------------\n"
14
+ $stdout.print "Start srt searching from www.podnapisi.net\n"
15
+ $stdout.print "------------------------------------------\n"
16
+ episodes.each do |e|
17
+ @inspector.langs.each do |l|
18
+ unless e.srt.include?(l)
19
+ $stdout.print "#{e.episode_name_with_format} [#{l}]: "
20
+ if get_srt(e, l)
21
+ @inspector.log.info "#{e.episode_name_with_format} [#{l}] // Podnapisi // #{@srt_name}"
22
+ $stdout.print "FOUND\n"
23
+ e.srt << l
24
+ @inspector.growl_episode(e, l)
25
+ break
26
+ else
27
+ $stdout.print "NOT FOUND\n"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def get_srt(episode, lang)
37
+ found = false
38
+ doc = Hpricot(open(url(episode, lang)))
39
+ doc.search("table.list tr").each do |el|
40
+ if !found && have_srt_format?(el) && !hearing_impaired?(el) && url = open(download_url(el))
41
+ Tempfile.open("tv.zip") do |tempfile|
42
+ tempfile.write(open(url).read) # download the zip
43
+ tempfile.close # tempfile need to be closed for unzip it
44
+ Zip::ZipFile.open(tempfile.path) do |zip_file|
45
+ zip_file.each do |f|
46
+ if f.size > 5000
47
+ @srt_name = f.name
48
+ zip_file.extract(f, episode.srt_filename(lang))
49
+ found = true
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ rescue => e
57
+ @inspector.log.fatal "Podnapisi // #{episode.episode_name_with_format} [#{lang}] // #{e}"
58
+ found = false
59
+ else
60
+ found
61
+ end
62
+
63
+ def url(episode, lang)
64
+ "http://simple.podnapisi.net/ppodnapisi/search?tbsl=3&asdp=1&sK=#{tv_show(episode)}&sJ=#{lang_num(lang)}&sO=desc&sS=time&submit=Search&sTS=#{episode.season}&sTE=#{episode.number}&sY=&sR=#{format(episode)}&sT=1"
65
+ end
66
+
67
+ def tv_show(episode)
68
+ CGI.escape(episode.tv_show)
69
+ end
70
+
71
+ def format(episode)
72
+ case episode.format
73
+ when 'hd'
74
+ "720"
75
+ when 'sd'
76
+ ""
77
+ end
78
+ end
79
+
80
+ def lang_num(lang)
81
+ case lang
82
+ when 'fr'
83
+ 8
84
+ when 'en'
85
+ 2
86
+ end
87
+ end
88
+
89
+ def have_srt_format?(el)
90
+ !el.search("td[text()*='SubRip']").empty?
91
+ end
92
+
93
+ def hearing_impaired?(el)
94
+ !el.search("img[@title='Subtitle is for hearing impaired']").empty?
95
+ end
96
+
97
+ def download_url(el)
98
+ "http://simple.podnapisi.net#{el.search("a[text()*='download subtitle']").first[:href]}"
99
+ end
100
+
101
+ end
@@ -0,0 +1,122 @@
1
+ require 'hpricot'
2
+ require 'open-uri'
3
+ require 'zip/zip'
4
+
5
+ # http://www.seriessub.com/
6
+ class SeriesSub
7
+
8
+ def initialize(inspector)
9
+ @inspector = inspector
10
+ episodes = @inspector.episodes.select { |e| e.need_srt?(@inspector.langs) }
11
+
12
+ $stdout.print "------------------------------------------\n"
13
+ $stdout.print "Start srt searching from www.seriessub.com\n"
14
+ $stdout.print "------------------------------------------\n"
15
+ episodes.each do |e|
16
+ @inspector.langs.each do |l|
17
+ unless e.srt.include?(l)
18
+ $stdout.print "#{e.episode_name_with_format} [#{l}]: "
19
+ if get_srt(e, l)
20
+ inspector.log.info "#{e.episode_name_with_format} [#{l}] // SeriesSub // #{@srt_name}"
21
+ $stdout.print "FOUND\n"
22
+ e.srt << l
23
+ @inspector.growl_episode(e, l)
24
+ break
25
+ else
26
+ $stdout.print "NOT FOUND\n"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def get_srt(episode, lang)
36
+ found = false
37
+ doc = Hpricot(open(url(episode)))
38
+ doc.search("td.gst_fichier a").each do |el|
39
+ text = el.inner_text.gsub(/(\_|\.)/, ' ')
40
+ if good_episode?(episode, text) && text.include?(lang_version(lang))
41
+ if text.include?('zip')
42
+ Tempfile.open("tv.zip") do |tempfile|
43
+ tempfile.write(open(el[:href]).read) # download the zip
44
+ tempfile.close # tempfile need to be closed for unzip it
45
+ Zip::ZipFile.open(tempfile.path) do |zip_file|
46
+ zip_file.each do |f|
47
+ if f.size > 5000 && good_episode?(episode, f.name) && f.name.include?(lang_version(lang)) && episode.good_format?(f.name) && no_tag?(f.name)
48
+ @srt_name = f.name
49
+ zip_file.extract(f, episode.srt_filename(lang))
50
+ found = true
51
+ end
52
+ end
53
+ end
54
+ end
55
+ elsif episode.good_format?(text) && no_tag?(text) # just a single srt file
56
+ @srt_name = text
57
+ Tempfile.open("tv.srt") do |tempfile|
58
+ tempfile.write(open(el[:href]).read) # download the zip
59
+ tempfile.close
60
+ File.move(tempfile.path, episode.srt_filename(lang))
61
+ found = true
62
+ end
63
+ end
64
+ end
65
+ end
66
+ rescue => e
67
+ @inspector.log.fatal "SeriesSub // #{episode.episode_name_with_format} [#{lang}] // #{e}"
68
+ found = false
69
+ else
70
+ found
71
+ end
72
+
73
+
74
+ def url(episode)
75
+ "http://www.seriessub.com/sous-titres/#{tv_show(episode)}/#{season(episode)}"
76
+ end
77
+
78
+ def tv_show(episode)
79
+ case episode.tv_show
80
+ when "Terminator The Sarah Connor Chronicles"
81
+ "The Sarah Connor Chronicles"
82
+ when "The IT Crowd"
83
+ "IT Crowd"
84
+ else
85
+ episode.tv_show
86
+ end.downcase.gsub(/\s/, '_')
87
+ end
88
+
89
+ def season(episode)
90
+ "saison_#{episode.season}"
91
+ end
92
+
93
+ def lang_version(lang)
94
+ case lang
95
+ when 'fr'
96
+ "VF"
97
+ when 'en'
98
+ "VO"
99
+ end
100
+ end
101
+
102
+ def num(episode)
103
+ "#{episode.season}#{episode.number < 10 ? "0#{episode.number}" : episode.number}"
104
+ end
105
+
106
+ def good_episode?(episode, name)
107
+ num2 = "S#{episode.season < 10 ? "0#{episode.season}" : episode.season}E#{episode.number < 10 ? "0#{episode.number}" : episode.number}"
108
+ name.include?(num(episode)) || name.include?(num2)
109
+ end
110
+
111
+ def no_tag?(filename)
112
+ case filename
113
+ when /notag/i
114
+ true
115
+ when /tag/i
116
+ false
117
+ else
118
+ true
119
+ end
120
+ end
121
+
122
+ end
@@ -0,0 +1,81 @@
1
+ require 'simple-rss'
2
+ require 'open-uri'
3
+ require 'zip/zip'
4
+ require 'cgi'
5
+ require 'mechanize'
6
+
7
+ # http://www.tvsubtitles.net/
8
+ class TVSubtitle
9
+
10
+ def initialize(inspector)
11
+ @inspector = inspector
12
+ episodes = @inspector.episodes.select { |e| e.need_srt?(@inspector.langs) }
13
+
14
+ $stdout.print "--------------------------------------------\n"
15
+ $stdout.print "Searching for srt in www.tvsubtitles.net RSS\n"
16
+ $stdout.print "--------------------------------------------\n"
17
+ @inspector.langs.each do |l|
18
+ rss(l).items.each do |item|
19
+ episodes.each do |e|
20
+ unless e.srt.include?(l)
21
+ if episode_title(e, l) == item_title(item)
22
+ download_srt(item, e, l)
23
+ inspector.log.info "#{e.episode_name_with_format} [#{l}] // TVSubtitle // #{@srt_name}"
24
+ $stdout.print "FOUND: #{e.episode_name_with_format} [#{l}]\n"
25
+ e.srt << l
26
+ @inspector.growl_episode(e, l)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def download_srt(item, episode, lang)
37
+ found = false
38
+ agent = WWW::Mechanize.new
39
+ id = item_id(item)
40
+ Tempfile.open("srt") do |tempfile|
41
+ agent.get("http://www.tvsubtitles.net/subtitle-#{id}.html") # set cookie
42
+ tempfile.write(agent.get_file("http://www.tvsubtitles.net/download-#{id}.html")) # download the srt
43
+ tempfile.close
44
+ Zip::ZipFile.open(tempfile.path) do |zip_file|
45
+ zip_file.each do |f|
46
+ if f.size > 5000
47
+ @srt_name = f.name
48
+ zip_file.extract(f, episode.srt_filename(lang))
49
+ found = true
50
+ end
51
+ end
52
+ end
53
+ end
54
+ rescue => e
55
+ @inspector.log.fatal "TVSubtitle // #{episode.episode_name_with_format} [#{lang}] // #{e}"
56
+ found = false
57
+ else
58
+ found
59
+ end
60
+
61
+ def rss(lang)
62
+ SimpleRSS.parse open("http://fr.tvsubtitles.net/rss#{lang}.xml")
63
+ end
64
+
65
+ def num(episode)
66
+ "#{episode.season}X#{episode.number < 10 ? "0#{episode.number}" : episode.number}"
67
+ end
68
+
69
+ def episode_title(episode, lang)
70
+ "#{episode.tv_show} #{num(episode)} #{lang} #{episode.format}".downcase
71
+ end
72
+
73
+ def item_title(item)
74
+ "#{item.title} #{item.description.include?('720p') ? 'hd' : 'sd'}".downcase
75
+ end
76
+
77
+ def item_id(item)
78
+ item.link.match(/([0-9]+)/)[1]
79
+ end
80
+
81
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: autosub
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Pirate
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-06 00:00:00 +01:00
13
+ default_executable: bin/autosub
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.9
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hpricot
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.1
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: httparty
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.4.5
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: optiflag
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0.7"
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubyzip
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 0.9.1
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: mechanize
67
+ type: :runtime
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 0.9.3
74
+ version:
75
+ - !ruby/object:Gem::Dependency
76
+ name: simple-rss
77
+ type: :runtime
78
+ version_requirement:
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 1.2.2
84
+ version:
85
+ description: Ruby tool to automatically download subtitles (srt) inside your TV Shows folder
86
+ email: pirate.2061@gmail.com
87
+ executables:
88
+ - autosub
89
+ extensions: []
90
+
91
+ extra_rdoc_files:
92
+ - LICENSE
93
+ - README.markdown
94
+ files:
95
+ - .gitignore
96
+ - LICENSE
97
+ - README.markdown
98
+ - Rakefile
99
+ - VERSION
100
+ - asset/failure.png
101
+ - asset/srt.png
102
+ - autosub.gemspec
103
+ - bin/autosub
104
+ - lib/episode.rb
105
+ - lib/inspector.rb
106
+ - lib/sites/betaseries.rb
107
+ - lib/sites/podnapisi.rb
108
+ - lib/sites/seriessub.rb
109
+ - lib/sites/tvsubtitle.rb
110
+ has_rdoc: true
111
+ homepage: http://github.com/pirate/autosub
112
+ licenses: []
113
+
114
+ post_install_message:
115
+ rdoc_options:
116
+ - --charset=UTF-8
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: "0"
124
+ version:
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: "0"
130
+ version:
131
+ requirements: []
132
+
133
+ rubyforge_project:
134
+ rubygems_version: 1.3.5
135
+ signing_key:
136
+ specification_version: 3
137
+ summary: Automatically download srt for your TV Shows
138
+ test_files: []
139
+