royw-tmdb 0.1.0 → 0.1.1
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/VERSION.yml +1 -1
- data/lib/string_extensions.rb +8 -0
- data/lib/tmdb.rb +1 -0
- data/lib/tmdb/optional_logger.rb +20 -8
- data/lib/tmdb/tmdb_image.rb +155 -0
- data/lib/tmdb/tmdb_movie.rb +8 -2
- data/lib/tmdb/tmdb_profile.rb +8 -1
- data/spec/tmdb_image_spec.rb +118 -0
- data/spec/tmdb_movie_spec.rb +3 -2
- metadata +5 -2
data/VERSION.yml
CHANGED
data/lib/string_extensions.rb
CHANGED
@@ -8,6 +8,14 @@ class String
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
# this handles unicode characters by converting each byte to "%XX"
|
12
|
+
# where XX is the hex value
|
13
|
+
my_extension("escape_unicode") do
|
14
|
+
def escape_unicode
|
15
|
+
self.each_byte.collect{|c| c.to_i > 127 ? "%#{c.to_i.to_s(16)}" : c.chr}.join('')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
11
19
|
my_extension("strip_tags") do
|
12
20
|
def strip_tags
|
13
21
|
gsub(/<\/?[^>]*>/, "")
|
data/lib/tmdb.rb
CHANGED
data/lib/tmdb/optional_logger.rb
CHANGED
@@ -9,23 +9,35 @@ class OptionalLogger
|
|
9
9
|
end
|
10
10
|
|
11
11
|
# debug {...}
|
12
|
-
def debug(&blk)
|
13
|
-
|
12
|
+
def debug(msg=nil, &blk)
|
13
|
+
unless @logger.nil?
|
14
|
+
@logger.debug(msg) unless msg.nil?
|
15
|
+
@logger.debug(blk.call) unless blk.nil?
|
16
|
+
end
|
14
17
|
end
|
15
18
|
|
16
19
|
# info {...}
|
17
|
-
def info(&blk)
|
18
|
-
|
20
|
+
def info(msg=nil, &blk)
|
21
|
+
unless @logger.nil?
|
22
|
+
@logger.info(msg) unless msg.nil?
|
23
|
+
@logger.info(blk.call) unless blk.nil?
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
27
|
# warn {...}
|
22
|
-
def warn(&blk)
|
23
|
-
|
28
|
+
def warn(msg=nil, &blk)
|
29
|
+
unless @logger.nil?
|
30
|
+
@logger.warn(msg) unless msg.nil?
|
31
|
+
@logger.warn(blk.call) unless blk.nil?
|
32
|
+
end
|
24
33
|
end
|
25
34
|
|
26
35
|
# error {...}
|
27
|
-
def error(&blk)
|
28
|
-
|
36
|
+
def error(msg=nil, &blk)
|
37
|
+
unless @logger.nil?
|
38
|
+
@logger.error(msg) unless msg.nil?
|
39
|
+
@logger.error(blk.call) unless blk.nil?
|
40
|
+
end
|
29
41
|
end
|
30
42
|
end
|
31
43
|
|
@@ -0,0 +1,155 @@
|
|
1
|
+
class TmdbImage
|
2
|
+
attr_reader :imdb_id
|
3
|
+
|
4
|
+
# imdb_id => String IMDB ID either with or without the 'tt' prefix
|
5
|
+
# api_key => String containing the themovieDb.com API key
|
6
|
+
# logger => nil or logger instance
|
7
|
+
def initialize(imdb_id, api_key, logger)
|
8
|
+
@imdb_id = imdb_id
|
9
|
+
@api_key = api_key
|
10
|
+
@logger = OptionalLogger.new(logger)
|
11
|
+
end
|
12
|
+
|
13
|
+
# return an Array of fanart sizes as Strings
|
14
|
+
def fanart_sizes
|
15
|
+
['original', 'mid', 'thumb']
|
16
|
+
end
|
17
|
+
|
18
|
+
# return an Array of poster sizes as Strings
|
19
|
+
def poster_sizes
|
20
|
+
['original', 'mid', 'thumb', 'cover']
|
21
|
+
end
|
22
|
+
|
23
|
+
# return nil or the source url to the given size (must be in fanart_sizes) fanart
|
24
|
+
# optionally save the image to dest_filespec unless dest_filespec is nil
|
25
|
+
def fanart(size, dest_filespec=nil)
|
26
|
+
src_url = nil
|
27
|
+
if fanart_sizes.include?(size)
|
28
|
+
src_url = image_url(@imdb_id, 'fanarts', size)
|
29
|
+
copy_image(src_url, dest_filespec) unless dest_filespec.nil?
|
30
|
+
end
|
31
|
+
src_url
|
32
|
+
end
|
33
|
+
|
34
|
+
# return nil or the source url to the given size (must be in poster_sizes) poster
|
35
|
+
# optionally save the image to dest_filespec unless dest_filespec is nil
|
36
|
+
def poster(size, dest_filespec=nil)
|
37
|
+
src_url = nil
|
38
|
+
if poster_sizes.include?(size)
|
39
|
+
src_url = image_url(@imdb_id, 'posters', size)
|
40
|
+
copy_image(src_url, dest_filespec) unless dest_filespec.nil?
|
41
|
+
end
|
42
|
+
src_url
|
43
|
+
end
|
44
|
+
|
45
|
+
# return nil or the source url to the 'original' size fanart
|
46
|
+
# optionally save the image to dest_filespec unless dest_filespec is nil
|
47
|
+
def fanart_original(dest_filespec=nil)
|
48
|
+
fanart('original', dest_filespec)
|
49
|
+
end
|
50
|
+
|
51
|
+
# return nil or the source url to the 'mid' size fanart
|
52
|
+
# optionally save the image to dest_filespec unless dest_filespec is nil
|
53
|
+
def fanart_mid(dest_filespec=nil)
|
54
|
+
fanart('mid', dest_filespec)
|
55
|
+
end
|
56
|
+
|
57
|
+
# return nil or the source url to the 'thumb' size fanart
|
58
|
+
# optionally save the image to dest_filespec unless dest_filespec is nil
|
59
|
+
def fanart_thumb(dest_filespec=nil)
|
60
|
+
fanart('thumb', dest_filespec)
|
61
|
+
end
|
62
|
+
|
63
|
+
# return nil or the source url to the 'original' size poster
|
64
|
+
# optionally save the image to dest_filespec unless dest_filespec is nil
|
65
|
+
def poster_original(dest_filespec=nil)
|
66
|
+
poster('original', dest_filespec)
|
67
|
+
end
|
68
|
+
|
69
|
+
# return nil or the source url to the 'mid' size poster
|
70
|
+
# optionally save the image to dest_filespec unless dest_filespec is nil
|
71
|
+
def poster_mid(dest_filespec=nil)
|
72
|
+
poster('original', dest_filespec)
|
73
|
+
end
|
74
|
+
|
75
|
+
# return nil or the source url to the 'thumb' size poster
|
76
|
+
# optionally save the image to dest_filespec unless dest_filespec is nil
|
77
|
+
def poster_thumb(dest_filespec=nil)
|
78
|
+
poster('original', dest_filespec)
|
79
|
+
end
|
80
|
+
|
81
|
+
# return nil or the source url to the 'cover' size poster
|
82
|
+
# optionally save the image to dest_filespec unless dest_filespec is nil
|
83
|
+
def poster_cover(dest_filespec=nil)
|
84
|
+
poster('original', dest_filespec)
|
85
|
+
end
|
86
|
+
|
87
|
+
protected
|
88
|
+
|
89
|
+
# find the URL to the image
|
90
|
+
# imdb_id => IMDB ID with or without 'tt' prefix
|
91
|
+
# type => either 'fanart' or 'poster' String
|
92
|
+
# size => member of either fanart_sizes or poster_sizes
|
93
|
+
def image_url(imdb_id, type, size)
|
94
|
+
src_url = nil
|
95
|
+
profile = TmdbProfile.first(:imdb_id => imdb_id, :api_key => @api_key, :filespec => nil, :logger => @logger)
|
96
|
+
indexes = {}
|
97
|
+
unless profile.nil? || profile.movie.blank?
|
98
|
+
movie = profile.movie
|
99
|
+
unless movie[type].blank?
|
100
|
+
images = movie[type]
|
101
|
+
images.each do |image|
|
102
|
+
if image['size'] == size
|
103
|
+
@logger.debug { "#{image.inspect}" }
|
104
|
+
src_url = image['content']
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
src_url
|
110
|
+
end
|
111
|
+
|
112
|
+
# download the fanart
|
113
|
+
def copy_image(src_url, dest_filespec)
|
114
|
+
begin
|
115
|
+
extension = File.extname(src_url)
|
116
|
+
unless extension.blank?
|
117
|
+
dest_filespec += extension
|
118
|
+
end
|
119
|
+
data = fetch(src_url.escape_unicode)
|
120
|
+
File.open(dest_filespec, 'w') do |file|
|
121
|
+
file.print(data)
|
122
|
+
end
|
123
|
+
rescue Exception => e
|
124
|
+
@logger.error { "Error fetching image.\n src_url => #{src_url},\n dest_filespec => #{dest_filespec}\n #{e.to_s}" }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
MAX_ATTEMPTS = 3
|
129
|
+
SECONDS_BETWEEN_RETRIES = 1.0
|
130
|
+
|
131
|
+
# fetch the page retrying on error up to MAX_ATTEMPTS with a pause
|
132
|
+
# of SECONDS_BETWEEN_RETRIES seconds between retries
|
133
|
+
def fetch(page)
|
134
|
+
doc = nil
|
135
|
+
attempts = 0
|
136
|
+
begin
|
137
|
+
doc = read_page(page)
|
138
|
+
rescue Exception => e
|
139
|
+
attempts += 1
|
140
|
+
if attempts > MAX_ATTEMPTS
|
141
|
+
raise
|
142
|
+
else
|
143
|
+
sleep SECONDS_BETWEEN_RETRIES
|
144
|
+
retry
|
145
|
+
end
|
146
|
+
end
|
147
|
+
doc
|
148
|
+
end
|
149
|
+
|
150
|
+
# makes reading from cache during specs possible
|
151
|
+
def read_page(src_url)
|
152
|
+
open(src_url).read
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
data/lib/tmdb/tmdb_movie.rb
CHANGED
@@ -2,9 +2,15 @@ class TmdbMovie
|
|
2
2
|
|
3
3
|
attr_reader :query, :document
|
4
4
|
|
5
|
-
def initialize(ident, key)
|
5
|
+
def initialize(ident, key, logger)
|
6
6
|
@imdb_id = 'tt' + ident.gsub(/^tt/, '') unless ident.blank?
|
7
|
+
@api_key = key
|
7
8
|
@query = "http://api.themoviedb.org/2.0/Movie.imdbLookup?imdb_id=#{@imdb_id}&api_key=#{key}"
|
9
|
+
@logger = OptionalLogger.new(logger)
|
10
|
+
end
|
11
|
+
|
12
|
+
def image
|
13
|
+
TmdbImage.new(@imdb_id, @api_key, @logger)
|
8
14
|
end
|
9
15
|
|
10
16
|
def fanarts
|
@@ -100,7 +106,7 @@ class TmdbMovie
|
|
100
106
|
# Fetch the document with retry to handle the occasional glitches
|
101
107
|
def document
|
102
108
|
if @document.nil?
|
103
|
-
html = fetch(self.query)
|
109
|
+
html = fetch(self.query.escape_unicode)
|
104
110
|
@document = XmlSimple.xml_in(html)
|
105
111
|
@document = nil if @document['totalResults'] == ['0']
|
106
112
|
end
|
data/lib/tmdb/tmdb_profile.rb
CHANGED
@@ -49,6 +49,8 @@ class TmdbProfile
|
|
49
49
|
|
50
50
|
attr_reader :imdb_id, :movie
|
51
51
|
|
52
|
+
# convert to xml
|
53
|
+
# returns String (either empty or containing the xml)
|
52
54
|
def to_xml
|
53
55
|
xml = ''
|
54
56
|
unless @movie.blank?
|
@@ -58,6 +60,11 @@ class TmdbProfile
|
|
58
60
|
xml
|
59
61
|
end
|
60
62
|
|
63
|
+
# return the TmdbImage for this profile
|
64
|
+
def image
|
65
|
+
TmdbImage.new(@imdb_id.gsub(/^tt/, ''), @api_key, @logger)
|
66
|
+
end
|
67
|
+
|
61
68
|
protected
|
62
69
|
|
63
70
|
def load
|
@@ -67,7 +74,7 @@ class TmdbProfile
|
|
67
74
|
@movie = from_xml(open(@filespec).read)
|
68
75
|
elsif !@imdb_id.blank?
|
69
76
|
@logger.debug { "loading movie from tmdb.com, filespec=> #{@filespec.inspect}" }
|
70
|
-
@movie = TmdbMovie.new(@imdb_id.gsub(/^tt/, ''), @api_key).to_hash
|
77
|
+
@movie = TmdbMovie.new(@imdb_id.gsub(/^tt/, ''), @api_key, @logger).to_hash
|
71
78
|
save(@filespec) unless @filespec.blank?
|
72
79
|
end
|
73
80
|
unless @movie.blank?
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
require 'ruby-debug'
|
5
|
+
|
6
|
+
# Time to add your specs!
|
7
|
+
# http://rspec.info/
|
8
|
+
|
9
|
+
TMDB_API_KEY = '7a2f6eb9b6aa01651000f0a9324db835'
|
10
|
+
|
11
|
+
describe "TmdbImage" do
|
12
|
+
|
13
|
+
before(:all) do
|
14
|
+
@logger = nil
|
15
|
+
File.mkdirs(TMPDIR)
|
16
|
+
end
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
# tt0465234 => National Treasure: Book of Secrets
|
20
|
+
@image = TmdbImage.new('tt0465234', TMDB_API_KEY, @logger)
|
21
|
+
end
|
22
|
+
|
23
|
+
after(:each) do
|
24
|
+
Dir.glob(File.join(TMPDIR,'tmdb_image_spec*')).each { |filename| File.delete(filename) }
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should find by imdb_id" do
|
28
|
+
@image.should_not == nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should find image via profile" do
|
32
|
+
profile = TmdbProfile.first(:imdb_id => 'tt0465234', :api_key => TMDB_API_KEY, :logger => @logger)
|
33
|
+
profile.image.imdb_id.should == '0465234'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should find image via movie" do
|
37
|
+
profile = TmdbMovie.new('tt0465234', TMDB_API_KEY, @logger)
|
38
|
+
profile.image.imdb_id.should == 'tt0465234'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should find original size fanart" do
|
42
|
+
src_url = nil
|
43
|
+
src_url = @image.fanart_original unless @image.nil?
|
44
|
+
src_url.should_not be_nil
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should find mid size fanart" do
|
48
|
+
src_url = nil
|
49
|
+
src_url = @image.fanart_mid unless @image.nil?
|
50
|
+
src_url.should_not be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should find thumb size fanart" do
|
54
|
+
src_url = nil
|
55
|
+
src_url = @image.fanart_thumb unless @image.nil?
|
56
|
+
src_url.should_not be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should find original size poster" do
|
60
|
+
src_url = nil
|
61
|
+
src_url = @image.poster_original unless @image.nil?
|
62
|
+
src_url.should_not be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should find mid size poster" do
|
66
|
+
src_url = nil
|
67
|
+
src_url = @image.poster_mid unless @image.nil?
|
68
|
+
src_url.should_not be_nil
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should find thumb size poster" do
|
72
|
+
src_url = nil
|
73
|
+
src_url = @image.poster_thumb unless @image.nil?
|
74
|
+
src_url.should_not be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should find cover size poster" do
|
78
|
+
src_url = nil
|
79
|
+
src_url = @image.poster_cover unless @image.nil?
|
80
|
+
src_url.should_not be_nil
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should find all fanarts" do
|
84
|
+
buf = []
|
85
|
+
@image.fanart_sizes.each do |size|
|
86
|
+
buf << "fanart(#{size}) returned nil" if @image.fanart(size).nil?
|
87
|
+
end
|
88
|
+
puts buf.join("\n") unless buf.empty?
|
89
|
+
buf.empty?.should be_true
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should find all posters" do
|
93
|
+
buf = []
|
94
|
+
@image.poster_sizes.each do |size|
|
95
|
+
buf << "poster(#{size}) returned nil" if @image.poster(size).nil?
|
96
|
+
end
|
97
|
+
puts buf.join("\n") unless buf.empty?
|
98
|
+
buf.empty?.should be_true
|
99
|
+
end
|
100
|
+
|
101
|
+
# the same routine is used by all the getters to fetch the image so only
|
102
|
+
# need to test one case
|
103
|
+
it "should fetch fanart" do
|
104
|
+
filespec = get_temp_filename
|
105
|
+
src_url = @image.fanart_original(filespec)
|
106
|
+
filespec += File.extname(src_url)
|
107
|
+
(File.exist?(filespec).should be_true) && (File.size(filespec).should > 0)
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_temp_filename
|
111
|
+
outfile = Tempfile.new('tmdb_image_spec', TMPDIR)
|
112
|
+
filespec = outfile.path
|
113
|
+
outfile.unlink
|
114
|
+
filespec
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
data/spec/tmdb_movie_spec.rb
CHANGED
@@ -8,11 +8,12 @@ TMDB_API_KEY = '7a2f6eb9b6aa01651000f0a9324db835'
|
|
8
8
|
describe "TmdbMovie" do
|
9
9
|
|
10
10
|
before(:all) do
|
11
|
+
@logger = nil
|
11
12
|
File.mkdirs(TMPDIR)
|
12
13
|
end
|
13
14
|
|
14
15
|
before(:each) do
|
15
|
-
@profile = TmdbMovie.new('tt0465234', TMDB_API_KEY)
|
16
|
+
@profile = TmdbMovie.new('tt0465234', TMDB_API_KEY, @logger)
|
16
17
|
end
|
17
18
|
|
18
19
|
after(:each) do
|
@@ -68,7 +69,7 @@ describe "TmdbMovie" do
|
|
68
69
|
end
|
69
70
|
|
70
71
|
it "should handle The Sand Pebble" do
|
71
|
-
profile = TmdbMovie.new('tt0060934', TMDB_API_KEY)
|
72
|
+
profile = TmdbMovie.new('tt0060934', TMDB_API_KEY, @logger)
|
72
73
|
profile.idents.should be_nil
|
73
74
|
end
|
74
75
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: royw-tmdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roy Wright
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
12
|
+
date: 2009-04-18 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -33,10 +33,12 @@ files:
|
|
33
33
|
- lib/string_extensions.rb
|
34
34
|
- lib/tmdb.rb
|
35
35
|
- lib/tmdb/optional_logger.rb
|
36
|
+
- lib/tmdb/tmdb_image.rb
|
36
37
|
- lib/tmdb/tmdb_movie.rb
|
37
38
|
- lib/tmdb/tmdb_profile.rb
|
38
39
|
- spec/cache_extensions.rb
|
39
40
|
- spec/spec_helper.rb
|
41
|
+
- spec/tmdb_image_spec.rb
|
40
42
|
- spec/tmdb_movie_spec.rb
|
41
43
|
- spec/tmdb_profile_spec.rb
|
42
44
|
has_rdoc: true
|
@@ -70,3 +72,4 @@ test_files:
|
|
70
72
|
- spec/tmdb_profile_spec.rb
|
71
73
|
- spec/spec_helper.rb
|
72
74
|
- spec/tmdb_movie_spec.rb
|
75
|
+
- spec/tmdb_image_spec.rb
|