class TmdbImage attr_reader :imdb_id # imdb_id => String IMDB ID either with or without the 'tt' prefix # api_key => String containing the themovieDb.com API key # logger => nil or logger instance def initialize(ident, api_key, logger, filespec=nil) @imdb_id = 'tt' + ident.gsub(/^tt/, '') unless ident.blank? @api_key = api_key @logger = OptionalLogger.new(logger) @filespec = filespec end # return an Array of fanart sizes as Strings def fanart_sizes ['original', 'mid', 'thumb'] end # return an Array of poster sizes as Strings def poster_sizes ['original', 'mid', 'thumb', 'cover'] end # return nil or the source url to the given size (must be in fanart_sizes) fanart # optionally save the image to dest_filespec unless dest_filespec is nil def fanart(size, dest_filespec=nil) src_url = nil if fanart_sizes.include?(size) src_url = image_url(@imdb_id, 'fanarts', size) copy_image(src_url, dest_filespec) end src_url end # return nil or the source url to the given size (must be in poster_sizes) poster # optionally save the image to dest_filespec unless dest_filespec is nil def poster(size, dest_filespec=nil) src_url = nil if poster_sizes.include?(size) src_url = image_url(@imdb_id, 'posters', size) copy_image(src_url, dest_filespec) end src_url end # return nil or the source url to the 'original' size fanart # optionally save the image to dest_filespec unless dest_filespec is nil def fanart_original(dest_filespec=nil) fanart('original', dest_filespec) end # return nil or the source url to the 'mid' size fanart # optionally save the image to dest_filespec unless dest_filespec is nil def fanart_mid(dest_filespec=nil) fanart('mid', dest_filespec) end # return nil or the source url to the 'thumb' size fanart # optionally save the image to dest_filespec unless dest_filespec is nil def fanart_thumb(dest_filespec=nil) fanart('thumb', dest_filespec) end # return nil or the source url to the 'original' size poster # optionally save the image to dest_filespec unless dest_filespec is nil def poster_original(dest_filespec=nil) poster('original', dest_filespec) end # return nil or the source url to the 'mid' size poster # optionally save the image to dest_filespec unless dest_filespec is nil def poster_mid(dest_filespec=nil) poster('original', dest_filespec) end # return nil or the source url to the 'thumb' size poster # optionally save the image to dest_filespec unless dest_filespec is nil def poster_thumb(dest_filespec=nil) poster('original', dest_filespec) end # return nil or the source url to the 'cover' size poster # optionally save the image to dest_filespec unless dest_filespec is nil def poster_cover(dest_filespec=nil) poster('original', dest_filespec) end protected # find the URL to the image # imdb_id => IMDB ID with or without 'tt' prefix # type => either 'fanart' or 'poster' String # size => member of either fanart_sizes or poster_sizes def image_url(imdb_id, type, size) src_url = nil profile = TmdbProfile.first(:imdb_id => imdb_id, :api_key => @api_key, :filespec => @filespec, :logger => @logger) indexes = {} unless profile.nil? || profile.movie.blank? movie = profile.movie unless movie[type].blank? images = movie[type] images.each do |image| image_size = image['size'] image_size = image_size.first if image_size.respond_to?('first') if image_size == size @logger.debug { "#{image.inspect}" } src_url = image['content'] end break unless src_url.blank? end end end src_url end # download the fanart # returns nil if no attempt to copy was made, 0 on error, or the image size in bytes on success def copy_image(src_url, dest_filespec) @logger.debug { "copy_image(#{src_url}, #{dest_filespec})" } image_size = nil unless src_url.blank? || dest_filespec.blank? begin image_size = 0 extension = File.extname(src_url) unless extension.blank? dest_filespec += extension end unless File.exist?(dest_filespec) && (File.size(dest_filespec) > 0) @logger.info { "Downloading: #{src_url}" } data = fetch(src_url.escape_unicode) File.open(dest_filespec, 'w') do |file| file.print(data) end end image_size = File.size(dest_filespec) rescue Exception => e @logger.error { "Error fetching image.\n src_url => #{src_url},\n dest_filespec => #{dest_filespec}\n #{e.to_s}" } end end image_size end MAX_ATTEMPTS = 3 SECONDS_BETWEEN_RETRIES = 1.0 # fetch the page retrying on error up to MAX_ATTEMPTS with a pause # of SECONDS_BETWEEN_RETRIES seconds between retries def fetch(page) doc = nil attempts = 0 begin doc = read_page(page) rescue Exception => e attempts += 1 if attempts > MAX_ATTEMPTS raise else sleep SECONDS_BETWEEN_RETRIES retry end end doc end # makes reading from cache during specs possible def read_page(src_url) open(src_url).read end end