Fix metadata mediabrowser when no actors.

Change metadata usage of indexer api keys.
Change make tvdb_api docs consistent to the attributes for show object.
Change consolidate write_file at helpers.
This commit is contained in:
JackDandy 2018-06-09 12:13:21 +01:00
parent 990755f966
commit 0f6f31a3bf
12 changed files with 204 additions and 220 deletions

View file

@ -1,4 +1,10 @@
### 0.16.15 (2018-06-03 21:24:00 UTC) ### 0.16.16 (2018-06-09 12:13:00 UTC)
* Fix metadata mediabrowser when no actors
* Add 'vp9' and 'av1' to ignore word list
### 0.16.15 (2018-06-03 21:24:00 UTC)
* Change garbage_name regex * Change garbage_name regex

View file

@ -398,17 +398,17 @@ class Tvdb:
banners (True/False): banners (True/False):
Retrieves the banners for a show. These are accessed Retrieves the banners for a show. These are accessed
via the _banners key of a Show(), for example: via the banners key of a Show(), for example:
>> Tvdb(banners=True)['scrubs']['_banners'].keys() >> Tvdb(banners=True)['scrubs']['banners'].keys()
['fanart', 'poster', 'series', 'season'] ['fanart', 'poster', 'series', 'season']
actors (True/False): actors (True/False):
Retrieves a list of the actors for a show. These are accessed Retrieves a list of the actors for a show. These are accessed
via the _actors key of a Show(), for example: via the actors key of a Show(), for example:
>> t = Tvdb(actors=True) >> t = Tvdb(actors=True)
>> t['scrubs']['_actors'][0]['name'] >> t['scrubs']['actors'][0]['name']
u'Zach Braff' u'Zach Braff'
custom_ui (tvdb_ui.BaseUI subclass): custom_ui (tvdb_ui.BaseUI subclass):
@ -524,7 +524,7 @@ class Tvdb:
self.config['url_actorsInfo'] = '%(base_url)sseries/%%s/actors' % self.config self.config['url_actorsInfo'] = '%(base_url)sseries/%%s/actors' % self.config
self.config['url_seriesBanner'] = '%(base_url)sseries/%%s/images/query?keyType=%%s' % self.config self.config['url_seriesBanner'] = '%(base_url)sseries/%%s/images/query?keyType=%%s' % self.config
self.config['url_artworkPrefix'] = 'https://thetvdb.com/banners/%s' self.config['url_artworkPrefix'] = 'https://www.thetvdb.com/banners/%s'
def get_new_token(self): def get_new_token(self):
token = sickbeard.THETVDB_V2_API_TOKEN.get('token', None) token = sickbeard.THETVDB_V2_API_TOKEN.get('token', None)
@ -784,10 +784,10 @@ class Tvdb:
k, v = k.lower(), v.lower() if isinstance(v, (str, unicode)) else v k, v = k.lower(), v.lower() if isinstance(v, (str, unicode)) else v
if k == 'filename': if k == 'filename':
k = 'bannerpath' k = 'bannerpath'
banners[btype][btype2][bid]['_bannerpath'] = self.config['url_artworkPrefix'] % v banners[btype][btype2][bid]['bannerpath'] = self.config['url_artworkPrefix'] % v
elif k == 'thumbnail': elif k == 'thumbnail':
k = 'thumbnailpath' k = 'thumbnailpath'
banners[btype][btype2][bid]['_thumbnailpath'] = self.config['url_artworkPrefix'] % v banners[btype][btype2][bid]['thumbnailpath'] = self.config['url_artworkPrefix'] % v
elif k == 'keytype': elif k == 'keytype':
k = 'bannertype' k = 'bannertype'
banners[btype][btype2][bid][k] = v banners[btype][btype2][bid][k] = v
@ -803,14 +803,14 @@ class Tvdb:
try: try:
for n in sorted(actor_list, key=lambda x: x['sortorder']): for n in sorted(actor_list, key=lambda x: x['sortorder']):
a.append({'character': {'id': None, a.append({'character': {'id': None,
'name': n.get('role', ''), 'name': n.get('role', '').strip(),
'url': None, # not supported by tvdb 'url': None, # not supported by tvdb
'image': (None, self.config['url_artworkPrefix'] % n.get('image')) 'image': (None, self.config['url_artworkPrefix'] %
[n.get('image')not in (None, '')], n.get('image'))[any([n.get('image')])],
}, },
'person': {'id': None, # not supported by tvdb 'person': {'id': None, # not supported by tvdb
'name': n.get('name', ''), 'name': n.get('name', '').strip(),
'url': '', # not supported by tvdb 'url': None, # not supported by tvdb
'image': None, # not supported by tvdb 'image': None, # not supported by tvdb
'birthday': None, # not supported by tvdb 'birthday': None, # not supported by tvdb
'deathday': None, # not supported by tvdb 'deathday': None, # not supported by tvdb

View file

@ -380,7 +380,7 @@ class TvdbV1:
Retrieves the banners for a show. These are accessed Retrieves the banners for a show. These are accessed
via the _banners key of a Show(), for example: via the _banners key of a Show(), for example:
>> Tvdb(banners=True)['scrubs']['_banners'].keys() >> Tvdb(banners=True)['scrubs']['banners'].keys()
['fanart', 'poster', 'series', 'season'] ['fanart', 'poster', 'series', 'season']
actors (True/False): actors (True/False):
@ -388,7 +388,7 @@ class TvdbV1:
via the _actors key of a Show(), for example: via the _actors key of a Show(), for example:
>> t = Tvdb(actors=True) >> t = Tvdb(actors=True)
>> t['scrubs']['_actors'][0]['name'] >> t['scrubs']['actors'][0]['name']
u'Zach Braff' u'Zach Braff'
custom_ui (tvdb_ui.BaseUI subclass): custom_ui (tvdb_ui.BaseUI subclass):
@ -514,7 +514,7 @@ class TvdbV1:
self.config['url_actorsInfo'] = u'%(base_url)s/api/%(apikey)s/series/%%s/actors.xml' % self.config self.config['url_actorsInfo'] = u'%(base_url)s/api/%(apikey)s/series/%%s/actors.xml' % self.config
self.config['url_seriesBanner'] = u'%(base_url)s/api/%(apikey)s/series/%%s/banners.xml' % self.config self.config['url_seriesBanner'] = u'%(base_url)s/api/%(apikey)s/series/%%s/banners.xml' % self.config
self.config['url_artworkPrefix'] = u'%(base_url)s/banners/%%s' % self.config self.config['url_artworkPrefix'] = u'https://thetvdb.com/banners/%%s' % self.config
def log(self, msg, log_level=logger.DEBUG): def log(self, msg, log_level=logger.DEBUG):
logger.log('TVDB_API :: %s' % (msg.replace(self.config['apikey'], '<apikey>')), log_level=log_level) logger.log('TVDB_API :: %s' % (msg.replace(self.config['apikey'], '<apikey>')), log_level=log_level)
@ -699,7 +699,7 @@ class TvdbV1:
>> t = Tvdb(banners = True) >> t = Tvdb(banners = True)
>> t['scrubs']['_banners'].keys() >> t['scrubs']['_banners'].keys()
['fanart', 'poster', 'series', 'season'] ['fanart', 'poster', 'series', 'season']
>> t['scrubs']['_banners']['poster']['680x1000']['35308']['_bannerpath'] >> t['scrubs']['_banners']['poster']['680x1000']['35308']['bannerpath']
u'http://thetvdb.com/banners/posters/76156-2.jpg' u'http://thetvdb.com/banners/posters/76156-2.jpg'
>> >>
@ -751,7 +751,7 @@ class TvdbV1:
Actors are retrieved using t['show name]['_actors'], for example: Actors are retrieved using t['show name]['_actors'], for example:
>> t = Tvdb(actors = True) >> t = Tvdb(actors = True)
>> actors = t['scrubs']['_actors'] >> actors = t['scrubs']['actors']
>> type(actors) >> type(actors)
<class 'tvdb_api.Actors'> <class 'tvdb_api.Actors'>
>> type(actors[0]) >> type(actors[0])
@ -775,14 +775,14 @@ class TvdbV1:
try: try:
for n in sorted(actors_et['Actor'], key=lambda x: x['SortOrder']): for n in sorted(actors_et['Actor'], key=lambda x: x['SortOrder']):
a.append({'character': {'id': None, a.append({'character': {'id': None,
'name': n.get('Role', ''), 'name': n.get('Role', '').strip(),
'url': None, # not supported by tvdb 'url': None, # not supported by tvdb
'image': (None, self.config['url_artworkPrefix'] % n.get('Image')) 'image': (None, self.config['url_artworkPrefix'] %
[n.get('Image')not in (None, '')], n.get('Image'))[any([n.get('Image')])],
}, },
'person': {'id': None, # not supported by tvdb 'person': {'id': None, # not supported by tvdb
'name': n.get('Name', ''), 'name': n.get('Name', '').strip(),
'url': '', # not supported by tvdb 'url': None, # not supported by tvdb
'image': None, # not supported by tvdb 'image': None, # not supported by tvdb
'birthday': None, # not supported by tvdb 'birthday': None, # not supported by tvdb
'deathday': None, # not supported by tvdb 'deathday': None, # not supported by tvdb

View file

@ -847,20 +847,29 @@ class ConfigMigrator:
sickbeard.CACHE_DIR = cache_default sickbeard.CACHE_DIR = cache_default
@staticmethod @staticmethod
def _migrate_v17(): def add_ignore_words(wordlist):
# add words to ignore list and insert spaces to improve the ui config readability # add words to ignore list and insert spaces to improve the ui config readability
words_to_add = ['vp9', 'av1'] if not isinstance(wordlist, list):
wordlist = [wordlist]
config_words = sickbeard.IGNORE_WORDS.split(',') config_words = sickbeard.IGNORE_WORDS.split(',')
new_list = [] new_list = []
for new_word in words_to_add: using_regex = ''
for new_word in wordlist:
add_word = True add_word = True
for ignore_word in config_words: for ignore_word in config_words:
ignored = ignore_word.strip().lower() ignored = ignore_word.strip().lower()
if ignored.startswith('regex:'):
ignored = ignored.lstrip('regex:')
using_regex = 'regex:'
if ignored and ignored not in new_list: if ignored and ignored not in new_list:
new_list += [ignored] new_list += [ignored]
if re.search(r'(?i)%s' % new_word, ignored): if new_word in ignored:
add_word = False add_word = False
if add_word: if add_word:
new_list += [new_word] new_list += [new_word]
sickbeard.IGNORE_WORDS = ', '.join(sorted(new_list)) sickbeard.IGNORE_WORDS = '%s%s' % (using_regex, ', '.join(new_list))
def _migrate_v17(self):
self.add_ignore_words(['vp9', 'av1'])

View file

@ -20,9 +20,11 @@ from __future__ import print_function
from __future__ import with_statement from __future__ import with_statement
import base64 import base64
import codecs
import datetime import datetime
import getpass import getpass
import hashlib import hashlib
import io
import os import os
import re import re
import shutil import shutil
@ -360,7 +362,7 @@ def moveAndSymlinkFile(srcFile, destFile):
copyFile(srcFile, destFile) copyFile(srcFile, destFile)
def make_dirs(path): def make_dirs(path, syno=True):
""" """
Creates any folders that are missing and assigns them the permissions of their Creates any folders that are missing and assigns them the permissions of their
parents parents
@ -394,8 +396,9 @@ def make_dirs(path):
ek.ek(os.mkdir, sofar) ek.ek(os.mkdir, sofar)
# use normpath to remove end separator, otherwise checks permissions against itself # use normpath to remove end separator, otherwise checks permissions against itself
chmodAsParent(ek.ek(os.path.normpath, sofar)) chmodAsParent(ek.ek(os.path.normpath, sofar))
# do the library update for synoindex if syno:
notifiers.NotifierFactory().get('SYNOINDEX').addFolder(sofar) # do the library update for synoindex
notifiers.NotifierFactory().get('SYNOINDEX').addFolder(sofar)
except (OSError, IOError) as e: except (OSError, IOError) as e:
logger.log(u'Failed creating %s : %s' % (sofar, ex(e)), logger.ERROR) logger.log(u'Failed creating %s : %s' % (sofar, ex(e)), logger.ERROR)
return False return False
@ -1251,17 +1254,8 @@ def getURL(url, post_data=None, params=None, headers=None, timeout=30, session=N
if savename: if savename:
try: try:
with open(savename, 'wb') as fp: write_file(savename, response, raw=True, raise_exceptions=raise_exceptions)
for chunk in response.iter_content(chunk_size=1024): except (StandardError, Exception) as e:
if chunk:
fp.write(chunk)
fp.flush()
ek.ek(os.fsync, fp.fileno())
chmodAsParent(savename)
except EnvironmentError as e:
logger.log(u'Unable to save the file: ' + ex(e), logger.ERROR)
if raise_exceptions: if raise_exceptions:
raise e raise e
return return
@ -1703,3 +1697,44 @@ def path_mapper(search, replace, subject):
result = os.path.normpath(re.sub(delim, '/', result)) result = os.path.normpath(re.sub(delim, '/', result))
return result, result != subject return result, result != subject
def write_file(filepath, data, raw=False, xmltree=False, utf8=False, raise_exceptions=False):
result = False
if make_dirs(ek.ek(os.path.dirname, filepath), False):
try:
if raw:
with io.FileIO(filepath, 'wb') as fh:
for chunk in data.iter_content(chunk_size=1024):
if chunk:
fh.write(chunk)
fh.flush()
ek.ek(os.fsync, fh.fileno())
else:
w_mode = 'w'
if utf8:
w_mode = 'a'
with io.FileIO(filepath, 'wb') as fh:
fh.write(codecs.BOM_UTF8)
if xmltree:
with io.FileIO(filepath, w_mode) as fh:
if utf8:
data.write(fh, encoding='utf-8')
else:
data.write(fh)
else:
with io.FileIO(filepath, w_mode) as fh:
fh.write(data)
chmodAsParent(filepath)
result = True
except (EnvironmentError, IOError) as e:
logger.log('Unable to write file %s : %s' % (filepath, ex(e)), logger.ERROR)
if raise_exceptions:
raise e
return result

View file

@ -320,36 +320,31 @@ class GenericMetadata():
logger.DEBUG) logger.DEBUG)
nfo_file_path = self.get_show_file_path(show_obj) nfo_file_path = self.get_show_file_path(show_obj)
try: with ek.ek(open, nfo_file_path, 'r') as xmlFileObj:
with ek.ek(open, nfo_file_path, 'r') as xmlFileObj: show_xml = etree.ElementTree(file=xmlFileObj)
show_xml = etree.ElementTree(file=xmlFileObj)
indexer = show_xml.find('indexer') indexer = show_xml.find('indexer')
indexerid = show_xml.find('id') indexerid = show_xml.find('id')
root = show_xml.getroot() root = show_xml.getroot()
show_indexer = str(show_obj.indexer) show_indexer = str(show_obj.indexer)
if None is not indexer: if None is not indexer:
indexer.text = show_indexer indexer.text = show_indexer
else: else:
etree.SubElement(root, 'indexer').text = show_indexer etree.SubElement(root, 'indexer').text = show_indexer
show_indexerid = str(show_obj.indexerid) show_indexerid = str(show_obj.indexerid)
if None is not indexerid: if None is not indexerid:
indexerid.text = show_indexerid indexerid.text = show_indexerid
else: else:
etree.SubElement(root, 'id').text = show_indexerid etree.SubElement(root, 'id').text = show_indexerid
# Make it purdy # Make it purdy
helpers.indentXML(root) helpers.indentXML(root)
show_xml.write(nfo_file_path) helpers.write_file(nfo_file_path, show_xml, xmltree=True, utf8=True)
helpers.chmodAsParent(nfo_file_path)
return True return True
except IOError as e:
logger.log(u'Unable to write file %s - is the folder writable? %s' % (nfo_file_path, ex(e)),
logger.ERROR)
def create_fanart(self, show_obj): def create_fanart(self, show_obj):
if self.fanart and show_obj and not self._has_fanart(show_obj): if self.fanart and show_obj and not self._has_fanart(show_obj):
@ -476,27 +471,10 @@ class GenericMetadata():
return False return False
nfo_file_path = self.get_show_file_path(show_obj) nfo_file_path = self.get_show_file_path(show_obj)
nfo_file_dir = ek.ek(os.path.dirname, nfo_file_path)
try: logger.log(u'Writing show metadata file: %s' % nfo_file_path, logger.DEBUG)
if not ek.ek(os.path.isdir, nfo_file_dir):
logger.log(u"Metadata dir didn't exist, creating it at " + nfo_file_dir, logger.DEBUG)
ek.ek(os.makedirs, nfo_file_dir)
helpers.chmodAsParent(nfo_file_dir)
logger.log(u"Writing show nfo file to " + nfo_file_path, logger.DEBUG) return helpers.write_file(nfo_file_path, data, xmltree=True, utf8=True)
nfo_file = ek.ek(open, nfo_file_path, 'w')
data.write(nfo_file, encoding="utf-8")
nfo_file.close()
helpers.chmodAsParent(nfo_file_path)
except IOError as e:
logger.log(u"Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + ex(e),
logger.ERROR)
return False
return True
def write_ep_file(self, ep_obj): def write_ep_file(self, ep_obj):
""" """
@ -521,27 +499,10 @@ class GenericMetadata():
return False return False
nfo_file_path = self.get_episode_file_path(ep_obj) nfo_file_path = self.get_episode_file_path(ep_obj)
nfo_file_dir = ek.ek(os.path.dirname, nfo_file_path)
try: logger.log(u'Writing episode metadata file: %s' % nfo_file_path, logger.DEBUG)
if not ek.ek(os.path.isdir, nfo_file_dir):
logger.log(u"Metadata dir didn't exist, creating it at " + nfo_file_dir, logger.DEBUG)
ek.ek(os.makedirs, nfo_file_dir)
helpers.chmodAsParent(nfo_file_dir)
logger.log(u"Writing episode nfo file to " + nfo_file_path, logger.DEBUG) return helpers.write_file(nfo_file_path, data, xmltree=True, utf8=True)
nfo_file = ek.ek(open, nfo_file_path, 'w')
data.write(nfo_file, encoding="utf-8")
nfo_file.close()
helpers.chmodAsParent(nfo_file_path)
except IOError as e:
logger.log(u"Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + ex(e),
logger.ERROR)
return False
return True
def save_thumbnail(self, ep_obj): def save_thumbnail(self, ep_obj):
""" """
@ -911,12 +872,12 @@ class GenericMetadata():
if not self._valid_show(indexer_show_obj, show_obj): if not self._valid_show(indexer_show_obj, show_obj):
return result return result
season_images = getattr(indexer_show_obj, '_banners', {}).get( season_images = getattr(indexer_show_obj, 'banners', {}).get(
('season', 'seasonwide')['seasonwides' == image_type], {}).get(season, {}) ('season', 'seasonwide')['seasonwides' == image_type], {}).get(season, {})
for image_id in season_images.keys(): for image_id in season_images.keys():
if season not in result: if season not in result:
result[season] = {} result[season] = {}
result[season][image_id] = season_images[image_id]['_bannerpath'] result[season][image_id] = season_images[image_id]['bannerpath']
return result return result

View file

@ -187,24 +187,7 @@ class KODIMetadata(generic.GenericMetadata):
if getattr(myShow, 'network', None) is not None: if getattr(myShow, 'network', None) is not None:
studio.text = myShow['network'] studio.text = myShow['network']
if getattr(myShow, '_actors', None) is not None: self.add_actor_element(myShow, etree, tv_node)
for actor in myShow['_actors']:
cur_actor = etree.SubElement(tv_node, 'actor')
cur_actor_name = etree.SubElement(cur_actor, 'name')
cur_actor_name_text = actor['name']
if isinstance(cur_actor_name_text, basestring):
cur_actor_name.text = cur_actor_name_text.strip()
cur_actor_role = etree.SubElement(cur_actor, 'role')
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = etree.SubElement(cur_actor, 'thumb')
cur_actor_thumb_text = actor['image']
if cur_actor_thumb_text != None:
cur_actor_thumb.text = cur_actor_thumb_text
# Make it purdy # Make it purdy
helpers.indentXML(tv_node) helpers.indentXML(tv_node)
@ -351,24 +334,7 @@ class KODIMetadata(generic.GenericMetadata):
cur_actor_name = etree.SubElement(cur_actor, 'name') cur_actor_name = etree.SubElement(cur_actor, 'name')
cur_actor_name.text = actor cur_actor_name.text = actor
if getattr(myEp, '_actors', None) is not None: self.add_actor_element(myShow, etree, episode)
for actor in myShow['_actors']:
cur_actor = etree.SubElement(episode, 'actor')
cur_actor_name = etree.SubElement(cur_actor, 'name')
cur_actor_name_text = actor['name']
if isinstance(cur_actor_name_text, basestring):
cur_actor_name.text = cur_actor_name_text.strip()
cur_actor_role = etree.SubElement(cur_actor, 'role')
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = etree.SubElement(cur_actor, 'thumb')
cur_actor_thumb_text = actor['image']
if cur_actor_thumb_text != None:
cur_actor_thumb.text = cur_actor_thumb_text
# Make it purdy # Make it purdy
helpers.indentXML(rootNode) helpers.indentXML(rootNode)
@ -377,6 +343,26 @@ class KODIMetadata(generic.GenericMetadata):
return data return data
@staticmethod
def add_actor_element(my_show, et, node):
for actor in getattr(my_show, 'actors', []):
cur_actor = et.SubElement(node, 'actor')
cur_actor_name = et.SubElement(cur_actor, 'name')
cur_actor_name_text = actor['person']['name']
if cur_actor_name_text:
cur_actor_name.text = cur_actor_name_text
cur_actor_role = et.SubElement(cur_actor, 'role')
cur_actor_role_text = actor['character']['name']
if cur_actor_role_text:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = et.SubElement(cur_actor, 'thumb')
cur_actor_thumb_text = actor['character']['image']
if None is not cur_actor_thumb_text:
cur_actor_thumb.text = cur_actor_thumb_text
# present a standard "interface" from the module # present a standard "interface" from the module
metadata_class = KODIMetadata metadata_class = KODIMetadata

View file

@ -199,14 +199,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
Runtime.text = myShow['runtime'] Runtime.text = myShow['runtime']
cast = etree.SubElement(tv_node, "cast") cast = etree.SubElement(tv_node, "cast")
self.add_actor_element(myShow, etree, cast)
if getattr(myShow, '_actors', None) is not None:
for actor in myShow['_actors']:
cur_actor_name_text = actor['name']
if cur_actor_name_text != None and cur_actor_name_text.strip():
cur_actor = etree.SubElement(cast, "actor")
cur_actor.text = cur_actor_name_text.strip()
helpers.indentXML(rootNode) helpers.indentXML(rootNode)
@ -333,14 +326,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
credits.text = credits_text credits.text = credits_text
cast = etree.SubElement(episode, "cast") cast = etree.SubElement(episode, "cast")
self.add_actor_element(myShow, etree, cast)
if getattr(myShow, '_actors', None) is not None:
for actor in myShow['_actors']:
cur_actor_name_text = actor['name']
if cur_actor_name_text != None and cur_actor_name_text.strip():
cur_actor = etree.SubElement(cast, "actor")
cur_actor.text = cur_actor_name_text.strip()
else: else:
# append data from (if any) related episodes # append data from (if any) related episodes
@ -362,6 +348,17 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
return data return data
@staticmethod
def add_actor_element(my_show, et, node):
for actor in getattr(my_show, 'actors', []):
cur_actor_name_text = actor['character']['name'] and actor['person']['name'] \
and actor['character']['name'] != actor['person']['name'] \
and '%s (%s)' % (actor['character']['name'], actor['person']['name']) \
or actor['person']['name'] or actor['character']['name']
if cur_actor_name_text:
cur_actor = et.SubElement(node, 'actor')
cur_actor.text = cur_actor_name_text
# present a standard "interface" from the module # present a standard "interface" from the module
metadata_class = Mede8erMetadata metadata_class = Mede8erMetadata

View file

@ -362,18 +362,20 @@ class MediaBrowserMetadata(generic.GenericMetadata):
if getattr(myShow, 'network', None) is not None: if getattr(myShow, 'network', None) is not None:
Studio.text = myShow['network'] Studio.text = myShow['network']
Persons = etree.SubElement(tv_node, "Persons") Persons = etree.SubElement(tv_node, 'Persons')
if getattr(myShow, 'actors', None) is not None: for actor in getattr(myShow, 'actors', []):
for actor in myShow['_actors']: cur_actor = etree.SubElement(Persons, 'Person')
cur_actor = etree.SubElement(Persons, "Person")
cur_actor_name = etree.SubElement(cur_actor, "Name") cur_actor_name = etree.SubElement(cur_actor, 'Name')
cur_actor_name.text = actor['name'].strip() cur_actor_name.text = actor['person']['name']
cur_actor_type = etree.SubElement(cur_actor, "Type")
cur_actor_type.text = "Actor" cur_actor_type = etree.SubElement(cur_actor, 'Type')
cur_actor_role = etree.SubElement(cur_actor, "Role") cur_actor_type.text = 'Actor'
cur_actor_role_text = actor['role']
if cur_actor_role_text != None: cur_actor_role = etree.SubElement(cur_actor, 'Role')
cur_actor_role.text = cur_actor_role_text cur_actor_role_text = actor['character']['name']
if cur_actor_role_text:
cur_actor_role.text = cur_actor_role_text
helpers.indentXML(tv_node) helpers.indentXML(tv_node)

View file

@ -252,15 +252,16 @@ class TIVOMetadata(generic.GenericMetadata):
# This must be entered as yyyy-mm-ddThh:mm:ssZ (the t is capitalized and never changes, the Z is also # This must be entered as yyyy-mm-ddThh:mm:ssZ (the t is capitalized and never changes, the Z is also
# capitalized and never changes). This is the original air date of the episode. # capitalized and never changes). This is the original air date of the episode.
# NOTE: Hard coded the time to T00:00:00Z as we really don't know when during the day the first run happened. # NOTE: Hard coded the time to T00:00:00Z as we really don't know when during the day the first run happened
if curEpToWrite.airdate != datetime.date.fromordinal(1): if curEpToWrite.airdate != datetime.date.fromordinal(1):
data += ("originalAirDate : " + str(curEpToWrite.airdate) + "T00:00:00Z\n") data += ("originalAirDate : " + str(curEpToWrite.airdate) + "T00:00:00Z\n")
# This shows up at the beginning of the description on the Program screen and on the Details screen. # This shows up at the beginning of the description on the Program screen and on the Details screen.
if getattr(myShow, 'actors', None) is not None: for actor in getattr(myShow, 'actors', []):
for actor in myShow["actors"].split('|'): data += ('vActor : %s\n' % actor['character']['name'] and actor['person']['name']
if actor: and actor['character']['name'] != actor['person']['name']
data += ("vActor : " + actor + "\n") and '%s (%s)' % (actor['character']['name'], actor['person']['name'])
or actor['person']['name'] or actor['character']['name'])
# This is shown on both the Program screen and the Details screen. # This is shown on both the Program screen and the Details screen.
if getattr(myEp, 'rating', None) is not None: if getattr(myEp, 'rating', None) is not None:

View file

@ -275,15 +275,16 @@ class WDTVMetadata(generic.GenericMetadata):
if director_text is not None: if director_text is not None:
director.text = director_text director.text = director_text
if getattr(myShow, '_actors', None) is not None: for actor in getattr(myShow, 'actors', []):
for actor in myShow['_actors']: cur_actor = etree.SubElement(episode, 'actor')
cur_actor = etree.SubElement(episode, "actor")
cur_actor_name = etree.SubElement(cur_actor, "name") cur_actor_name = etree.SubElement(cur_actor, 'name')
cur_actor_name.text = actor['name'] cur_actor_name.text = actor['person']['name']
cur_actor_role = etree.SubElement(cur_actor, "role")
cur_actor_role_text = actor['role'] cur_actor_role = etree.SubElement(cur_actor, 'role')
if cur_actor_role_text != None: cur_actor_role_text = actor['character']['name']
cur_actor_role.text = cur_actor_role_text if cur_actor_role_text:
cur_actor_role.text = cur_actor_role_text
overview = etree.SubElement(episode, "overview") overview = etree.SubElement(episode, "overview")
if curEpToWrite.description != None: if curEpToWrite.description != None:

View file

@ -187,24 +187,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
if getattr(myShow, 'network', None) is not None: if getattr(myShow, 'network', None) is not None:
studio.text = myShow["network"] studio.text = myShow["network"]
if getattr(myShow, '_actors', None) is not None: self.add_actor_element(myShow, etree, tv_node)
for actor in myShow['_actors']:
cur_actor = etree.SubElement(tv_node, "actor")
cur_actor_name = etree.SubElement(cur_actor, "name")
cur_actor_name_text = actor['name']
if isinstance(cur_actor_name_text, basestring):
cur_actor_name.text = cur_actor_name_text.strip()
cur_actor_role = etree.SubElement(cur_actor, "role")
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = etree.SubElement(cur_actor, "thumb")
cur_actor_thumb_text = actor['image']
if cur_actor_thumb_text != None:
cur_actor_thumb.text = cur_actor_thumb_text
# Make it purdy # Make it purdy
helpers.indentXML(tv_node) helpers.indentXML(tv_node)
@ -354,24 +337,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
cur_actor_name = etree.SubElement(cur_actor, "name") cur_actor_name = etree.SubElement(cur_actor, "name")
cur_actor_name.text = actor cur_actor_name.text = actor
if getattr(myEp, '_actors', None) is not None: self.add_actor_element(myShow, etree, episode)
for actor in myShow['_actors']:
cur_actor = etree.SubElement(episode, "actor")
cur_actor_name = etree.SubElement(cur_actor, "name")
cur_actor_name_text = actor['name']
if isinstance(cur_actor_name_text, basestring):
cur_actor_name.text = cur_actor_name_text.strip()
cur_actor_role = etree.SubElement(cur_actor, "role")
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = etree.SubElement(cur_actor, "thumb")
cur_actor_thumb_text = actor['image']
if cur_actor_thumb_text != None:
cur_actor_thumb.text = cur_actor_thumb_text
# Make it purdy # Make it purdy
helpers.indentXML(rootNode) helpers.indentXML(rootNode)
@ -380,6 +346,26 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
return data return data
@staticmethod
def add_actor_element(my_show, et, node):
for actor in getattr(my_show, 'actors', []):
cur_actor = et.SubElement(node, 'actor')
cur_actor_name = et.SubElement(cur_actor, 'name')
cur_actor_name_text = actor['person']['name']
if cur_actor_name_text:
cur_actor_name.text = cur_actor_name_text
cur_actor_role = et.SubElement(cur_actor, 'role')
cur_actor_role_text = actor['character']['name']
if cur_actor_role_text:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = et.SubElement(cur_actor, 'thumb')
cur_actor_thumb_text = actor['character']['image']
if None is not cur_actor_thumb_text:
cur_actor_thumb.text = cur_actor_thumb_text
# present a standard "interface" from the module # present a standard "interface" from the module
metadata_class = XBMC_12PlusMetadata metadata_class = XBMC_12PlusMetadata