suby 0.0.3

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.
Files changed (2) hide show
  1. data/bin/suby +101 -0
  2. metadata +46 -0
data/bin/suby ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ARGV.include? '-h'
4
+ puts "#{File.basename $0} video"
5
+ puts " Find and download subtitles for the given video file"
6
+ exit
7
+ end
8
+
9
+ require 'net/http'
10
+ require 'nokogiri'
11
+
12
+ SUB_EXTENSIONS = %w[srt sub]
13
+ archive = '__archive__'
14
+ site = 'www.tvsubtitles.net'
15
+ search_url = '/search.php'
16
+ lang = 'en'
17
+
18
+ def extract_subs_from_archive(archive)
19
+ case `file #{archive}`
20
+ when /Zip archive data/
21
+ subs = `unzip -qql #{archive}`.scan(/\d{2}:\d{2} (.+?(?:#{SUB_EXTENSIONS.join '|'}))$/).map(&:first)
22
+ raise "no subtitles in #{archive}" if subs.empty?
23
+ subs_for_unzip = subs.map { |sub| sub.gsub(/(\[|\])/) { "\\#{$1}" } }
24
+ system 'unzip', archive, *subs_for_unzip, 1 => :close
25
+ puts "found subtitles: #{subs.join(', ')}"
26
+ else
27
+ raise "unknown archive type (#{archive})"
28
+ end
29
+
30
+ # Cleaning
31
+ File.unlink archive
32
+ subs
33
+ end
34
+
35
+ # cache
36
+ show_urls = {}
37
+ show_pages = {}
38
+
39
+ ARGV.each { |file|
40
+ next if SUB_EXTENSIONS.include? File.extname(file)
41
+ next(puts "Skipping: #{file}") if SUB_EXTENSIONS.any? { |ext|
42
+ File.exist? File.basename(file, File.extname(file)) + ".#{ext}" }
43
+
44
+ unless /^(?<tvshow>.+) (?<season>\d{1,2})x(?<episode>\d{1,2}) - .+\.[a-z]+?$/ =~ file
45
+ next puts "wrong file format (#{file}). Must be:\n<tvshow> <season>x<episode> - <title>.<ext>"
46
+ end
47
+ season, episode = [season, episode].map(&:to_i)
48
+ puts "Searching subtitles for #{file}:"
49
+ puts "Show: #{tvshow}, Season: #{season}, Episode: #{episode}"
50
+
51
+ Net::HTTP.start(site) { |tvsubtitles|
52
+ # search tvshow
53
+ tvshow_url = (show_urls[tvshow] ||= begin
54
+ post = Net::HTTP::Post.new(search_url)
55
+ post.form_data = { 'q' => tvshow }
56
+ results = Nokogiri tvsubtitles.request(post).body
57
+ url = results.css('ul li div a').first[:href]
58
+
59
+ raise 'could not find the show' unless /^\/tvshow-(\d+)\.html$/ =~ url
60
+ "/tvshow-#{$1}-#{season}.html"
61
+ end)
62
+ puts "tvshow url: #{tvshow_url}"
63
+
64
+ # search episode
65
+ tvshow = (show_pages[tvshow] ||= Nokogiri tvsubtitles.get(tvshow_url).body)
66
+ tr = tvshow.css('div.left_articles table tr').find { |tr|
67
+ tr.children.find { |td| td.name == 'td' && td.text =~ /\A#{season}x0?#{episode}\z/ }
68
+ }
69
+ episode_url = nil
70
+ tr.children.find { |td|
71
+ td.children.find { |a|
72
+ a.name == 'a' && a[:href].start_with?('episode') && episode_url = a[:href]
73
+ }
74
+ }
75
+
76
+ raise "invalid episode url: #{episode_url}" unless episode_url =~ /^episode-(\d+)\.html$/
77
+ episode_url = "/episode-#{$1}-#{lang}.html"
78
+ puts "episode url: #{episode_url}"
79
+
80
+ # subtitles
81
+ subtitles = Nokogiri tvsubtitles.get(episode_url).body
82
+
83
+ # TODO: choose 720p or most downloaded instead of first found
84
+ subtitle_url = subtitles.css('div.left_articles a').find { |a| a.name == 'a' && a[:href].start_with?('/subtitle') }[:href]
85
+ raise 'invalid subtitle url' unless subtitle_url =~ /^\/subtitle-(\d+)\.html/
86
+ puts "subtitle url: #{subtitle_url}"
87
+
88
+ # download
89
+ download_url = tvsubtitles.get("/download-#{$1}.html")['Location']
90
+ download_url = URI.escape('/'+download_url)
91
+ puts "download url: #{download_url}"
92
+
93
+ # extract
94
+ zip = tvsubtitles.get(download_url).body
95
+ open(archive, 'wb') { |f| f.write zip }
96
+ subs = extract_subs_from_archive(archive)
97
+ new_name = File.basename(file, File.extname(file))+File.extname(subs.first)
98
+ File.rename(subs.first, new_name)
99
+ puts "Renaming to #{new_name}"
100
+ }
101
+ }
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: suby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - eregon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-15 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Find and download subtitles
15
+ email:
16
+ executables:
17
+ - suby
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - bin/suby
22
+ homepage:
23
+ licenses: []
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 1.8.5
43
+ signing_key:
44
+ specification_version: 3
45
+ summary: Subtitles' downloader
46
+ test_files: []