bartzon-osdb 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.
@@ -0,0 +1,17 @@
1
+ Manifest
2
+ README.md
3
+ Rakefile
4
+ bin/getsub
5
+ lib/osdb.rb
6
+ lib/osdb/language.rb
7
+ lib/osdb/movie.rb
8
+ lib/osdb/options.rb
9
+ lib/osdb/server.rb
10
+ lib/osdb/sub.rb
11
+ osdb.gemspec
12
+ spec/fixtures/somemovie.avi
13
+ spec/osdb/language_spec.rb
14
+ spec/osdb/movie_spec.rb
15
+ spec/osdb/server_spec.rb
16
+ spec/osdb/sub_spec.rb
17
+ spec/spec_helper.rb
@@ -0,0 +1,31 @@
1
+ # OSDb
2
+
3
+ Client library for the [OSDb protocol](http://trac.opensubtitles.org/projects/opensubtitles/wiki/XMLRPC).
4
+ Currently the implentation is limited to movie identification and subtitles search
5
+
6
+ ## Examples
7
+
8
+ Just read the source of `bin/getsub` it is a typical example of OSDb's capacities.
9
+
10
+ ## getsub
11
+
12
+ The osdb gem provide a simple script to find and download the best subtitle on
13
+ [opensubtitles.org](http://www.opensubtitles.org/) for your video file.
14
+
15
+ ### Installation
16
+
17
+ $ gem install bartzon-osdb
18
+
19
+ ### Usage
20
+
21
+ You just have to execute `getsub` with some video files in arguments:
22
+
23
+ $ getsub somemovie.avi othermovie.mkv
24
+
25
+ Or specify a directory to search recursively:
26
+
27
+ $ getsub -d ~/Movies
28
+
29
+ For options details just run:
30
+
31
+ $ getsub --help
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'spec/rake/spectask'
4
+
5
+ Spec::Rake::SpecTask.new(:spec) do |spec|
6
+ spec.libs << 'lib' << 'spec'
7
+ spec.spec_files = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ begin
11
+ require 'echoe'
12
+
13
+ Echoe.new('bartzon-osdb', '0.0.6') do |p|
14
+ p.description = "Ruby library to access OSDb services like OpenSubtitles.org"
15
+ p.url = "http://github.com/bartzon/ruby-osdb"
16
+ p.author = "Jean Boussier, Bart Zonneveld"
17
+ p.email = "jean.boussier @nospam@ gmail.com, loop@superinfinite.com"
18
+ end
19
+
20
+ rescue LoadError => e
21
+ puts "Failed to load Echoe"
22
+ puts e.message
23
+ end
24
+
25
+ task :default => :spec
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{bartzon-osdb}
5
+ s.version = "0.0.6"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Jean Boussier, Bart Zonneveld"]
9
+ s.date = %q{2010-12-09}
10
+ s.default_executable = %q{getsub}
11
+ s.description = %q{Ruby library to access OSDb services like OpenSubtitles.org}
12
+ s.email = %q{jean.boussier @nospam@ gmail.com, loop@superinfinite.com}
13
+ s.executables = ["getsub"]
14
+ s.extra_rdoc_files = ["README.md", "bin/getsub", "lib/osdb.rb", "lib/osdb/language.rb", "lib/osdb/movie.rb", "lib/osdb/options.rb", "lib/osdb/server.rb", "lib/osdb/sub.rb"]
15
+ s.files = ["Manifest", "README.md", "Rakefile", "bin/getsub", "lib/osdb.rb", "lib/osdb/language.rb", "lib/osdb/movie.rb", "lib/osdb/options.rb", "lib/osdb/server.rb", "lib/osdb/sub.rb", "osdb.gemspec", "spec/fixtures/somemovie.avi", "spec/osdb/language_spec.rb", "spec/osdb/movie_spec.rb", "spec/osdb/server_spec.rb", "spec/osdb/sub_spec.rb", "spec/spec_helper.rb", "bartzon-osdb.gemspec"]
16
+ s.homepage = %q{http://github.com/bartzon/ruby-osdb}
17
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Bartzon-osdb", "--main", "README.md"]
18
+ s.require_paths = ["lib"]
19
+ s.rubyforge_project = %q{bartzon-osdb}
20
+ s.rubygems_version = %q{1.3.7}
21
+ s.summary = %q{Ruby library to access OSDb services like OpenSubtitles.org}
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 3
26
+
27
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
28
+ else
29
+ end
30
+ else
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ STDOUT.sync = true
4
+
5
+ require 'optparse'
6
+ require 'uri'
7
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'osdb')
8
+
9
+ OSDb::Sub.fetch_all
@@ -0,0 +1,37 @@
1
+ require 'xmlrpc/client'
2
+
3
+ module OSDb
4
+ base_path = File.expand_path(File.dirname(__FILE__) + '/osdb')
5
+ autoload :Language, "#{base_path}/language"
6
+ autoload :Movie, "#{base_path}/movie"
7
+ autoload :Server, "#{base_path}/server"
8
+ autoload :Sub, "#{base_path}/sub"
9
+ autoload :Options, "#{base_path}/options"
10
+
11
+ def self.log(str='')
12
+ puts str unless options[:silent]
13
+ end
14
+
15
+ def self.options
16
+ @@options ||= OSDb::Options.parse_options
17
+ end
18
+
19
+ def self.curl_available?
20
+ %x{ curl --version 2> /dev/null > /dev/null }
21
+ $?.success?
22
+ end
23
+
24
+ def self.wget_available?
25
+ %x{ wget --version 2> /dev/null > /dev/null }
26
+ $?.success?
27
+ end
28
+
29
+ def self.server
30
+ @@server ||= OSDb::Server.new(
31
+ :host => 'api.opensubtitles.org',
32
+ :path => '/xml-rpc',
33
+ :timeout => 90,
34
+ :useragent => "SubDownloader 2.0.10" # register useragent ? WTF ? too boring.
35
+ )
36
+ end
37
+ end
@@ -0,0 +1,84 @@
1
+ module OSDb
2
+
3
+ LANGUAGES = [
4
+ {:iso639_1 => 'sq', :iso639_2b => 'alb', :locale => 'sq', :name => 'Albanian'},
5
+ {:iso639_1 => 'ar', :iso639_2b => 'ara', :locale => 'ar', :name => 'Arabic'},
6
+ {:iso639_1 => 'hy', :iso639_2b => 'arm', :locale => 'hy', :name => 'Armenian'},
7
+ {:iso639_1 => 'ms', :iso639_2b => 'may', :locale => 'ms', :name => 'Malay'},
8
+ {:iso639_1 => 'bs', :iso639_2b => 'bos', :locale => 'bs', :name => 'Bosnian'},
9
+ {:iso639_1 => 'bg', :iso639_2b => 'bul', :locale => 'bg', :name => 'Bulgarian'},
10
+ {:iso639_1 => 'ca', :iso639_2b => 'cat', :locale => 'ca', :name => 'Catalan'},
11
+ {:iso639_1 => 'eu', :iso639_2b => 'eus', :locale => 'eu', :name => 'Basque'},
12
+ {:iso639_1 => 'zh', :iso639_2b => 'chi', :locale => 'zh_CN', :name => 'Chinese (China)'},
13
+ {:iso639_1 => 'hr', :iso639_2b => 'hrv', :locale => 'hr', :name => 'Croatian'},
14
+ {:iso639_1 => 'cs', :iso639_2b => 'cze', :locale => 'cs', :name => 'Czech'},
15
+ {:iso639_1 => 'da', :iso639_2b => 'dan', :locale => 'da', :name => 'Danish'},
16
+ {:iso639_1 => 'nl', :iso639_2b => 'dut', :locale => 'nl', :name => 'Dutch'},
17
+ {:iso639_1 => 'en', :iso639_2b => 'eng', :locale => 'en', :name => 'English (US)'},
18
+ {:iso639_1 => 'en', :iso639_2b => 'bre', :locale => 'en_GB', :name => 'English (UK)'},
19
+ {:iso639_1 => 'eo', :iso639_2b => 'epo', :locale => 'eo', :name => 'Esperanto'},
20
+ {:iso639_1 => 'et', :iso639_2b => 'est', :locale => 'et', :name => 'Estonian'},
21
+ {:iso639_1 => 'fi', :iso639_2b => 'fin', :locale => 'fi', :name => 'Finnish'},
22
+ {:iso639_1 => 'fr', :iso639_2b => 'fre', :locale => 'fr', :name => 'French'},
23
+ {:iso639_1 => 'gl', :iso639_2b => 'glg', :locale => 'gl', :name => 'Galician'},
24
+ {:iso639_1 => 'ka', :iso639_2b => 'geo', :locale => 'ka', :name => 'Georgian'},
25
+ {:iso639_1 => 'de', :iso639_2b => 'ger', :locale => 'de', :name => 'German'},
26
+ {:iso639_1 => 'el', :iso639_2b => 'ell', :locale => 'el', :name => 'Greek'},
27
+ {:iso639_1 => 'he', :iso639_2b => 'heb', :locale => 'he', :name => 'Hebrew'},
28
+ {:iso639_1 => 'hu', :iso639_2b => 'hun', :locale => 'hu', :name => 'Hungarian'},
29
+ {:iso639_1 => 'id', :iso639_2b => 'ind', :locale => 'id', :name => 'Indonesian'},
30
+ {:iso639_1 => 'it', :iso639_2b => 'ita', :locale => 'it', :name => 'Italian'},
31
+ {:iso639_1 => 'ja', :iso639_2b => 'jpn', :locale => 'ja', :name => 'Japanese'},
32
+ {:iso639_1 => 'kk', :iso639_2b => 'kaz', :locale => 'kk', :name => 'Kazakh'},
33
+ {:iso639_1 => 'ko', :iso639_2b => 'kor', :locale => 'ko', :name => 'Korean'},
34
+ {:iso639_1 => 'lv', :iso639_2b => 'lav', :locale => 'lv', :name => 'Latvian'},
35
+ {:iso639_1 => 'lt', :iso639_2b => 'lit', :locale => 'lt', :name => 'Lithuanian'},
36
+ {:iso639_1 => 'lb', :iso639_2b => 'ltz', :locale => 'lb', :name => 'Luxembourgish'},
37
+ {:iso639_1 => 'mk', :iso639_2b => 'mac', :locale => 'mk', :name => 'Macedonian'},
38
+ {:iso639_1 => 'no', :iso639_2b => 'nor', :locale => 'no', :name => 'Norwegian'},
39
+ {:iso639_1 => 'fa', :iso639_2b => 'per', :locale => 'fa', :name => 'Persian'},
40
+ {:iso639_1 => 'pl', :iso639_2b => 'pol', :locale => 'pl', :name => 'Polish'},
41
+ {:iso639_1 => 'pt', :iso639_2b => 'por', :locale => 'pt_PT', :name => 'Portuguese (Portugal)'},
42
+ {:iso639_1 => 'pb', :iso639_2b => 'pob', :locale => 'pt_BR', :name => 'Portuguese (Brazil)'},
43
+ {:iso639_1 => 'ro', :iso639_2b => 'rum', :locale => 'ro', :name => 'Romanian'},
44
+ {:iso639_1 => 'ru', :iso639_2b => 'rus', :locale => 'ru', :name => 'Russian'},
45
+ {:iso639_1 => 'sr', :iso639_2b => 'scc', :locale => 'sr', :name => 'Serbian'},
46
+ {:iso639_1 => 'sk', :iso639_2b => 'slo', :locale => 'sk', :name => 'Slovak'},
47
+ {:iso639_1 => 'sl', :iso639_2b => 'slv', :locale => 'sl', :name => 'Slovenian'},
48
+ {:iso639_1 => 'es', :iso639_2b => 'spa', :locale => 'es_ES', :name => 'Spanish (Spain)'},
49
+ {:iso639_1 => 'sv', :iso639_2b => 'swe', :locale => 'sv', :name => 'Swedish'},
50
+ {:iso639_1 => 'th', :iso639_2b => 'tha', :locale => 'th', :name => 'Thai'},
51
+ {:iso639_1 => 'tr', :iso639_2b => 'tur', :locale => 'tr', :name => 'Turkish'},
52
+ {:iso639_1 => 'uk', :iso639_2b => 'ukr', :locale => 'uk', :name => 'Ukrainian'},
53
+ {:iso639_1 => 'vi', :iso639_2b => 'vie', :locale => 'vi', :name => 'Vietnamese'}
54
+ ]
55
+
56
+ class Language
57
+
58
+ class << self
59
+
60
+ def from_locale(locale)
61
+ locale = locale.split('.').first
62
+ lang = LANGUAGES.find{ |lang| lang[:locale] == locale }
63
+ return from_locale(locale.split('_').first) if !lang && locale.include?('_')
64
+ new(lang)
65
+ end
66
+
67
+ def from_iso639_2b(code)
68
+ new(LANGUAGES.find{ |lang| lang[:iso639_2b] == code })
69
+ end
70
+
71
+ end
72
+
73
+ attr_reader :name, :to_iso639_1, :to_iso639_2b, :to_locale
74
+
75
+ def initialize(hash)
76
+ @name = hash[:name]
77
+ @to_iso639_1 = hash[:iso639_1]
78
+ @to_iso639_2b = hash[:iso639_2b]
79
+ @to_locale = hash[:locale]
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,81 @@
1
+ module OSDb
2
+ class Movie
3
+
4
+ attr_reader :path
5
+
6
+ class << self
7
+ def get_movie_list
8
+
9
+ if dir = OSDb.options[:dir]
10
+ path = Dir.glob(File.join(dir, '**', "*.{#{OSDb.options[:movie_exts]}}"))
11
+ movies = path.map { |path| new(path) }
12
+ else
13
+ movies = ARGV.map{ |path| OSDb::Movie.new(path) }
14
+ end
15
+ movies.reject!(&:has_sub?) unless OSDb.options[:force]
16
+
17
+ if movies.empty?
18
+ OSDb.log "All movies in #{dir} already have subtitles."
19
+ exit 1
20
+ end
21
+
22
+ movies
23
+ end
24
+ end
25
+
26
+ def initialize(path)
27
+ @path = path
28
+ end
29
+
30
+ def has_sub?
31
+ exist = false
32
+ %w(.srt .sub .smi).each{ |ext| exist ||= File.exist?(path.gsub(File.extname(path), ext)) }
33
+ exist
34
+ end
35
+
36
+ def sub_path(format)
37
+ path.gsub(File.extname(path), ".#{format}")
38
+ end
39
+
40
+ def hash
41
+ @hash ||= self.class.compute_hash(path)
42
+ end
43
+
44
+ def size
45
+ @size ||= File.size(path)
46
+ end
47
+
48
+ CHUNK_SIZE = 64 * 1024 # in bytes
49
+
50
+ # from http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes
51
+ def self.compute_hash(path)
52
+ begin
53
+ filesize = File.size(path)
54
+ hash = filesize
55
+
56
+ # Read 64 kbytes, divide up into 64 bits and add each
57
+ # to hash. Do for beginning and end of file.
58
+ File.open(path, 'rb') do |f|
59
+ # Q = unsigned long long = 64 bit
60
+ f.read(CHUNK_SIZE).unpack("Q*").each do |n|
61
+ hash = hash + n & 0xffffffffffffffff # to remain as 64 bit number
62
+ end
63
+
64
+ f.seek([0, filesize - CHUNK_SIZE].max, IO::SEEK_SET)
65
+
66
+ # And again for the end of the file
67
+ f.read(CHUNK_SIZE).unpack("Q*").each do |n|
68
+ hash = hash + n & 0xffffffffffffffff
69
+ end
70
+ end
71
+
72
+ sprintf("%016x", hash)
73
+ rescue Errno::EPERM
74
+ OSDb.log("* could not read #{path}")
75
+ rescue RuntimeError
76
+ OSDb.log("* could not read #{path}")
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,51 @@
1
+ module OSDb
2
+ class Options
3
+
4
+ class << self
5
+ def env_lang
6
+ OSDb::Language.from_locale(ENV['LANG'])
7
+ end
8
+
9
+ def parse_options
10
+ @@options = {:languages => [env_lang.to_iso639_2b], :force => false, :dir => nil, :silent => false, :movie_exts => %w{avi,mpg,m4v,mkv,mov,ogv,divx} }
11
+
12
+ @@parser ||= OptionParser.new do |opts|
13
+ opts.banner = "Automatically download subs for your video files using opensubtitles.org"
14
+ opts.separator ""
15
+ opts.separator "Usage: getsub [options] DIRECTORY | VIDEO_FILE [VIDEO_FILE ...]"
16
+ opts.separator ""
17
+ opts.separator "Main options:"
18
+
19
+ opts.on("-e", "--extensions EXTENSIONS", "Movie extensions to search for when using --directory. Default: #{@@options[:movie_exts].join(',')}") do |exts|
20
+ @@options[:movie_exts] = exts.split(',')
21
+ end
22
+
23
+ opts.on("-l", "--languages LANGUAGES", "Sub language ISO 963 code separated by comma's like fre or eng. Default: env $LANG (#{env_lang.to_iso639_2b})") do |languages|
24
+ @@options[:languages] = languages.split(',')
25
+ end
26
+
27
+ opts.on("-d", "--directory DIRECTORY", "Specify a directory to search recursively for movies") do |dir|
28
+ @@options[:dir] = dir
29
+ end
30
+
31
+ opts.on("-f", "--force", "Download sub even if video already has one") { @@options[:force] = true }
32
+
33
+ opts.on("-s", "--silent", "Don't output anything") { options[:silent] = true }
34
+ end
35
+ @@parser.parse!
36
+
37
+ if !@@options[:dir] && ARGV.empty?
38
+ help
39
+ exit 1
40
+ end
41
+
42
+ @@options
43
+ end
44
+
45
+ def help
46
+ puts @@parser.help
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,53 @@
1
+ module OSDb
2
+
3
+ class LoginFailed < ::Exception
4
+ end
5
+
6
+ class Server
7
+
8
+ attr_reader :username, :password, :language, :useragent, :client
9
+
10
+ def initialize(options={})
11
+ @username = options[:username] || ''
12
+ @password = options[:password] || ''
13
+ @language = options[:language] || 'eng'
14
+ @useragent = options[:useragent] || 'ruby-osdb v0.1'
15
+ @client = ::XMLRPC::Client.new(*options.values_at(:host, :path, :port, :proxy_host, :proxy_port, :http_user, :http_password, :use_ssl, :timeout))
16
+ end
17
+
18
+ def token
19
+ @token ||= login
20
+ end
21
+
22
+ def login
23
+ response = client.call('LogIn', username, password, language, useragent)
24
+ if response['status'] != '200 OK'
25
+ raise LoginFailed.new("Failed to login with #{username} : #{password}. Server return code: #{response['status']}")
26
+ end
27
+ response['token']
28
+ end
29
+
30
+ def logout
31
+ client.call('LogOut', token)
32
+ @token = nil
33
+ end
34
+
35
+ def check_movie_hash(*hashes)
36
+ client.call('CheckMovieHash', token, hashes)
37
+ end
38
+
39
+ def search_subtitles(*queries)
40
+ subs = client.call('SearchSubtitles', token, queries)['data']
41
+ subs ? subs.map{ |s| Sub.new(s) } : []
42
+ rescue EOFError
43
+ []
44
+ rescue RuntimeError
45
+ []
46
+ end
47
+
48
+ def info
49
+ client.call('ServerInfo')
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,91 @@
1
+ require 'uri'
2
+
3
+ module OSDb
4
+
5
+ class Sub
6
+
7
+ attr_reader :url, :format, :language, :rating, :movie_name, :raw_data
8
+
9
+ class << self
10
+ def fetch_all
11
+ movies = Movie.get_movie_list
12
+
13
+ movies.each do |movie|
14
+ begin
15
+ OSDb.log "* search subs for: #{movie.path}"
16
+ subs = OSDb.server.search_subtitles(:moviehash => movie.hash, :moviebytesize => movie.size, :sublanguageid => OSDb.options[:languages].join(','))
17
+ if subs.any?
18
+ if sub = select_sub(subs)
19
+ sub_path = movie.sub_path(sub.format)
20
+ Sub.download!(sub.url, sub_path)
21
+ end
22
+ else
23
+ OSDb.log "* no sub found"
24
+ end
25
+ OSDb.log
26
+ end
27
+ end
28
+ end
29
+
30
+ def download!(url, local_path)
31
+ OSDb.log "* download #{url} to #{local_path}"
32
+ if OSDb.curl_available?
33
+ %x{ curl -s '#{url}' | gunzip > "#{local_path}" }
34
+ elsif OSDb.wget_available?
35
+ %x{ wget -O -quiet - '#{url}' | gunzip > "#{local_path}"}
36
+ else
37
+ OSDb.log "Can't found any curl or wget please install one of them or manualy download your sub"
38
+ OSDb.log url
39
+ end
40
+ end
41
+
42
+ private
43
+ def select_sub(subs)
44
+ return subs.first if subs.length == 1
45
+ movies = group_by_movie_name(subs)
46
+ return movies.values.first.max if movies.length == 1
47
+ if selected_movie_subs = ask_user_to_identify_movie(movies)
48
+ selected_movie_subs.max
49
+ else
50
+ nil
51
+ end
52
+ end
53
+
54
+ def group_by_movie_name(subs)
55
+ subs.inject({}) do |hash, sub|
56
+ hash[sub.movie_name] ||= []
57
+ hash[sub.movie_name] << sub
58
+ hash
59
+ end
60
+ end
61
+
62
+ def ask_user_to_identify_movie(movies)
63
+ puts "D'oh! You stumbled upon a hash conflict, please resolve it:"
64
+ puts
65
+ puts " 0 - none of the below"
66
+ movies.keys.each_with_index do |name, index|
67
+ puts " #{index+1} - #{name}"
68
+ end
69
+ puts
70
+ print 'id: '
71
+ str = STDIN.gets.to_i
72
+ str == 0 ? false : movies[movies.keys[str.to_i]]
73
+ end
74
+ end
75
+
76
+ def initialize(data)
77
+ @url = URI.parse(data['SubDownloadLink'])
78
+ @format = data['SubFormat']
79
+ @language = Language.from_iso639_2b(data['SubLanguageID'])
80
+ @rating = data['SubRating'].to_f
81
+ @movie_name = data['MovieName']
82
+ @raw_data = data
83
+ end
84
+
85
+ def <=>(other)
86
+ rating <=> other.rating
87
+ end
88
+
89
+ end
90
+
91
+ end
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{osdb}
5
+ s.version = "0.0.5"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Jean Boussier, Bart Zonneveld"]
9
+ s.date = %q{2010-12-09}
10
+ s.default_executable = %q{getsub}
11
+ s.description = %q{Ruby library to access OSDb services like OpenSubtitles.org}
12
+ s.email = %q{jean.boussier @nospam@ gmail.com, loop@superinfinite.com}
13
+ s.executables = ["getsub"]
14
+ s.extra_rdoc_files = ["README.md", "bin/getsub", "lib/osdb.rb", "lib/osdb/language.rb", "lib/osdb/movie.rb", "lib/osdb/server.rb", "lib/osdb/sub.rb", "lib/osdb/options.rb"]
15
+ s.files = FileList['lib/**/*.rb', 'bin/*', '[A-Z]*', 'spec/**/*'].to_a
16
+ s.homepage = %q{http://github.com/bartzon/ruby-osdb}
17
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Osdb", "--main", "README.md"]
18
+ s.require_paths = ["lib"]
19
+ s.rubyforge_project = %q{osdb}
20
+ s.rubygems_version = %q{1.3.7}
21
+ s.summary = %q{Ruby library to access OSDb services like OpenSubtitles.org}
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 3
26
+
27
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
28
+ else
29
+ end
30
+ else
31
+ end
32
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe OSDb::Language do
4
+
5
+ describe '.from_locale' do
6
+
7
+ describe "simple locale" do
8
+
9
+ subject{ OSDb::Language.from_locale('fr') }
10
+
11
+ its(:name) { should == 'French' }
12
+
13
+ its(:to_iso639_1) { should == 'fr' }
14
+
15
+ its(:to_iso639_2b) { should == 'fre' }
16
+
17
+ end
18
+
19
+ describe "locale with territory" do
20
+
21
+ subject{ OSDb::Language.from_locale('en_US') }
22
+
23
+ its(:name) { should == 'English (US)' }
24
+
25
+ its(:to_iso639_1) { should == 'en' }
26
+
27
+ its(:to_iso639_2b) { should == 'eng' }
28
+
29
+ end
30
+
31
+ describe "locale with territory and encoding" do
32
+
33
+ subject{ OSDb::Language.from_locale('es_ES.UTF8') }
34
+
35
+ its(:name) { should == 'Spanish (Spain)' }
36
+
37
+ its(:to_iso639_1) { should == 'es' }
38
+
39
+ its(:to_iso639_2b) { should == 'spa' }
40
+
41
+ end
42
+
43
+ end
44
+
45
+ describe ".from_iso_639_2b" do
46
+
47
+ subject{ OSDb::Language.from_iso639_2b('bre') }
48
+
49
+ its(:name) { should == 'English (UK)' }
50
+
51
+ its(:to_iso639_1) { should == 'en' }
52
+
53
+ its(:to_locale) { should == 'en_GB' }
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe OSDb::Movie do
4
+
5
+ subject do
6
+ OSDb::Movie.new(File.dirname(__FILE__) + '/../fixtures/somemovie.avi')
7
+ end
8
+
9
+ its(:hash) { should == '243339b48f4e8741' }
10
+
11
+ end
@@ -0,0 +1,79 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe OSDb::Server do
4
+
5
+ before :all do
6
+ @server = OSDb::Server.new(
7
+ :host => 'api.opensubtitles.org',
8
+ :path => '/xml-rpc',
9
+ :timeout => 60, # OS.org is very very slow ....
10
+ :useragent => 'OS Test User Agent'
11
+ )
12
+ end
13
+
14
+ subject { @server }
15
+
16
+ it 'should respond to #info' do
17
+ hash_including(
18
+ "seconds" => instance_of(Float),
19
+ "last_update_strings" => instance_of(Hash),
20
+ "website_url"=>"http://www.opensubtitles.org",
21
+ "contact"=>"admin@opensubtitles.org",
22
+ "application"=>"OpenSuber v0.2",
23
+ "xmlrpc_version"=>"0.1",
24
+ "xmlrpc_url"=>"http://api.opensubtitles.net/xml-rpc"
25
+ ).should == subject.info
26
+ end
27
+
28
+ it 'should automatically call #login when token is needed' do
29
+ subject.instance_variable_get('@token').should be_nil
30
+ subject.token.should match(/[a-z0-9]{26}/)
31
+ subject.instance_variable_get('@token').should == subject.token
32
+ end
33
+
34
+ it 'should clear @login after #logout' do
35
+ expect{
36
+ subject.logout
37
+ }.to change{ subject.instance_variable_get('@token') }.from(instance_of(String)).to(nil)
38
+ end
39
+
40
+ describe "#check_movie_hash" do
41
+
42
+ it 'should identify movie' do
43
+ subject.check_movie_hash('37d0c7d0cfcbe280')['data'].should == {
44
+ "37d0c7d0cfcbe280" => {
45
+ "MovieYear" => "1996",
46
+ "MovieImdbID" => "0117500",
47
+ "MovieName" => "The Rock",
48
+ "MovieHash" => "37d0c7d0cfcbe280"
49
+ }
50
+ }
51
+ end
52
+
53
+ end
54
+
55
+ describe '#search_subtitles' do
56
+
57
+ it 'can search by hash and size' do
58
+ subs = subject.search_subtitles(:moviehash => 'bd71526264fd8bd9', :moviebytesize => '183406990', :sublanguageid => 'fre')
59
+ subs.should be_a(Array)
60
+ subs.length.should >= 2
61
+ subs.each do |sub|
62
+ sub.language.name.should == 'French'
63
+ sub.raw_data['MovieName'].should == '"How I Met Your Mother"'
64
+ end
65
+ end
66
+
67
+ it 'can search by imdbid' do
68
+ subs = subject.search_subtitles(:imdbid => "0117500", :sublanguageid => 'fre')
69
+ subs.should be_a(Array)
70
+ subs.length.should >= 1
71
+ subs.each do |sub|
72
+ sub.language.name.should == 'French'
73
+ sub.raw_data['MovieName'].should == 'The Rock'
74
+ end
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe OSDb::Sub do
4
+
5
+ before :each do
6
+ @response = {
7
+ 'SubFormat' => 'srt',
8
+ 'SubDownloadLink' => 'http://example.com/foo.srt.gz',
9
+ 'SubRating' => '7.89',
10
+ 'SubLanguageID' => 'dut',
11
+ 'MovieName' => 'Lock, Stock and Two Smoking Barrels'
12
+ }
13
+ end
14
+
15
+ subject do
16
+ OSDb::Sub.new @response
17
+ end
18
+
19
+ its(:format) { should == 'srt' }
20
+
21
+ its(:url) { should be_an(URI::HTTP) }
22
+
23
+ its(:language) { should be_a(OSDb::Language) }
24
+
25
+ its(:rating) { should == 7.89 }
26
+
27
+ its(:movie_name) { should == 'Lock, Stock and Two Smoking Barrels' }
28
+
29
+ it 'should be comparable' do
30
+ [subject, OSDb::Sub.new(@response.merge('SubRating' => '2.45'))].max.should == subject
31
+ end
32
+
33
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/../lib/osdb'
2
+ require 'spec/autorun'
3
+
4
+ # Spec Helpers
5
+ Dir[File.dirname(__FILE__) + '/*_spec_helper.rb'].each do |f|
6
+ require File.expand_path(f)
7
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bartzon-osdb
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 6
10
+ version: 0.0.6
11
+ platform: ruby
12
+ authors:
13
+ - Jean Boussier, Bart Zonneveld
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-09 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Ruby library to access OSDb services like OpenSubtitles.org
23
+ email: jean.boussier @nospam@ gmail.com, loop@superinfinite.com
24
+ executables:
25
+ - getsub
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.md
30
+ - bin/getsub
31
+ - lib/osdb.rb
32
+ - lib/osdb/language.rb
33
+ - lib/osdb/movie.rb
34
+ - lib/osdb/options.rb
35
+ - lib/osdb/server.rb
36
+ - lib/osdb/sub.rb
37
+ files:
38
+ - Manifest
39
+ - README.md
40
+ - Rakefile
41
+ - bin/getsub
42
+ - lib/osdb.rb
43
+ - lib/osdb/language.rb
44
+ - lib/osdb/movie.rb
45
+ - lib/osdb/options.rb
46
+ - lib/osdb/server.rb
47
+ - lib/osdb/sub.rb
48
+ - osdb.gemspec
49
+ - spec/fixtures/somemovie.avi
50
+ - spec/osdb/language_spec.rb
51
+ - spec/osdb/movie_spec.rb
52
+ - spec/osdb/server_spec.rb
53
+ - spec/osdb/sub_spec.rb
54
+ - spec/spec_helper.rb
55
+ - bartzon-osdb.gemspec
56
+ has_rdoc: true
57
+ homepage: http://github.com/bartzon/ruby-osdb
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --line-numbers
63
+ - --inline-source
64
+ - --title
65
+ - Bartzon-osdb
66
+ - --main
67
+ - README.md
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 11
85
+ segments:
86
+ - 1
87
+ - 2
88
+ version: "1.2"
89
+ requirements: []
90
+
91
+ rubyforge_project: bartzon-osdb
92
+ rubygems_version: 1.3.7
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: Ruby library to access OSDb services like OpenSubtitles.org
96
+ test_files: []
97
+