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.
- data/bin/suby +101 -0
- 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: []
|