suby 0.0.5 → 0.0.6

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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # suby
2
+
3
+ Find and download subtitles
4
+
5
+ suby is a little script to find and download subtitles for TV series
6
+
7
+ ## Install
8
+
9
+ gem install suby
10
+
11
+ ## Synopsis
12
+
13
+ suby 'my show 1x01 - Pilot.avi' # => Downloads my show 1x01 - Pilot.srt
14
+
15
+ ## Status
16
+
17
+ Under heavy development.
18
+
19
+ * Currently only accept one format for input.
20
+ You could use [tvnamer](https://github.com/dbr/tvnamer) to rename the video files before.
21
+
22
+ * Search only on tvsubtitles.net.
23
+ Many series have subtitles there, but not all.
data/bin/suby CHANGED
@@ -23,6 +23,4 @@ option_parser.parse!
23
23
 
24
24
  puts option_parser if ARGV.empty?
25
25
 
26
- ARGV.each do |file|
27
- Suby.download_subtitles file, options
28
- end
26
+ Suby.download_subtitles ARGV, options
data/lib/suby.rb CHANGED
@@ -1,83 +1,24 @@
1
- require 'net/http'
2
- require 'nokogiri'
1
+ require_relative 'suby/downloader'
3
2
 
4
3
  module Suby
5
4
  extend self
6
5
 
7
- DEFAULT_OPTIONS = {
8
- lang: 'en'
9
- }
10
-
11
6
  SUB_EXTENSIONS = %w[srt sub]
12
7
  TEMP_ARCHIVE_NAME = '__archive__'
13
- SITE = 'www.tvsubtitles.net'
14
- SEARCH_URL = '/search.php'
15
-
16
- # cache
17
- SHOW_URLS = {}
18
- SHOW_PAGES = {}
19
-
20
- def download_subtitles(file, options = {})
21
- options = DEFAULT_OPTIONS.merge options
22
- return if SUB_EXTENSIONS.include? File.extname(file)
23
- return puts "Skipping: #{file}" if SUB_EXTENSIONS.any? { |ext|
24
- File.exist? File.basename(file, File.extname(file)) + ".#{ext}" }
25
-
26
- unless /^(?<show>.+) (?<season>\d{1,2})x(?<episode>\d{1,2}) - .+\.[a-z]+?$/ =~ file
27
- return puts "wrong file format (#{file}). Must be:\n<show> <season>x<episode> - <title>.<ext>"
28
- end
29
- season, episode = [season, episode].map(&:to_i)
30
- puts "Searching subtitles for #{file}:"
31
- puts "Show: #{show}, Season: #{season}, Episode: #{episode}"
32
-
33
- Net::HTTP.start(SITE) { |tvsubtitles|
34
- # search show
35
- show_url = (SHOW_URLS[show] ||= begin
36
- post = Net::HTTP::Post.new(SEARCH_URL)
37
- post.form_data = { 'q' => show }
38
- results = Nokogiri tvsubtitles.request(post).body
39
- url = results.css('ul li div a').first[:href]
40
-
41
- raise 'could not find the show' unless /^\/tvshow-(\d+)\.html$/ =~ url
42
- "/tvshow-#{$1}-#{season}.html"
43
- end)
44
- puts "show url: #{show_url}"
45
-
46
- # search episode
47
- show = (SHOW_PAGES[show] ||= Nokogiri tvsubtitles.get(show_url).body)
48
- episode_url = nil
49
- show.css('div.left_articles table tr').find { |tr|
50
- tr.children.find { |td| td.name == 'td' && td.text =~ /\A#{season}x0?#{episode}\z/ }
51
- }.children.find { |td|
52
- td.children.find { |a|
53
- a.name == 'a' && a[:href].start_with?('episode') && episode_url = a[:href]
54
- }
55
- }
56
-
57
- raise "invalid episode url: #{episode_url}" unless episode_url =~ /^episode-(\d+)\.html$/
58
- episode_url = "/episode-#{$1}-#{options[:lang]}.html"
59
- puts "episode url: #{episode_url}"
60
-
61
- # subtitles
62
- subtitles = Nokogiri tvsubtitles.get(episode_url).body
63
-
64
- # TODO: choose 720p or most downloaded instead of first found
65
- subtitle_url = subtitles.css('div.left_articles a').find { |a| a.name == 'a' && a[:href].start_with?('/subtitle') }[:href]
66
- raise 'invalid subtitle url' unless subtitle_url =~ /^\/subtitle-(\d+)\.html/
67
- puts "subtitle url: #{subtitle_url}"
68
-
69
- # download
70
- download_url = tvsubtitles.get("/download-#{$1}.html")['Location']
71
- download_url = URI.escape('/'+download_url)
72
- puts "download url: #{download_url}"
73
8
 
74
- # extract
75
- zip = tvsubtitles.get(download_url).body
76
- open(TEMP_ARCHIVE_NAME, 'wb') { |f| f.write zip }
77
- subs = extract_subs_from_archive(TEMP_ARCHIVE_NAME)
78
- new_name = File.basename(file, File.extname(file))+File.extname(subs.first)
79
- File.rename(subs.first, new_name)
80
- puts "Renaming to #{new_name}"
9
+ def download_subtitles(files, options = {})
10
+ files.each { |file|
11
+ next if SUB_EXTENSIONS.include? File.extname(file)
12
+ next puts "Skipping: #{file}" if SUB_EXTENSIONS.any? { |ext|
13
+ File.exist? File.basename(file, File.extname(file)) + ".#{ext}" }
14
+
15
+ begin
16
+ Downloader.new(file, options[:lang]).download
17
+ rescue
18
+ puts " The download of the subtitles failed for #{file}:"
19
+ puts " #{$!.class}: #{$!.message}"
20
+ puts $!.backtrace.map { |line| line.prepend ' '*4 }
21
+ end
81
22
  }
82
23
  end
83
24
 
@@ -0,0 +1,91 @@
1
+ require 'net/http'
2
+ require 'nokogiri'
3
+
4
+ module Suby
5
+ class Downloader
6
+ SITE = 'www.tvsubtitles.net'
7
+ SEARCH_URL = '/search.php'
8
+
9
+ # cache
10
+ SHOW_URLS = {}
11
+ SHOW_PAGES = {}
12
+
13
+ attr_reader :show, :season, :episode, :file, :lang
14
+
15
+ def initialize file, lang = nil
16
+ @file, @lang = file, lang || 'en'
17
+ unless /^(?<show>.+) (?<season>\d{1,2})x(?<episode>\d{1,2})(?: - .+)?\.[a-z]+?$/ =~ file
18
+ raise "wrong file format (#{file}). Must be:\n<show> <season>x<episode>[ - <title>].<ext>"
19
+ end
20
+ @show, @season, @episode = show, season.to_i, episode.to_i
21
+ end
22
+
23
+ def http
24
+ @http ||= Net::HTTP.new(SITE).start
25
+ end
26
+
27
+ def show_url
28
+ SHOW_URLS[show] ||= begin
29
+ post = Net::HTTP::Post.new(SEARCH_URL)
30
+ post.form_data = { 'q' => show }
31
+ results = Nokogiri http.request(post).body
32
+ url = results.css('ul li div a').first[:href]
33
+
34
+ raise 'could not find the show' unless /^\/tvshow-(\d+)\.html$/ =~ url
35
+ "/tvshow-#{$1}-#{season}.html"
36
+ end
37
+ end
38
+
39
+ def episode_url
40
+ @episode_url ||= begin
41
+ SHOW_PAGES[show] ||= Nokogiri http.get(show_url).body
42
+
43
+ url = nil
44
+ SHOW_PAGES[show].css('div.left_articles table tr').find { |tr|
45
+ tr.children.find { |td| td.name == 'td' && td.text =~ /\A#{season}x0?#{episode}\z/ }
46
+ }.children.find { |td|
47
+ td.children.find { |a|
48
+ a.name == 'a' && a[:href].start_with?('episode') && url = a[:href]
49
+ }
50
+ }
51
+ raise "invalid episode url: #{episode_url}" unless url =~ /^episode-(\d+)\.html$/
52
+ "/episode-#{$1}-#{lang}.html"
53
+ end
54
+ end
55
+
56
+ def subtitles_url
57
+ @subtitles_url ||= begin
58
+ subtitles = Nokogiri http.get(episode_url).body
59
+
60
+ # TODO: choose 720p or most downloaded instead of first found
61
+ url = subtitles.css('div.left_articles a').find { |a| a.name == 'a' && a[:href].start_with?('/subtitle') }[:href]
62
+ raise 'invalid subtitle url' unless url =~ /^\/subtitle-(\d+)\.html/
63
+ url
64
+ end
65
+ end
66
+
67
+ def download_url
68
+ @download_url ||= URI.escape '/' + http.get(subtitles_url.sub('subtitle', 'download'))['Location']
69
+ end
70
+
71
+ def download
72
+ puts "Searching subtitles for #{file}:"
73
+ puts "Show: #{show}, Season: #{season}, Episode: #{episode}"
74
+
75
+ puts "show url: #{show_url}"
76
+ puts "episode url: #{episode_url}"
77
+ puts "subtitle url: #{subtitles_url}"
78
+ puts "download url: #{download_url}"
79
+
80
+ # extract
81
+ zip = http.get(download_url).body
82
+ http.finish
83
+ open(TEMP_ARCHIVE_NAME, 'wb') { |f| f.write zip }
84
+ subs = Suby.extract_subs_from_archive(TEMP_ARCHIVE_NAME)
85
+
86
+ new_name = File.basename(file, File.extname(file))+File.extname(subs.first)
87
+ File.rename subs.first, new_name
88
+ puts "Renaming to #{new_name}"
89
+ end
90
+ end
91
+ end
data/suby.gemspec ADDED
@@ -0,0 +1,14 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'suby'
3
+ s.summary = "Subtitles' downloader"
4
+ s.description = "Find and download subtitles"
5
+ s.author = 'eregon'
6
+
7
+ s.files = Dir['bin/*', 'lib/**/*.rb', '.gitignore', 'README.md', 'suby.gemspec']
8
+ s.executables = ['suby']
9
+
10
+ s.required_ruby_version = '>= 1.9.2'
11
+ s.add_dependency 'nokogiri'
12
+
13
+ s.version = '0.0.6'
14
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: suby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,19 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-06-19 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2011-07-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: &2153880860 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2153880860
14
25
  description: Find and download subtitles
15
26
  email:
16
27
  executables:
@@ -19,7 +30,11 @@ extensions: []
19
30
  extra_rdoc_files: []
20
31
  files:
21
32
  - bin/suby
33
+ - lib/suby/downloader.rb
22
34
  - lib/suby.rb
35
+ - .gitignore
36
+ - README.md
37
+ - suby.gemspec
23
38
  homepage:
24
39
  licenses: []
25
40
  post_install_message:
@@ -31,7 +46,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
31
46
  requirements:
32
47
  - - ! '>='
33
48
  - !ruby/object:Gem::Version
34
- version: '0'
49
+ version: 1.9.2
35
50
  required_rubygems_version: !ruby/object:Gem::Requirement
36
51
  none: false
37
52
  requirements:
@@ -40,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
40
55
  version: '0'
41
56
  requirements: []
42
57
  rubyforge_project:
43
- rubygems_version: 1.8.5
58
+ rubygems_version: 1.8.5.1
44
59
  signing_key:
45
60
  specification_version: 3
46
61
  summary: Subtitles' downloader