pirate-autosub 0.2.1

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,57 @@
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
+ ## License
37
+
38
+ Copyright (c) 2008 Pirate
39
+
40
+ Permission is hereby granted, free of charge, to any person obtaining
41
+ a copy of this software and associated documentation files (the
42
+ "Software"), to deal in the Software without restriction, including
43
+ without limitation the rights to use, copy, modify, merge, publish,
44
+ distribute, sublicense, and/or sell copies of the Software, and to
45
+ permit persons to whom the Software is furnished to do so, subject to
46
+ the following conditions:
47
+
48
+ The above copyright notice and this permission notice shall be
49
+ included in all copies or substantial portions of the Software.
50
+
51
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
52
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
53
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
54
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
55
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
56
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
57
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,16 @@
1
+ # Rakefile
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'echoe'
5
+
6
+ Echoe.new('autosub', '0.2.1') do |p|
7
+ p.description = "Ruby tool to automatically download subtitles (srt) inside your TV Shows folder"
8
+ p.url = "http://github.com/pirate/autosub"
9
+ p.author = "Pirate"
10
+ p.email = "pirate.2061@gmail.com"
11
+ p.ignore_pattern = ["tmp/*", "script/*"]
12
+ p.executable_pattern = "bin/autosub"
13
+ p.runtime_dependencies = ["hpricot", "rubyzip", "optiflag", "simple-rss"]
14
+ end
15
+
16
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
Binary file
@@ -0,0 +1,48 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{autosub}
5
+ s.version = "0.2.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Pirate"]
9
+ s.date = %q{2008-12-28}
10
+ s.default_executable = %q{autosub}
11
+ s.description = %q{Ruby tool to automatically download subtitles (srt) inside your TV Shows folder}
12
+ s.email = %q{pirate.2061@gmail.com}
13
+ s.executables = ["autosub"]
14
+ s.extra_rdoc_files = ["bin/autosub", "lib/episode.rb", "lib/inspector.rb", "lib/sites/seriessub.rb", "lib/sites/tvsubtitle.rb", "README.markdown"]
15
+ s.files = ["asset/srt.png", "autosub.gemspec", "bin/autosub", "lib/episode.rb", "lib/inspector.rb", "lib/sites/seriessub.rb", "lib/sites/tvsubtitle.rb", "Manifest", "Rakefile", "README.markdown"]
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://github.com/pirate/autosub}
18
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Autosub", "--main", "README.markdown"]
19
+ s.require_paths = ["lib"]
20
+ s.rubyforge_project = %q{autosub}
21
+ s.rubygems_version = %q{1.3.1}
22
+ s.summary = %q{Ruby tool to automatically download subtitles (srt) inside your TV Shows folder}
23
+
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 2
27
+
28
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
+ s.add_runtime_dependency(%q<hpricot>, [">= 0"])
30
+ s.add_runtime_dependency(%q<rubyzip>, [">= 0"])
31
+ s.add_runtime_dependency(%q<optiflag>, [">= 0"])
32
+ s.add_runtime_dependency(%q<simple-rss>, [">= 0"])
33
+ s.add_development_dependency(%q<echoe>, [">= 0"])
34
+ else
35
+ s.add_dependency(%q<hpricot>, [">= 0"])
36
+ s.add_dependency(%q<rubyzip>, [">= 0"])
37
+ s.add_dependency(%q<optiflag>, [">= 0"])
38
+ s.add_dependency(%q<simple-rss>, [">= 0"])
39
+ s.add_dependency(%q<echoe>, [">= 0"])
40
+ end
41
+ else
42
+ s.add_dependency(%q<hpricot>, [">= 0"])
43
+ s.add_dependency(%q<rubyzip>, [">= 0"])
44
+ s.add_dependency(%q<optiflag>, [">= 0"])
45
+ s.add_dependency(%q<simple-rss>, [">= 0"])
46
+ s.add_dependency(%q<echoe>, [">= 0"])
47
+ end
48
+ end
@@ -0,0 +1,23 @@
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
+
15
+ and_process!
16
+ end
17
+
18
+ begin
19
+ inspector = Inspector.new(ARGV.flags.p, ARGV.flags.lang)
20
+ rescue => e
21
+ p e.to_s
22
+ Inspector.growl("AutoSub Error!", 'look into the console log', 'failure.png')
23
+ 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
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')
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,76 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'episode')
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sites', 'seriessub')
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sites', 'tvsubtitle')
4
+
5
+ class Inspector
6
+
7
+ attr_accessor :tv_shows, :episodes, :langs
8
+
9
+ def initialize(path , langs = nil)
10
+ @path = path.gsub(/\/$/,'')
11
+ @langs = langs ? langs.split(',') : ['fr','en']
12
+
13
+ @tv_shows = [] # {:name => ..., :path => ...}
14
+ initialize_tv_shows
15
+ $stdout.print "Found #{@tv_shows.size} TV Show(s) in #{@path}\n"
16
+
17
+ @episodes = []
18
+ initialize_episodes
19
+ # keep only episodes who needs srt
20
+ $stdout.print "Found #{@episodes.select { |e| e.need_srt?(@langs) }.size} episode(s) who need(s) srt\n"
21
+
22
+ # Find new srt
23
+ TVSubtitle.new(self)
24
+ SeriesSub.new(self)
25
+ end
26
+
27
+ def growl_episode(episode, lang)
28
+ Inspector.growl episode.episode_name_with_format, "#{lang_name(lang)} srt added", "srt.png"
29
+ end
30
+
31
+ def self.growl(title, msg, icon, pri = 0)
32
+ system("/usr/local/bin/growlnotify -w -n autosub --image #{File.dirname(__FILE__) + "/../asset/#{icon}"} -p #{pri} -m #{msg.inspect} #{title} &")
33
+ end
34
+
35
+ private
36
+
37
+ def initialize_tv_shows
38
+ # path is a dir with many tv_shows dir
39
+ base_dir = clean_dir(Dir.new(@path))
40
+ base_dir.each do |tv_show_name|
41
+ @tv_shows << { :name => tv_show_name, :path => "#{@path}/#{tv_show_name}" }
42
+ end
43
+ end
44
+
45
+ def initialize_episodes
46
+ @tv_shows.each do |tv_show|
47
+ search_episodes(tv_show[:name], tv_show[:path])
48
+ end
49
+ end
50
+
51
+ def search_episodes(tv_show_name, path)
52
+ elements = clean_dir(Dir.new(path))
53
+ elements.each do |el|
54
+ el_path = "#{path}/#{el}"
55
+ if File.directory?(el_path)
56
+ search_episodes(tv_show_name, el_path)
57
+ elsif Episode.valid?(el)
58
+ episodes << Episode.new(tv_show_name, el_path)
59
+ end
60
+ end
61
+ end
62
+
63
+ def clean_dir(dir)
64
+ dir.select { |e| !["..", ".", ".DS_Store", ".com.apple.timemachine.supported"].include?(e) }
65
+ end
66
+
67
+ def lang_name(lang)
68
+ case lang
69
+ when 'en'
70
+ 'English'
71
+ when 'fr'
72
+ 'French'
73
+ end
74
+ end
75
+
76
+ end
@@ -0,0 +1,116 @@
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
+ $stdout.print "FOUND\n"
21
+ e.srt << l
22
+ @inspector.growl_episode(e, l)
23
+ break
24
+ else
25
+ $stdout.print "NOT FOUND\n"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def get_srt(episode, lang)
35
+ found = false
36
+ doc = Hpricot(open(url(episode)))
37
+ doc.search("td.gst_fichier a").each do |el|
38
+ text = el.inner_text.gsub(/(\_|\.)/, ' ')
39
+ if good_episode?(episode, text) && text.include?(lang_version(lang))
40
+ if text.include?('zip')
41
+ Tempfile.open("tv.zip") do |tempfile|
42
+ tempfile.write(open(el[:href]).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 good_episode?(episode, f.name) && f.name.include?(lang_version(lang)) && episode.good_format?(f.name) && no_tag?(f.name)
47
+ zip_file.extract(f, episode.srt_filename(lang))
48
+ found = true
49
+ end
50
+ end
51
+ end
52
+ end
53
+ elsif episode.good_format?(text) && no_tag?(text) # just a single srt file
54
+ Tempfile.open("tv.srt") do |tempfile|
55
+ tempfile.write(open(el[:href]).read) # download the zip
56
+ tempfile.close
57
+ File.move(tempfile.path, episode.srt_filename(lang))
58
+ found = true
59
+ end
60
+ end
61
+ end
62
+ end
63
+ found
64
+ end
65
+
66
+
67
+ def url(episode)
68
+ "http://www.seriessub.com/sous-titres/#{tv_show(episode)}/#{season(episode)}"
69
+ end
70
+
71
+ def tv_show(episode)
72
+ name = episode.tv_show.gsub(/\s\([0-9]{4}\)/,'')
73
+ case name
74
+ when "Terminator The Sarah Connor Chronicles"
75
+ "The Sarah Connor Chronicles"
76
+ when "The IT Crowd"
77
+ "IT Crowd"
78
+ else
79
+ name
80
+ end.downcase.gsub(/\s/, '_')
81
+ end
82
+
83
+ def season(episode)
84
+ "saison_#{episode.season}"
85
+ end
86
+
87
+ def lang_version(lang)
88
+ case lang
89
+ when 'fr'
90
+ "VF"
91
+ when 'en'
92
+ "VO"
93
+ end
94
+ end
95
+
96
+ def num(episode)
97
+ "#{episode.season}#{episode.number < 10 ? "0#{episode.number}" : episode.number}"
98
+ end
99
+
100
+ def good_episode?(episode, name)
101
+ num2 = "S#{episode.season < 10 ? "0#{episode.season}" : episode.season}E#{episode.number < 10 ? "0#{episode.number}" : episode.number}"
102
+ name.include?(num(episode)) || name.include?(num2)
103
+ end
104
+
105
+ def no_tag?(filename)
106
+ case filename
107
+ when /notag/i
108
+ true
109
+ when /tag/i
110
+ false
111
+ else
112
+ true
113
+ end
114
+ end
115
+
116
+ end
@@ -0,0 +1,70 @@
1
+ require 'simple-rss'
2
+ require 'open-uri'
3
+ require 'zip/zip'
4
+ require 'cgi'
5
+
6
+ # http://www.tvsubtitles.net/
7
+ class TVSubtitle
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 "Searching fot srt in www.tvsubtitles.net RSS\n"
15
+ $stdout.print "--------------------------------------------\n"
16
+ @inspector.langs.each do |l|
17
+ rss(l).items.each do |item|
18
+ episodes.each do |e|
19
+ unless e.srt.include?(l)
20
+ if episode_title(e, l) == item_title(item)
21
+ $stdout.print "FOUND: #{e.episode_name_with_format} [#{l}]\n"
22
+ download_srt(item, e, l)
23
+ e.srt << l
24
+ @inspector.growl_episode(e, l)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def srt_link(item)
35
+ id = item.link.match(/([0-9]+)/)[1]
36
+ http = Net::HTTP.new('www.tvsubtitles.net')
37
+ resp, data = http.get("/download-#{id}.html")
38
+ "http://www.tvsubtitles.net/#{resp.response['Location'].gsub(/\s/, '%20')}"
39
+ end
40
+
41
+ def download_srt(item, episode, lang)
42
+ url = srt_link(item)
43
+ Tempfile.open("srt") do |tempfile|
44
+ tempfile.write(open(url).read) # download the srt
45
+ tempfile.close
46
+ Zip::ZipFile.open(tempfile.path) do |zip_file|
47
+ zip_file.each do |f|
48
+ zip_file.extract(f, episode.srt_filename(lang))
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def rss(lang)
55
+ SimpleRSS.parse open("http://fr.tvsubtitles.net/rss#{lang}.xml")
56
+ end
57
+
58
+ def num(episode)
59
+ "#{episode.season}X#{episode.number < 10 ? "0#{episode.number}" : episode.number}"
60
+ end
61
+
62
+ def episode_title(episode, lang)
63
+ "#{episode.tv_show} #{num(episode)} #{lang} #{episode.format}".downcase
64
+ end
65
+
66
+ def item_title(item)
67
+ "#{item.title} #{item.description.include?('720p') ? 'hd' : 'sd'}".downcase
68
+ end
69
+
70
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pirate-autosub
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Pirate
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-28 00:00:00 -08:00
13
+ default_executable: autosub
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hpricot
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: rubyzip
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: optiflag
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ - !ruby/object:Gem::Dependency
43
+ name: simple-rss
44
+ version_requirement:
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ - !ruby/object:Gem::Dependency
52
+ name: echoe
53
+ version_requirement:
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ description: Ruby tool to automatically download subtitles (srt) inside your TV Shows folder
61
+ email: pirate.2061@gmail.com
62
+ executables:
63
+ - autosub
64
+ extensions: []
65
+
66
+ extra_rdoc_files:
67
+ - bin/autosub
68
+ - lib/episode.rb
69
+ - lib/inspector.rb
70
+ - lib/sites/seriessub.rb
71
+ - lib/sites/tvsubtitle.rb
72
+ - README.markdown
73
+ files:
74
+ - asset/srt.png
75
+ - autosub.gemspec
76
+ - bin/autosub
77
+ - lib/episode.rb
78
+ - lib/inspector.rb
79
+ - lib/sites/seriessub.rb
80
+ - lib/sites/tvsubtitle.rb
81
+ - Manifest
82
+ - Rakefile
83
+ - README.markdown
84
+ has_rdoc: true
85
+ homepage: http://github.com/pirate/autosub
86
+ post_install_message:
87
+ rdoc_options:
88
+ - --line-numbers
89
+ - --inline-source
90
+ - --title
91
+ - Autosub
92
+ - --main
93
+ - README.markdown
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ version:
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: "1.2"
107
+ version:
108
+ requirements: []
109
+
110
+ rubyforge_project: autosub
111
+ rubygems_version: 1.2.0
112
+ signing_key:
113
+ specification_version: 2
114
+ summary: Ruby tool to automatically download subtitles (srt) inside your TV Shows folder
115
+ test_files: []
116
+