bathyscaphe 0.1.0

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,2 @@
1
+ .DS_Store
2
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in bathyscaphe.gemspec
4
+ gemspec
@@ -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
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -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
@@ -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")
@@ -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
@@ -0,0 +1,3 @@
1
+ module Bathyscaphe
2
+ VERSION = "0.1.0"
3
+ 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
+