from couchpotato . core . event import addEvent
from couchpotato . core . helpers . encoding import simplifyString , toUnicode
from couchpotato . core . logger import CPLog
from couchpotato . core . providers . show . base import ShowProvider
from thetvdb . tvdb_api import Tvdb
import traceback
log = CPLog ( __name__ )
class TheTVDb ( ShowProvider ) :
def __init__ ( self ) :
#addEvent('show.by_hash', self.byHash)
addEvent ( ' show.search ' , self . search , priority = 1 )
addEvent ( ' show.info ' , self . getInfo , priority = 1 )
addEvent ( ' show.episodes ' , self . getEpisodes , priority = 1 )
#addEvent('show.info_by_thetvdb', self.getInfoByTheTVDBId)
# Use base wrapper
#thetvdbtmdb.configure(self.conf('api_key'))
self . tvdb = Tvdb ( apikey = " 7966C02F860586D2 " , banners = True )
#def byHash(self, file):
#''' Find show by hash '''
#if self.isDisabled():
#return False
#cache_key = 'tmdb.cache.%s' % simplifyString(file)
#results = self.getCache(cache_key)
#if not results:
#log.debug('Searching for show by hash: %s', file)
#try:
#raw = tmdb.searchByHashingFile(file)
#results = []
#if raw:
#try:
#results = self.parseShow(raw)
#log.info('Found: %s', results['titles'][0] + ' (' + str(results.get('year', 0)) + ')')
#self.setCache(cache_key, results)
#return results
#except SyntaxError, e:
#log.error('Failed to parse XML response: %s', e)
#return False
#except:
#log.debug('No shows known by hash for: %s', file)
#pass
#return results
def search ( self , q , limit = 12 ) :
''' Find show by name
show = { ' id ' : 74713 ,
' language ' : ' en ' ,
' lid ' : 7 ,
' seriesid ' : ' 74713 ' ,
' seriesname ' : u ' Breaking Bad ' , }
'''
if self . isDisabled ( ) :
return False
search_string = simplifyString ( q )
cache_key = ' thetvdb.cache. %s . %s ' % ( search_string , limit )
results = self . getCache ( cache_key )
if not results :
log . debug ( ' Searching for show: %s ' , q )
raw = None
try :
raw = self . tvdb . search ( search_string )
except : # XXX: Make more specific
log . error ( ' Failed searching TheTVDB for " %s " : %s ' , ( search_string , traceback . format_exc ( ) ) )
results = [ ]
if raw :
try :
nr = 0
for show in raw :
show = self . tvdb [ int ( show [ ' id ' ] ) ]
results . append ( self . parseShow ( show ) )
nr + = 1
if nr == limit :
break
log . info ( ' Found: %s ' , [ result [ ' titles ' ] [ 0 ] + ' ( ' + str ( result . get ( ' year ' , 0 ) ) + ' ) ' for result in results ] )
self . setCache ( cache_key , results )
return results
except SyntaxError , e :
log . error ( ' Failed to parse XML response: %s ' , e )
return False
return results
def getEpisodes ( self , identifier = None ) :
if not identifier :
return [ ]
try :
show = self . tvdb [ int ( identifier ) ]
except :
return [ ]
result = [ ]
for season in show . values ( ) :
for episode in season . values ( ) :
# Consider cache
result . append ( self . parseEpisode ( episode ) )
return result
def getInfo ( self , identifier = None ) :
cache_key = ' thetvdb.cache. %s ' % identifier
result = self . getCache ( cache_key )
if not result :
result = { }
show = None
try :
log . debug ( ' Getting info: %s ' , cache_key )
#show = thetvdb.imdbLookup(id = identifier)
show = self . tvdb [ int ( identifier ) ]
except :
pass
if show :
#result = self.parseShow(show[0])
result = self . parseShow ( show )
self . setCache ( cache_key , result )
return result
#def getInfoByTheTVDBId(self, id = None):
#cache_key = 'thetvdb.cache.%s' % id
#result = self.getCache(cache_key)
#if not result:
#result = {}
#show = None
#try:
#log.debug('Getting info: %s', cache_key)
#show = tmdb.getShowInfo(id = id)
#except:
#pass
#if show:
#result = self.parseShow(show)
#self.setCache(cache_key, result)
#return result
def parseShow ( self , show ) :
"""
show [ 74713 ] = {
' actors ' : u ' |Bryan Cranston|Aaron Paul|Dean Norris|RJ Mitte|Betsy Brandt|Anna Gunn|Laura Fraser|Jesse Plemons|Christopher Cousins|Steven Michael Quezada|Jonathan Banks|Giancarlo Esposito|Bob Odenkirk| ' ,
' added ' : None ,
' addedby ' : None ,
' airs_dayofweek ' : u ' Sunday ' ,
' airs_time ' : u ' 9:00 PM ' ,
' banner ' : u ' http://thetvdb.com/banners/graphical/81189-g13.jpg ' ,
' contentrating ' : u ' TV-MA ' ,
' fanart ' : u ' http://thetvdb.com/banners/fanart/original/81189-28.jpg ' ,
' firstaired ' : u ' 2008-01-20 ' ,
' genre ' : u ' |Crime|Drama|Suspense| ' ,
' id ' : u ' 81189 ' ,
' imdb_id ' : u ' tt0903747 ' ,
' language ' : u ' en ' ,
' lastupdated ' : u ' 1376620212 ' ,
' network ' : u ' AMC ' ,
' networkid ' : None ,
' overview ' : u " Walter White, a struggling high school chemistry teacher is diagnosed with advanced lung cancer. He turns to a life of crime, producing and selling methamphetamine accompanied by a former student, Jesse Pinkman with the aim of securing his family ' s financial future before he dies. " ,
' poster ' : u ' http://thetvdb.com/banners/posters/81189-22.jpg ' ,
' rating ' : u ' 9.3 ' ,
' ratingcount ' : u ' 473 ' ,
' runtime ' : u ' 60 ' ,
' seriesid ' : u ' 74713 ' ,
' seriesname ' : u ' Breaking Bad ' ,
' status ' : u ' Continuing ' ,
' zap2it_id ' : u ' SH01009396 ' }
"""
## Images
poster = self . getImage ( show , type = ' poster ' , size = ' cover ' )
backdrop = self . getImage ( show , type = ' fanart ' , size = ' w1280 ' )
#poster_original = self.getImage(show, type = 'poster', size = 'original')
#backdrop_original = self.getImage(show, type = 'backdrop', size = 'original')
## Genres
genres = [ ] if show [ ' genre ' ] is None else show [ ' genre ' ] . strip ( ' | ' ) . split ( ' | ' )
## Year (not really needed for show)
year = None
show_data = {
' via_thetvdb ' : True ,
' thetvdb_id ' : int ( show [ ' id ' ] ) ,
' titles ' : [ show [ ' seriesname ' ] , ] ,
' original_title ' : show [ ' seriesname ' ] ,
' images ' : {
' poster ' : [ poster ] if poster else [ ] ,
' backdrop ' : [ backdrop ] if backdrop else [ ] ,
' poster_original ' : [ ] ,
' backdrop_original ' : [ ] ,
} ,
' imdb ' : show [ ' imdb_id ' ] ,
' runtime ' : show [ ' runtime ' ] ,
' released ' : show [ ' firstaired ' ] ,
' year ' : year ,
' plot ' : show [ ' overview ' ] ,
' genres ' : genres ,
}
show_data = dict ( ( k , v ) for k , v in show_data . iteritems ( ) if v )
## Add alternative names
#for alt in ['original_name', 'alternative_name']:
#alt_name = toUnicode(show.get(alt))
#if alt_name and not alt_name in show_data['titles'] and alt_name.lower() != 'none' and alt_name != None:
#show_data['titles'].append(alt_name)
return show_data
def parseEpisode ( self , episode ) :
"""
( ' episodenumber ' , u ' 1 ' ) ,
( ' thumb_added ' , None ) ,
( ' rating ' , u ' 7.7 ' ) ,
( ' overview ' ,
u ' Experienced waitress Max Black meets her new co-worker, former rich-girl Caroline Channing, and puts her skills to the test at an old but re-emerging Brooklyn diner. Despite her initial distaste for Caroline, Max eventually softens and the two team up for a new business venture. ' ) ,
( ' dvd_episodenumber ' , None ) ,
( ' dvd_discid ' , None ) ,
( ' combined_episodenumber ' , u ' 1 ' ) ,
( ' epimgflag ' , u ' 7 ' ) ,
( ' id ' , u ' 4099506 ' ) ,
( ' seasonid ' , u ' 465948 ' ) ,
( ' thumb_height ' , u ' 225 ' ) ,
( ' tms_export ' , u ' 1374789754 ' ) ,
( ' seasonnumber ' , u ' 1 ' ) ,
( ' writer ' , u ' |Michael Patrick King|Whitney Cummings| ' ) ,
( ' lastupdated ' , u ' 1371420338 ' ) ,
( ' filename ' , u ' http://thetvdb.com/banners/episodes/248741/4099506.jpg ' ) ,
( ' absolute_number ' , u ' 1 ' ) ,
( ' ratingcount ' , u ' 102 ' ) ,
( ' combined_season ' , u ' 1 ' ) ,
( ' thumb_width ' , u ' 400 ' ) ,
( ' imdb_id ' , u ' tt1980319 ' ) ,
( ' director ' , u ' James Burrows ' ) ,
( ' dvd_chapter ' , None ) ,
( ' dvd_season ' , None ) ,
( ' gueststars ' ,
u ' |Brooke Lyons|Noah Mills|Shoshana Bush|Cale Hartmann|Adam Korson|Alex Enriquez|Matt Cook|Bill Parks|Eugene Shaw|Sergey Brusilovsky|Greg Lewis|Cocoa Brown|Nick Jameson| ' ) ,
( ' seriesid ' , u ' 248741 ' ) ,
( ' language ' , u ' en ' ) ,
( ' productioncode ' , u ' 296793 ' ) ,
( ' firstaired ' , u ' 2011-09-19 ' ) ,
( ' episodename ' , u ' Pilot ' ) ]
"""
## Images
#poster = self.getImage(episode, type = 'poster', size = 'cover')
#backdrop = self.getImage(episode, type = 'fanart', size = 'w1280')
##poster_original = self.getImage(episode, type = 'poster', size = 'original')
##backdrop_original = self.getImage(episode, type = 'backdrop', size = 'original')
poster = [ ]
backdrop = [ ]
## Genres
genres = [ ]
## Year (not really needed for episode)
year = None
episode_data = {
' via_thetvdb ' : True ,
' thetvdb_id ' : int ( episode [ ' id ' ] ) ,
' titles ' : [ episode [ ' episodename ' ] , ] ,
' original_title ' : episode [ ' episodename ' ] ,
' images ' : {
' poster ' : [ poster ] if poster else [ ] ,
' backdrop ' : [ backdrop ] if backdrop else [ ] ,
' poster_original ' : [ ] ,
' backdrop_original ' : [ ] ,
} ,
' imdb ' : episode [ ' imdb_id ' ] ,
' runtime ' : None ,
' released ' : episode [ ' firstaired ' ] ,
' year ' : year ,
' plot ' : episode [ ' overview ' ] ,
' genres ' : genres ,
}
episode_data = dict ( ( k , v ) for k , v in episode_data . iteritems ( ) if v )
## Add alternative names
#for alt in ['original_name', 'alternative_name']:
#alt_name = toUnicode(episode.get(alt))
#if alt_name and not alt_name in episode_data['titles'] and alt_name.lower() != 'none' and alt_name != None:
#episode_data['titles'].append(alt_name)
return episode_data
def getImage ( self , show , type = ' poster ' , size = ' cover ' ) :
""" """
# XXX: Need to implement size
image_url = ' '
for res , res_data in show [ ' _banners ' ] . get ( type , { } ) . items ( ) :
for bid , banner_info in res_data . items ( ) :
image_url = banner_info . get ( ' _bannerpath ' , ' ' )
break
return image_url
def isDisabled ( self ) :
if self . conf ( ' api_key ' ) == ' ' :
log . error ( ' No API key provided. ' )
True
else :
False