osdb 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ rvm:
2
+ - 1.8.7 # (current default)
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - rbx
6
+ - jruby
7
+ - ruby-head
8
+ - ree
9
+
data/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  Client library for the [OSDb protocol](http://trac.opensubtitles.org/projects/opensubtitles/wiki/XMLRPC).
4
4
  Currently the implentation is limited to movie identification and subtitles search
5
5
 
6
+ [![Build Status](https://secure.travis-ci.org/byroot/ruby-osdb.png)](http://travis-ci.org/byroot/ruby-osdb)
7
+
6
8
  ## Examples
7
9
 
8
10
  Just read the source of `bin/getsub` it is a typical example of OSDb's capacities.
data/bin/getsub CHANGED
@@ -16,16 +16,23 @@ end
16
16
  opts.separator "Usage: getsub [options] DIRECTORY | VIDEO_FILE [VIDEO_FILE ...]"
17
17
  opts.separator ""
18
18
  opts.separator "Main options:"
19
-
20
- opts.on("-l", "--language LANGUAGE", "Sub language ISO 963 code like fre or eng. Default: env $LANG (#{env_lang.to_iso639_2b})") do |language|
21
- @options[:language] = language
19
+
20
+ opts.on("-l", "--language LANGUAGE", "Sub language ISO 639-2 code like fre or eng. Default: env $LANG (#{env_lang.to_iso639_2b})") do |language|
21
+ if language.to_s.length != 3
22
+ STDERR.puts "Language should specified as ISO 639-2 (ie, 3 letters, like 'eng' or 'fre')"
23
+ exit 1
24
+ end
25
+ @options[:language] = language.to_s
22
26
  end
23
-
27
+
24
28
  opts.on("-d", "--directory DIRECTORY", "Specify a directory to search recursively for movies") do |dir|
25
29
  @options[:dir] = dir
26
30
  end
27
31
 
28
32
  opts.on("-f", "--force", "Download sub even if video already has one") { @options[:force] = true }
33
+
34
+ opts.on("-t", "--type FORMATS", "Select only subtitles in specified formats. e.g -t srt,sub") { |formats| @options[:formats] = formats.to_s.split(',') }
35
+
29
36
  end
30
37
  @parser.parse!
31
38
 
@@ -66,44 +73,34 @@ def ask_user_to_identify_movie(movies)
66
73
  print 'id: '
67
74
  str = STDIN.gets # TODO: rule #1, never trust user input
68
75
  puts
69
- movies[movies.keys[str.to_i]]
76
+ movies[movies.keys[str.to_i]] || []
70
77
  end
71
78
 
72
- def identify_by_imdb!(server, movie)
73
- puts "* could not find sub by hash, trying IMDB"
74
- imdb_results = server.search_imdb(:query => movie.name)
75
- if imdb_results.any?
76
- if imdb_results.length == 1
77
- imdb_result = imdb_results.first
78
- puts "* found on IMDB with ID: #{imdb_result.imdbid}"
79
- else
80
- movies = Hash[imdb_results.map{ |r| [r.title, r] }]
81
- imdb_result = ask_user_to_identify_movie(movies)
82
- end
83
- subs = server.search_subtitles(:sublanguageid => @options[:language], :imdbid => imdb_result.imdbid)
84
- if subs.any?
85
- select_and_download!(subs, movie)
86
- else
87
- puts "* no sub found for this movie"
88
- end
89
- else
90
- puts "* no movie found on IMDB"
91
- end
79
+ def normalize_name(name)
80
+ name.downcase.gsub(/[\s\.\-\_]+/, ' ')
92
81
  end
93
82
 
94
- def select_sub(subs)
95
- return subs.first if subs.length >= 1
96
- movies = group_by_movie_name(subs)
97
- return movies.values.first.max if movies.length == 1
83
+ def select_movie(movies)
84
+ return movies.values.first || [] if movies.length <= 1
98
85
 
99
86
  puts "D'oh! You stumbled upon a hash conflict, please resolve it:"
100
87
  puts
101
- selected_movie_subs = ask_user_to_identify_movie(movies)
102
- selected_movie_subs.max
88
+ ask_user_to_identify_movie(movies)
89
+ end
90
+
91
+ def select_format(subs)
92
+ return subs unless @options[:formats]
93
+ subs.select{ |s| @options[:formats].include?(s.format) }
94
+ end
95
+
96
+ def select_sub(subs)
97
+ subs = select_format(subs)
98
+ movies = group_by_movie_name(subs)
99
+ subs = select_movie(movies)
100
+ subs.max_by(&:score)
103
101
  end
104
102
 
105
- def select_and_download!(subs, movie)
106
- sub = select_sub(subs)
103
+ def download_sub!(sub, movie)
107
104
  sub_path = movie.sub_path(sub.format)
108
105
  download!(sub.url, sub_path)
109
106
  end
@@ -130,17 +127,70 @@ if movies.empty?
130
127
  exit 1
131
128
  end
132
129
 
130
+ def search_by_hash(server, movie)
131
+ server.search_subtitles(:moviehash => movie.hash, :moviebytesize => movie.size.to_s, :sublanguageid => @options[:language])
132
+ end
133
+
134
+ def search_by_path(server, movie)
135
+ server.search_subtitles(:sublanguageid => @options[:language], :tag => movie.path)
136
+ end
137
+
138
+ def search_by_name(server, movie)
139
+ subs = server.search_subtitles(:sublanguageid => @options[:language], :query => movie.name)
140
+ normalized_movie_name = normalize_name(movie.name)
141
+ subs.select! do |sub|
142
+ normalize_name(sub.filename).index(normalized_movie_name) # MAYBE: Levenshtein ?
143
+ end
144
+ subs if subs.any?
145
+ end
146
+
147
+ def search_by_imdb(server, movie)
148
+ imdb_results = server.search_imdb(:query => movie.name)
149
+ if imdb_results.any?
150
+ if imdb_results.length == 1
151
+ imdb_result = imdb_results.first
152
+ puts "* found on IMDB with ID: #{imdb_result.imdbid}"
153
+ else
154
+ movies = Hash[imdb_results.map{ |r| [r.title, r] }]
155
+ imdb_result = ask_user_to_identify_movie(movies)
156
+ end
157
+ server.search_subtitles(:sublanguageid => @options[:language], :imdbid => imdb_result.imdbid)
158
+ end
159
+ end
160
+
133
161
  movies.each do |movie|
134
162
  begin
135
- puts "* search subs for: #{movie.path}"
136
- subs = server.search_subtitles(:moviehash => movie.hash, :moviebytesize => movie.size.to_s, :sublanguageid => @options[:language])
137
- if subs.any?
138
- select_and_download!(subs, movie)
163
+ puts "* search subs by hash for: #{movie.path}"
164
+ sub = select_sub search_by_hash(server, movie)
165
+
166
+ unless sub
167
+ puts "* could not find sub by hash, trying IMDB"
168
+ sub = select_sub search_by_imdb(server, movie)
169
+ end
170
+
171
+ unless sub
172
+ puts "* no matches"
173
+ puts "* search subs by path"
174
+ sub = select_sub search_by_path(server, movie)
175
+ end
176
+
177
+ unless sub
178
+ puts "* still no matches"
179
+ puts "* search subs by filename"
180
+ sub = select_sub search_by_name(server, movie)
181
+ end
182
+
183
+ if sub
184
+ download_sub!(sub, movie)
139
185
  else
140
- identify_by_imdb!(server, movie)
186
+ puts "Nothing worked, you are very unlucky :'("
141
187
  end
142
188
  puts
143
189
  rescue Exception => e
190
+ puts "Something crashed."
191
+ puts "Feel free to report the error here: https://github.com/byroot/ruby-osdb/issues"
192
+ puts "With the following debug informations:"
193
+ puts
144
194
  puts "#{e.class.name}: #{e.message}:"
145
195
  puts e.backtrace
146
196
  end
data/lib/osdb/sub.rb CHANGED
@@ -1,24 +1,40 @@
1
1
  require 'uri'
2
2
 
3
3
  module OSDb
4
-
4
+
5
5
  class Sub
6
-
7
- attr_reader :url, :format, :language, :rating, :movie_name, :raw_data
8
-
6
+
7
+ attr_reader :url, :format, :language, :rating, :user_ranks, :movie_name,
8
+ :filename, :raw_data, :downloads_count, :bad_reports_count
9
+
9
10
  def initialize(data)
10
11
  @url = URI.parse(data['SubDownloadLink'])
11
12
  @format = data['SubFormat']
12
13
  @language = Language.from_iso639_2b(data['SubLanguageID'])
13
14
  @rating = data['SubRating'].to_f
15
+ @user_ranks = data['UserRank']
14
16
  @movie_name = data['MovieName']
17
+ @filename = data['SubFileName']
18
+ @downloads_count = data['SubDownloadsCnt'].to_i
19
+ @bad_reports_count = data['SubBad'].to_i
15
20
  @raw_data = data
16
21
  end
17
-
22
+
18
23
  def <=>(other)
19
24
  rating <=> other.rating
20
25
  end
21
-
26
+
27
+ # Totaly subjective formula to evaluate subtitle quality
28
+ # Originaly developed by runa (https://github.com/runa)
29
+ # https://github.com/byroot/ruby-osdb/commit/9d71775#L0R122
30
+ def score
31
+ uploader_score * downloads_count.next * (rating + 1) - bad_reports_count / downloads_count.next
32
+ end
33
+
34
+ def uploader_score
35
+ user_ranks.empty? ? 1 : 2
36
+ end
37
+
22
38
  end
23
-
24
- end
39
+
40
+ end
data/lib/osdb/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module OSDb
2
- VERSION = '0.0.9'
2
+ VERSION = '0.0.10'
3
3
  end
data/osdb.gemspec CHANGED
@@ -17,5 +17,6 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
+ s.add_development_dependency 'rake'
20
21
  s.add_development_dependency 'rspec'
21
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-12 00:00:00.000000000 Z
12
+ date: 2012-08-26 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &70311392052000 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70311392052000
14
25
  - !ruby/object:Gem::Dependency
15
26
  name: rspec
16
- requirement: &70099189686620 !ruby/object:Gem::Requirement
27
+ requirement: &70311392067940 !ruby/object:Gem::Requirement
17
28
  none: false
18
29
  requirements:
19
30
  - - ! '>='
@@ -21,7 +32,7 @@ dependencies:
21
32
  version: '0'
22
33
  type: :development
23
34
  prerelease: false
24
- version_requirements: *70099189686620
35
+ version_requirements: *70311392067940
25
36
  description:
26
37
  email:
27
38
  - jean.boussier @nospam@ gmail.com
@@ -32,6 +43,7 @@ extra_rdoc_files: []
32
43
  files:
33
44
  - .gitignore
34
45
  - .rspec
46
+ - .travis.yml
35
47
  - Gemfile
36
48
  - README.md
37
49
  - Rakefile