Merge branch 'hotfix/0.16.16'

This commit is contained in:
JackDandy 2018-06-09 12:14:37 +01:00
commit 54a877d3e3
13 changed files with 257 additions and 247 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
@ -799,23 +799,28 @@ class Tvdb:
def _parse_actors(self, sid, actor_list): def _parse_actors(self, sid, actor_list):
cur_actors = Actors() a = []
try: try:
for curActorItem in actor_list: for n in sorted(actor_list, key=lambda x: x['sortorder']):
cur_actor = Actor() a.append({'character': {'id': None,
for k, v in curActorItem.iteritems(): 'name': n.get('role', '').strip(),
k = k.lower() 'url': None, # not supported by tvdb
if None is not v: 'image': (None, self.config['url_artworkPrefix'] %
if 'image' == k: n.get('image'))[any([n.get('image')])],
v = self.config['url_artworkPrefix'] % v },
else: 'person': {'id': None, # not supported by tvdb
v = self._clean_data(v) 'name': n.get('name', '').strip(),
cur_actor[k] = v 'url': None, # not supported by tvdb
cur_actors.append(cur_actor) 'image': None, # not supported by tvdb
'birthday': None, # not supported by tvdb
'deathday': None, # not supported by tvdb
'gender': None, # not supported by tvdb
'country': None, # not supported by tvdb
},
})
except (StandardError, Exception): except (StandardError, Exception):
pass pass
self._set_show_data(sid, 'actors', a)
self._set_show_data(sid, '_actors', cur_actors)
def get_episode_data(self, epid): def get_episode_data(self, epid):
# Parse episode information # Parse episode information
@ -907,12 +912,7 @@ class Tvdb:
if self.config['actors_enabled']: if self.config['actors_enabled']:
actor_data = self._getetsrc(self.config['url_actorsInfo'] % sid, language=language) actor_data = self._getetsrc(self.config['url_actorsInfo'] % sid, language=language)
if actor_data and len(actor_data.get('data', '') or '') > 0: if actor_data and len(actor_data.get('data', '') or '') > 0:
a = '|%s|' % '|'.join([n.get('name', '') for n in sorted(
actor_data['data'], key=lambda x: x['sortorder'])])
self._parse_actors(sid, actor_data['data']) self._parse_actors(sid, actor_data['data'])
else:
a = '||'
self._set_show_data(sid, u'actors', a)
if get_ep_info: if get_ep_info:
# Parse episode data # Parse episode data

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])
@ -771,23 +771,28 @@ class TvdbV1:
self.log('Getting actors for %s' % sid) self.log('Getting actors for %s' % sid)
actors_et = self._getetsrc(self.config['url_actorsInfo'] % sid) actors_et = self._getetsrc(self.config['url_actorsInfo'] % sid)
cur_actors = Actors() a = []
try: try:
for curActorItem in actors_et['actor']: for n in sorted(actors_et['Actor'], key=lambda x: x['SortOrder']):
cur_actor = Actor() a.append({'character': {'id': None,
for k, v in curActorItem.items(): 'name': n.get('Role', '').strip(),
k = k.lower() 'url': None, # not supported by tvdb
if None is not v: 'image': (None, self.config['url_artworkPrefix'] %
if 'image' == k: n.get('Image'))[any([n.get('Image')])],
v = self._get_url_artwork(v) },
else: 'person': {'id': None, # not supported by tvdb
v = self._clean_data(v) 'name': n.get('Name', '').strip(),
cur_actor[k] = v 'url': None, # not supported by tvdb
cur_actors.append(cur_actor) 'image': None, # not supported by tvdb
'birthday': None, # not supported by tvdb
'deathday': None, # not supported by tvdb
'gender': None, # not supported by tvdb
'country': None, # not supported by tvdb
},
})
except (StandardError, Exception): except (StandardError, Exception):
pass pass
self._set_show_data(sid, 'actors', a)
self._set_show_data(sid, '_actors', cur_actors)
def _get_show_data(self, sid, language, get_ep_info=False): def _get_show_data(self, sid, language, get_ep_info=False):
"""Takes a series ID, gets the epInfo URL and parses the TVDB """Takes a series ID, gets the epInfo URL and parses the TVDB
@ -822,14 +827,15 @@ class TvdbV1:
self._set_show_data(sid, k.lower(), v) self._set_show_data(sid, k.lower(), v)
if get_ep_info: # Parse actors
if self.config['actors_enabled']:
self._parse_actors(sid)
# Parse banners # Parse banners
if self.config['banners_enabled']: if self.config['banners_enabled']:
self._parse_banners(sid) self._parse_banners(sid)
# Parse actors if get_ep_info:
if self.config['actors_enabled']:
self._parse_actors(sid)
# Parse episode data # Parse episode data
self.log('Getting all episodes of %s' % sid) self.log('Getting all episodes of %s' % sid)

View file

@ -61,7 +61,7 @@ CFG = None
CONFIG_FILE = None CONFIG_FILE = None
# This is the version of the config we EXPECT to find # This is the version of the config we EXPECT to find
CONFIG_VERSION = 16 CONFIG_VERSION = 17
# Default encryption version (0 for None) # Default encryption version (0 for None)
ENCRYPTION_VERSION = 0 ENCRYPTION_VERSION = 0

View file

@ -465,7 +465,8 @@ class ConfigMigrator:
13: 'Change default dereferrer url to blank', 13: 'Change default dereferrer url to blank',
14: 'Convert Trakt to multi-account', 14: 'Convert Trakt to multi-account',
15: 'Transmithe.net rebranded Nebulance', 15: 'Transmithe.net rebranded Nebulance',
16: 'Purge old cache image folders'} 16: 'Purge old cache image folders',
17: 'Add "vp9", "av1" to ignore words if not found'}
def migrate_config(self): def migrate_config(self):
""" Calls each successive migration until the config is the same version as SG expects """ """ Calls each successive migration until the config is the same version as SG expects """
@ -844,3 +845,31 @@ class ConfigMigrator:
except OSError: except OSError:
pass pass
sickbeard.CACHE_DIR = cache_default sickbeard.CACHE_DIR = cache_default
@staticmethod
def add_ignore_words(wordlist):
# add words to ignore list and insert spaces to improve the ui config readability
if not isinstance(wordlist, list):
wordlist = [wordlist]
config_words = sickbeard.IGNORE_WORDS.split(',')
new_list = []
using_regex = ''
for new_word in wordlist:
add_word = True
for ignore_word in config_words:
ignored = ignore_word.strip().lower()
if ignored.startswith('regex:'):
ignored = ignored.lstrip('regex:')
using_regex = 'regex:'
if ignored and ignored not in new_list:
new_list += [ignored]
if new_word in ignored:
add_word = False
if add_word:
new_list += [new_word]
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,6 +396,7 @@ 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))
if syno:
# do the library update for synoindex # do the library update for synoindex
notifiers.NotifierFactory().get('SYNOINDEX').addFolder(sofar) notifiers.NotifierFactory().get('SYNOINDEX').addFolder(sofar)
except (OSError, IOError) as e: except (OSError, IOError) as e:
@ -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,7 +320,6 @@ 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)
@ -343,13 +342,9 @@ class GenericMetadata():
# 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,17 +362,19 @@ 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 = actor['character']['name']
if cur_actor_role_text:
cur_actor_role.text = 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,14 +275,15 @@ 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']
if cur_actor_role_text:
cur_actor_role.text = cur_actor_role_text cur_actor_role.text = cur_actor_role_text
overview = etree.SubElement(episode, "overview") overview = etree.SubElement(episode, "overview")

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