unified_db 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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Unified Movie Database
2
+
3
+ This is project for unifying multiple movie database. Currently it support only IMDB and TVDB, but TMDB will be done shortly.
4
+
5
+ To see it in action please go to [demo site](http://unified-db.heroku.com)
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.rspec_opts = ["-c", "-f progress"]
8
+ t.pattern = 'spec/**/*_spec.rb'
9
+ end
10
+
11
+ task :default => :spec
data/lib/ext/crack.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'crack/json'
2
+ require 'yajl'
3
+
4
+ module Crack
5
+ class JSON
6
+ def self.parse(json)
7
+ Yajl::Parser.parse(json)
8
+ end
9
+ end
10
+ end
data/lib/unified_db.rb ADDED
@@ -0,0 +1,19 @@
1
+ module UnifiedDB
2
+
3
+ ROOT = File.expand_path(File.dirname(__FILE__))
4
+
5
+ autoload :ApiError, "#{ROOT}/unified_db/api_error"
6
+ autoload :Backend, "#{ROOT}/unified_db/backend"
7
+ autoload :Result, "#{ROOT}/unified_db/result"
8
+ autoload :Version, "#{ROOT}/unified_db/version"
9
+
10
+ class << self
11
+ attr_accessor :json_encoder, :tvdb_secret
12
+
13
+ def json_encoder
14
+ @json_encoder ||= Yajl::Encoder.new
15
+ end
16
+ end
17
+ end
18
+
19
+ require "#{UnifiedDB::ROOT}/ext/crack"
@@ -0,0 +1,16 @@
1
+ module UnifiedDB
2
+ class ApiError < RuntimeError
3
+
4
+ def to_h
5
+ {
6
+ :result => 'error',
7
+ :reason => message
8
+ }
9
+ end
10
+
11
+ def to_json(*args)
12
+ UnifiedDB.json_encoder.encode to_h
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ module UnifiedDB
2
+ module Backend
3
+
4
+ autoload :Base, "#{ROOT}/unified_db/backend/base"
5
+ autoload :IMDB, "#{ROOT}/unified_db/backend/imdb"
6
+ autoload :TVDB, "#{ROOT}/unified_db/backend/tvdb"
7
+
8
+ AVAILABLE = {
9
+ 'imdb' => Backend::IMDB,
10
+ 'tvdb' => Backend::TVDB
11
+ }
12
+
13
+ def self.select(name)
14
+ AVAILABLE[name.to_s]
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,66 @@
1
+ module UnifiedDB
2
+ module Backend
3
+ class Base
4
+
5
+ attr_accessor :id, :title
6
+
7
+ def self.find(params)
8
+ new.find(params)
9
+ end
10
+
11
+ def initialize
12
+ @result = []
13
+ end
14
+
15
+ def find(params)
16
+ if params[:id]
17
+ find_by_id params[:id]
18
+ elsif params[:t] || params[:title]
19
+ find_by_title(params[:t] || params[:title])
20
+ else
21
+ raise ApiError, 'no search criteria specified'
22
+ end
23
+
24
+ result
25
+ rescue ApiError => e
26
+ {
27
+ :status => 'error',
28
+ :reason => e.message
29
+ }
30
+ end
31
+
32
+ def find_by_id(id)
33
+ raise ApiError, 'not implemented'
34
+ end
35
+
36
+ def find_by_title(title)
37
+ raise ApiError, 'not implemented'
38
+ end
39
+
40
+ def result
41
+ {
42
+ :status => 'success',
43
+ :service => service,
44
+ :result => @result
45
+ }
46
+ end
47
+
48
+ private
49
+
50
+ def service; 'base'; end
51
+
52
+ def format_actors(actors)
53
+ Array(actors).collect { |a| { a.name => a.role } }
54
+ end
55
+
56
+ def format_directors(directors)
57
+ Array(directors).collect(&:name)
58
+ end
59
+
60
+ def format_writers(writers)
61
+ Array(writers).collect(&:name)
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,46 @@
1
+ require 'imdb_party'
2
+
3
+ module UnifiedDB
4
+ module Backend
5
+ class IMDB < Base
6
+
7
+ def find_by_id(id)
8
+ movie = handler.find_movie_by_id(id)
9
+ @result = Result::ID.new(
10
+ :id => movie.imdb_id,
11
+ :title => movie.title,
12
+ :overview => movie.plot,
13
+ :release_date => movie.release_date,
14
+ :genres => movie.genres,
15
+ :rating => movie.rating,
16
+ :runtime => movie.runtime.to_i,
17
+ :actors => format_actors(movie.actors),
18
+ :directors => format_directors(movie.directors),
19
+ :writers => format_writers(movie.writers),
20
+ :posters => Array(movie.poster_url)
21
+ )
22
+ rescue
23
+ raise ApiError, 'not found'
24
+ end
25
+
26
+ def find_by_title(title)
27
+ movies = handler.find_by_title(title)
28
+ movies.each do |movie|
29
+ @result << Result::Title.new(
30
+ :id => movie[:imdb_id],
31
+ :title => movie[:title],
32
+ :year => movie[:year])
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def service; 'imdb'; end
39
+
40
+ def handler
41
+ @handler ||= ImdbParty::Imdb.new(:anonymize => true)
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,51 @@
1
+ require 'tvdb_party'
2
+
3
+ module UnifiedDB
4
+ module Backend
5
+ class TVDB < Base
6
+
7
+ def find_by_id(id)
8
+ movie = handler.get_series_by_id(id)
9
+ @result = Result::ID.new(
10
+ :id => movie.id,
11
+ :title => movie.name,
12
+ :overview => movie.overview,
13
+ :release_date => movie.first_aired.to_s,
14
+ :genres => movie.genres,
15
+ :rating => movie.rating,
16
+ :runtime => movie.runtime.to_i,
17
+ :actors => format_actors(movie.actors),
18
+ :directors => [],
19
+ :writers => [],
20
+ :posters => format_posters(movie.banners)
21
+ )
22
+ rescue
23
+ raise ApiError, 'not found'
24
+ end
25
+
26
+ def find_by_title(title)
27
+ movies = handler.search(title)
28
+ movies.each do |movie|
29
+ @result << Result::Title.new(
30
+ :id => movie['seriesid'],
31
+ :title => movie['SeriesName'],
32
+ :year => movie['FirstAired'].to_s.split('-')[0])
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def service; 'tvdb'; end
39
+
40
+ def handler
41
+ raise ApiError, 'no TVDB secret provided' if UnifiedDB.tvdb_secret.nil?
42
+ @handler ||= TvdbParty::Search.new(UnifiedDB.tvdb_secret)
43
+ end
44
+
45
+ def format_posters(posters)
46
+ posters.select{|poster| poster.banner_type == 'season'}.collect(&:url)
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,9 @@
1
+ module UnifiedDB
2
+ module Result
3
+
4
+ autoload :Base, "#{ROOT}/unified_db/result/base"
5
+ autoload :ID, "#{ROOT}/unified_db/result/id"
6
+ autoload :Title, "#{ROOT}/unified_db/result/title"
7
+
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ module UnifiedDB
2
+ module Result
3
+ class Base
4
+
5
+ def self.allowed_keys; []; end
6
+
7
+ def initialize(params)
8
+ allowed_keys.each do |key|
9
+ instance_variable_set("@#{key}", params[key])
10
+ end
11
+ end
12
+
13
+ def to_h
14
+ allowed_keys.inject({}) { |hash, key| hash[key] = instance_variable_get("@#{key}"); hash }
15
+ end
16
+
17
+ def to_json(*args)
18
+ UnifiedDB.json_encoder.encode to_h
19
+ end
20
+
21
+ private
22
+
23
+ def allowed_keys
24
+ self.class.allowed_keys
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module UnifiedDB
2
+ module Result
3
+ class ID < Base
4
+
5
+ def self.allowed_keys
6
+ [ :id, :title, :overview, :release_date, :genres, :rating, :runtime, :actors, :directors, :writers, :posters ]
7
+ end
8
+
9
+ attr_reader *allowed_keys
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module UnifiedDB
2
+ module Result
3
+ class Title < Base
4
+
5
+ def self.allowed_keys
6
+ [ :id, :title, :year ]
7
+ end
8
+
9
+ attr_reader *allowed_keys
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module UnifiedDB
2
+
3
+ VERSION = '0.1.0'
4
+
5
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require 'yajl'
4
+
5
+ require 'unified_db'
6
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
7
+
8
+ # This is secret is for testing purposes
9
+ # PLEASE don't copy and reuse it :)
10
+ UnifiedDB.tvdb_secret = '7ED5C5E4CAFAF90E'
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe UnifiedDB::Backend::IMDB do
4
+ subject { described_class.new }
5
+
6
+ it "should return valid find by title" do
7
+ result = subject.find(:title => 'Dark Knight')
8
+ result.class.should eql(Hash)
9
+ result.keys.sort.should eql([:result, :service, :status])
10
+ result[:status].should eql('success')
11
+ result[:service].should eql('imdb')
12
+ result[:result].class.should eql(Array)
13
+ result[:result].size.should be > 18
14
+
15
+ first_result = result[:result].first
16
+ first_result.class.should eql(UnifiedDB::Result::Title)
17
+ first_result.id.should eql('tt0468569')
18
+ first_result.title.should eql('The Dark Knight')
19
+ first_result.year.should eql('2008')
20
+
21
+ encoded = Yajl::Encoder.new.encode result
22
+ decoded = Yajl::Parser.new.parse encoded
23
+
24
+ decoded.class.should eql(Hash)
25
+ decoded.keys.sort.should eql(['result', 'service', 'status'])
26
+ decoded['status'].should eql('success')
27
+ decoded['service'].should eql('imdb')
28
+ decoded['result'].class.should eql(Array)
29
+ decoded['result'].size.should be > 18
30
+
31
+ first_result = decoded['result'].first
32
+ first_result.class.should eql(Hash)
33
+ first_result['id'].should eql('tt0468569')
34
+ first_result['title'].should eql('The Dark Knight')
35
+ first_result['year'].should eql('2008')
36
+ end
37
+
38
+ it "should return empty array if invalid find by title specified" do
39
+ result = subject.find(:title => "qwertyuiopasdfghjkllzxcvbnm")
40
+ result.class.should eql(Hash)
41
+ result.keys.sort.should eql([:result, :service, :status])
42
+ result[:status].should eql('success')
43
+ result[:service].should eql('imdb')
44
+ result[:result].class.should eql(Array)
45
+ result[:result].size.should eql(0)
46
+ end
47
+
48
+
49
+ it "should return valid find by id" do
50
+ result = subject.find(:id => 'tt0468569')
51
+ result.class.should eql(Hash)
52
+ result.keys.sort.should eql([:result, :service, :status])
53
+ result[:status].should eql('success')
54
+ result[:service].should eql('imdb')
55
+
56
+ result[:result].class.should eql(UnifiedDB::Result::ID)
57
+ result[:result].id.should eql('tt0468569')
58
+ result[:result].title.should eql('The Dark Knight')
59
+ result[:result].overview.class.should eql(String)
60
+ result[:result].overview.length.should be > 20
61
+ result[:result].release_date.class.should eql(String)
62
+ result[:result].genres.should eql(["Action", "Crime", "Thriller"])
63
+ result[:result].rating.class.should eql(Float)
64
+ result[:result].rating.should be > 4
65
+ result[:result].rating.should be < 10
66
+ result[:result].runtime.should eql(152)
67
+ result[:result].actors.class.should eql(Array)
68
+ result[:result].actors.first.should eql({"Christian Bale" => "Bruce Wayne/Batman"})
69
+ result[:result].directors.should eql(["Christopher Nolan"])
70
+ result[:result].writers.should eql(["Jonathan Nolan", "Christopher Nolan"])
71
+ result[:result].posters.class.should eql(Array)
72
+ result[:result].posters.size.should be > 0
73
+ end
74
+
75
+ it "should return error if id was not found" do
76
+ result = subject.find(:id => 'tt046856910')
77
+ result.class.should eql(Hash)
78
+ result.keys.sort.should eql([:reason, :status])
79
+ result[:status].should eql('error')
80
+ result[:reason].should eql('not found')
81
+ end
82
+
83
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe UnifiedDB::Backend::TVDB do
4
+ subject { described_class.new }
5
+
6
+ it "should return valid find by title" do
7
+ result = subject.find(:title => 'StarGate')
8
+ result.class.should eql(Hash)
9
+ result.keys.sort.should eql([:result, :service, :status])
10
+ result[:status].should eql('success')
11
+ result[:service].should eql('tvdb')
12
+ result[:result].class.should eql(Array)
13
+ result[:result].size.should be > 3
14
+
15
+ first_result = result[:result].first
16
+ first_result.class.should eql(UnifiedDB::Result::Title)
17
+ first_result.id.should eql('72449')
18
+ first_result.title.should eql('Stargate SG-1')
19
+ first_result.year.should eql('1997')
20
+
21
+ encoded = Yajl::Encoder.new.encode result
22
+ decoded = Yajl::Parser.new.parse encoded
23
+
24
+ decoded.class.should eql(Hash)
25
+ decoded.keys.sort.should eql(['result', 'service', 'status'])
26
+ decoded['status'].should eql('success')
27
+ decoded['service'].should eql('tvdb')
28
+ decoded['result'].class.should eql(Array)
29
+ decoded['result'].size.should be > 3
30
+
31
+ first_result = decoded['result'].first
32
+ first_result.class.should eql(Hash)
33
+ first_result['id'].should eql('72449')
34
+ first_result['title'].should eql('Stargate SG-1')
35
+ first_result['year'].should eql('1997')
36
+ end
37
+
38
+ it "should return empty array if invalid find by title specified" do
39
+ result = subject.find(:title => "qwertyuiopasdfghjkllzxcvbnm")
40
+ result.class.should eql(Hash)
41
+ result.keys.sort.should eql([:result, :service, :status])
42
+ result[:status].should eql('success')
43
+ result[:service].should eql('tvdb')
44
+ result[:result].class.should eql(Array)
45
+ result[:result].size.should eql(0)
46
+ end
47
+
48
+
49
+ it "should return valid find by id" do
50
+ result = subject.find(:id => '72449')
51
+ result.class.should eql(Hash)
52
+ result.keys.sort.should eql([:result, :service, :status])
53
+ result[:status].should eql('success')
54
+ result[:service].should eql('tvdb')
55
+
56
+ result[:result].class.should eql(UnifiedDB::Result::ID)
57
+ result[:result].id.should eql('72449')
58
+ result[:result].title.should eql('Stargate SG-1')
59
+ result[:result].overview.class.should eql(String)
60
+ result[:result].overview.length.should be > 20
61
+ result[:result].release_date.class.should eql(String)
62
+ result[:result].genres.should eql(["Action and Adventure", "Science-Fiction"])
63
+ result[:result].rating.class.should eql(Float)
64
+ result[:result].rating.should be > 4
65
+ result[:result].rating.should be < 10
66
+ result[:result].runtime.should eql(60)
67
+ result[:result].actors.class.should eql(Array)
68
+ result[:result].actors.first.should eql({"Richard Dean Anderson"=>"Col./Gen. Jack O'Neill"})
69
+ result[:result].directors.should eql([])
70
+ result[:result].writers.should eql([])
71
+ result[:result].posters.class.should eql(Array)
72
+ result[:result].posters.size.should be > 0
73
+ end
74
+
75
+ it "should return error if id was not found" do
76
+ result = subject.find(:id => '72449123')
77
+ result.class.should eql(Hash)
78
+ result.keys.sort.should eql([:reason, :status])
79
+ result[:status].should eql('error')
80
+ result[:reason].should eql('not found')
81
+ end
82
+
83
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "unified_db/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "unified_db"
7
+ s.version = UnifiedDB::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Bernard Potocki"]
10
+ s.email = ["bernard.potocki@imanel.org"]
11
+ s.homepage = "http://github.com/imanel/unifieddb"
12
+ s.summary = %q{Scrapper for multiple Movie Databases}
13
+ s.description = %q{Scrapper for multiple Movie Databases}
14
+
15
+ s.add_dependency 'yajl-ruby'
16
+ s.add_dependency 'imdb_party', '~> 0.6.0'
17
+ s.add_dependency 'tvdb_party', '~> 0.6.0'
18
+ s.add_development_dependency 'rspec', '~> 2.0'
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unified_db
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bernard Potocki
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-22 00:00:00.000000000 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: yajl-ruby
17
+ requirement: &70343143888220 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70343143888220
26
+ - !ruby/object:Gem::Dependency
27
+ name: imdb_party
28
+ requirement: &70343143887680 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.6.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *70343143887680
37
+ - !ruby/object:Gem::Dependency
38
+ name: tvdb_party
39
+ requirement: &70343143887140 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 0.6.0
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *70343143887140
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ requirement: &70343143886640 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: '2.0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *70343143886640
59
+ description: Scrapper for multiple Movie Databases
60
+ email:
61
+ - bernard.potocki@imanel.org
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - .gitignore
67
+ - Gemfile
68
+ - README.md
69
+ - Rakefile
70
+ - lib/ext/crack.rb
71
+ - lib/unified_db.rb
72
+ - lib/unified_db/api_error.rb
73
+ - lib/unified_db/backend.rb
74
+ - lib/unified_db/backend/base.rb
75
+ - lib/unified_db/backend/imdb.rb
76
+ - lib/unified_db/backend/tvdb.rb
77
+ - lib/unified_db/result.rb
78
+ - lib/unified_db/result/base.rb
79
+ - lib/unified_db/result/id.rb
80
+ - lib/unified_db/result/title.rb
81
+ - lib/unified_db/version.rb
82
+ - spec/spec_helper.rb
83
+ - spec/unified_db/backend/imdb_spec.rb
84
+ - spec/unified_db/backend/tvdb_spec.rb
85
+ - unified_db.gemspec
86
+ has_rdoc: true
87
+ homepage: http://github.com/imanel/unifieddb
88
+ licenses: []
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 1.6.2
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Scrapper for multiple Movie Databases
111
+ test_files:
112
+ - spec/spec_helper.rb
113
+ - spec/unified_db/backend/imdb_spec.rb
114
+ - spec/unified_db/backend/tvdb_spec.rb