bathyscaphe 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/README.md +31 -0
- data/Rakefile +1 -0
- data/bathyscaphe.gemspec +24 -0
- data/bin/bathyscaphe +32 -0
- data/lib/bathyscaphe.rb +11 -0
- data/lib/bathyscaphe/addic7ed.rb +83 -0
- data/lib/bathyscaphe/config.rb +102 -0
- data/lib/bathyscaphe/tvdb.rb +19 -0
- data/lib/bathyscaphe/version.rb +3 -0
- metadata +84 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
Bathyscaphe
|
2
|
+
===========
|
3
|
+
|
4
|
+
Bathyscaphe is a command-line tool for downloading subtitles for tv-shows from addic7ed.com. Subtitles are searched based on tv-show file name. Downloaded subtitles are automatically renamed and saved next to corresponding files.
|
5
|
+
|
6
|
+
Existing solutions such as [Periscope](http://code.google.com/p/periscope/) and [Submarine](https://github.com/blazt/submarine) are more powerfull then bathyscaphe, they're using file hashes to search subtitles with API-powered services (Podnapisi, Opensubtitles, etc). And frankly, I use periscope myself most of the time. But they don't work in case of just released episodes of tv-shows. And going to addic7ed.com, every time new episode came out, is pain in the butt. So *bathyscaphe* to the rescue.
|
7
|
+
|
8
|
+
Be aware: there is a limit of 30 subs per day set by addic7ed.com.
|
9
|
+
|
10
|
+
### INSTALL
|
11
|
+
|
12
|
+
$ git clone git://github.com/ilzoff/bathyscaphe.git
|
13
|
+
$ cd bathyscaphe
|
14
|
+
$ gem install bones
|
15
|
+
$ rake gem:install
|
16
|
+
|
17
|
+
### USAGE
|
18
|
+
|
19
|
+
$ bathyscaphe [OPTIONS] TV_SHOW
|
20
|
+
|
21
|
+
#### Options
|
22
|
+
-d, --dry-run Parse filename but do not download anything
|
23
|
+
-h, --help Show usage
|
24
|
+
|
25
|
+
### TODO
|
26
|
+
|
27
|
+
1 Test regexp for matching more tv-show names
|
28
|
+
|
29
|
+
### Authors
|
30
|
+
|
31
|
+
- Ilia Zemskov (nbspace.ru) ilzoff@gmail.com
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bathyscaphe.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "bathyscaphe/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "bathyscaphe"
|
7
|
+
s.version = Bathyscaphe::VERSION
|
8
|
+
s.authors = ["Ilia Zemskov"]
|
9
|
+
s.email = ["il.zoff@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/ilzoff/bathyscaphe"
|
11
|
+
s.summary = %q{Simple gem to download subtitles from addic7ed.com}
|
12
|
+
s.description = %q{Simple gem to download subtitles for tv-show episodes from addic7ed.com. Subtitles are searched based on file name.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "bathyscaphe"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
s.add_runtime_dependency "nokogiri"
|
24
|
+
end
|
data/bin/bathyscaphe
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib bathyscaphe]))
|
4
|
+
|
5
|
+
file_arg = Bathyscaphe::Config.parse_options
|
6
|
+
|
7
|
+
unless File.exist? File.expand_path(file_arg)
|
8
|
+
puts "There's no such file: " + File.expand_path(file_arg)
|
9
|
+
exit 0
|
10
|
+
end
|
11
|
+
|
12
|
+
file_name = File.basename(file_arg)
|
13
|
+
file_dir = File.expand_path(File.dirname(file_arg))
|
14
|
+
|
15
|
+
|
16
|
+
begin
|
17
|
+
tv_show = Bathyscaphe::TVDB.new(file_name)
|
18
|
+
|
19
|
+
puts "TV Show: #{tv_show.name}"
|
20
|
+
puts "Season: #{tv_show.season}"
|
21
|
+
puts "Episode: #{tv_show.episode}"
|
22
|
+
|
23
|
+
rescue Exception => e
|
24
|
+
puts e
|
25
|
+
exit 0
|
26
|
+
end
|
27
|
+
|
28
|
+
exit if Bathyscaphe::Config::OPTIONS[:dry_run]
|
29
|
+
|
30
|
+
sub = Bathyscaphe::Addic7ed.new(tv_show.name, tv_show.season, tv_show.episode)
|
31
|
+
|
32
|
+
sub.save(file_dir + "/" + File.basename(file_name, ".*") + ".srt")
|
data/lib/bathyscaphe.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module Bathyscaphe
|
2
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
3
|
+
dir ||= ::File.basename(fname, '.*')
|
4
|
+
search_me = ::File.expand_path(
|
5
|
+
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
6
|
+
|
7
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Bathyscaphe.require_all_libs_relative_to(__FILE__)
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Bathyscaphe
|
2
|
+
require "nokogiri"
|
3
|
+
require "open-uri"
|
4
|
+
require 'net/http'
|
5
|
+
require "uri"
|
6
|
+
require "tempfile"
|
7
|
+
require "fileutils"
|
8
|
+
|
9
|
+
class Addic7ed
|
10
|
+
|
11
|
+
HTTP_HOST = "http://addic7ed.com"
|
12
|
+
HOST = "www.addic7ed.com"
|
13
|
+
|
14
|
+
def initialize(tv_show, season, episode)
|
15
|
+
@tv_show = tv_show
|
16
|
+
@season = season
|
17
|
+
@episode = episode
|
18
|
+
@temp_file = download
|
19
|
+
end
|
20
|
+
|
21
|
+
def download
|
22
|
+
|
23
|
+
uri = URI(HTTP_HOST + sub_link)
|
24
|
+
path = uri.path.empty? ? "/" : uri.path
|
25
|
+
|
26
|
+
headers = { "Host" => HOST,
|
27
|
+
"Referer" => show_page(:referer)
|
28
|
+
}
|
29
|
+
@temp_file = Tempfile.open("bathyscaphe_"+@tv_show+@season+@episode)
|
30
|
+
begin
|
31
|
+
Net::HTTP.start(uri.host, uri.port) { |http|
|
32
|
+
resp = http.get(path, headers)
|
33
|
+
@temp_file.write resp.body
|
34
|
+
raise "Limit exceeded" if resp.code.to_s == "302"
|
35
|
+
}
|
36
|
+
rescue Exception => e
|
37
|
+
puts e
|
38
|
+
ensure
|
39
|
+
@temp_file.close
|
40
|
+
end
|
41
|
+
@temp_file
|
42
|
+
end
|
43
|
+
|
44
|
+
def save local_path
|
45
|
+
@temp_file ||= download
|
46
|
+
FileUtils.mv(@temp_file.path, local_path)
|
47
|
+
end
|
48
|
+
|
49
|
+
def sub_link
|
50
|
+
html = Nokogiri::HTML(open(show_page(:lang)))
|
51
|
+
subtitles = {}
|
52
|
+
html.css(".tabel95 .newsDate").each do |td|
|
53
|
+
if downloads = td.text.match(/\s(\d*)\sDownloads/i)
|
54
|
+
done = false
|
55
|
+
td.parent.parent.xpath("./tr/td/a[@class='buttonDownload']/@href").each do |link|
|
56
|
+
if md = link.value.match(/updated/i)
|
57
|
+
subtitles[downloads[1].to_i] = link.value
|
58
|
+
done = true
|
59
|
+
elsif link.value.match(/original/i) && done == false
|
60
|
+
subtitles[downloads[1].to_i] = link.value
|
61
|
+
done = true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
subtitles = subtitles.sort
|
68
|
+
puts "Found subtitles with #{subtitles.last[0]} downloads: http://www.addic7ed.com#{subtitles.last[1]}"
|
69
|
+
subtitles.last[1]
|
70
|
+
end
|
71
|
+
|
72
|
+
def show_page(type)
|
73
|
+
link = URI::escape("http://www.addic7ed.com/serie/#{@tv_show}/#{@season}/#{@episode}/")
|
74
|
+
link += case type
|
75
|
+
when :referer
|
76
|
+
"addic7ed"
|
77
|
+
when :lang
|
78
|
+
"1"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require "optparse"
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
|
5
|
+
CONFIG_FILENAME = File.expand_path("~/.config/bathyscaphe/bathyscaphe.conf")
|
6
|
+
|
7
|
+
CONFIG_DEFAULTS = {
|
8
|
+
:source => 'http://addic7ed.com'
|
9
|
+
}
|
10
|
+
|
11
|
+
module Bathyscaphe
|
12
|
+
class Config
|
13
|
+
|
14
|
+
OPTIONS = {
|
15
|
+
:dry_run => false
|
16
|
+
}
|
17
|
+
|
18
|
+
def self.parse_options
|
19
|
+
optparser = OptionParser.new do |opts|
|
20
|
+
opts.set_summary_indent(' ')
|
21
|
+
opts.banner = "Usage: #{File.basename($0)} [OPTIONS] TV_SHOW"
|
22
|
+
# opts.on( "-s", "--source SOURCE", String, "Set source to download subtitles from","Current: #{self.source}" ) { |o| self.source = o ; self.save }
|
23
|
+
opts.on( "-d", "--dry-run", "Parse filename but do not download anything") { |o| OPTIONS[:dry_run] = o}
|
24
|
+
|
25
|
+
opts.on_tail( "-h", "--help", "Show usage") do
|
26
|
+
puts opts
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
end
|
30
|
+
# Parse command line
|
31
|
+
begin
|
32
|
+
optparser.parse!
|
33
|
+
if ARGV.empty?
|
34
|
+
puts optparser
|
35
|
+
exit
|
36
|
+
else
|
37
|
+
tv_show = ARGV[0]
|
38
|
+
end
|
39
|
+
rescue OptionParser::ParseError => e
|
40
|
+
puts e
|
41
|
+
puts optparser
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
return tv_show
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Loads configuration parameters.
|
49
|
+
#
|
50
|
+
def self.load
|
51
|
+
@params = CONFIG_DEFAULTS
|
52
|
+
if File.exists? config_filename
|
53
|
+
@params.merge! YAML::load_file( config_filename )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Writes configuration parameters, creating config directory and file
|
59
|
+
# if they do not exist.
|
60
|
+
#
|
61
|
+
def self.save
|
62
|
+
unless File.directory? config_dir
|
63
|
+
system "mkdir -p #{config_dir}"
|
64
|
+
end
|
65
|
+
File.open( config_filename, "w" ) do |f|
|
66
|
+
YAML::dump( @params, f )
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Returns a property with the given name.
|
72
|
+
#
|
73
|
+
def self.method_missing( name, *args )
|
74
|
+
if m = /^(.+)=$/.match(name.to_s)
|
75
|
+
# set
|
76
|
+
@params[m[1].to_sym] = args[0]
|
77
|
+
else
|
78
|
+
# get
|
79
|
+
@params[name.to_sym]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Returns full path to config file.
|
85
|
+
#
|
86
|
+
def self.config_filename
|
87
|
+
File.expand_path( CONFIG_FILENAME )
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Returns full path to the directory where config file is located.
|
92
|
+
#
|
93
|
+
def self.config_dir
|
94
|
+
File.dirname( config_filename )
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
Config.load
|
100
|
+
Config.save # creates default config on a fresh installation
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Bathyscaphe
|
2
|
+
class TVDB
|
3
|
+
|
4
|
+
TVREGEXP1 = /(.*)S([0-9]{2})E([0-9]{2}).*/i
|
5
|
+
TVREGEXP2 = /(.*).([0-9]{1,2})x([0-9]{1,2}).*/i
|
6
|
+
|
7
|
+
attr_accessor :name, :season, :episode
|
8
|
+
|
9
|
+
def initialize filename
|
10
|
+
if md = filename.match(TVREGEXP1) || md = filename.match(TVREGEXP2)
|
11
|
+
@name = md[1].gsub(".", " ").strip
|
12
|
+
@season = md[2].to_i.to_s
|
13
|
+
@episode = md[3].to_i.to_s
|
14
|
+
else
|
15
|
+
raise("Cant't parse filename")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bathyscaphe
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Ilia Zemskov
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2012-05-08 00:00:00 +04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: nokogiri
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
description: Simple gem to download subtitles for tv-show episodes from addic7ed.com. Subtitles are searched based on file name.
|
33
|
+
email:
|
34
|
+
- il.zoff@gmail.com
|
35
|
+
executables:
|
36
|
+
- bathyscaphe
|
37
|
+
extensions: []
|
38
|
+
|
39
|
+
extra_rdoc_files: []
|
40
|
+
|
41
|
+
files:
|
42
|
+
- .gitignore
|
43
|
+
- Gemfile
|
44
|
+
- README.md
|
45
|
+
- Rakefile
|
46
|
+
- bathyscaphe.gemspec
|
47
|
+
- bin/bathyscaphe
|
48
|
+
- lib/bathyscaphe.rb
|
49
|
+
- lib/bathyscaphe/addic7ed.rb
|
50
|
+
- lib/bathyscaphe/config.rb
|
51
|
+
- lib/bathyscaphe/tvdb.rb
|
52
|
+
- lib/bathyscaphe/version.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: https://github.com/ilzoff/bathyscaphe
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
rubyforge_project: bathyscaphe
|
79
|
+
rubygems_version: 1.3.6
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: Simple gem to download subtitles from addic7ed.com
|
83
|
+
test_files: []
|
84
|
+
|