autosub 0.4.0

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.
@@ -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
+