From 0f6f31a3bf91a2c78789f34e5eec0382bea1b632 Mon Sep 17 00:00:00 2001 From: JackDandy Date: Sat, 9 Jun 2018 12:13:21 +0100 Subject: [PATCH] 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. --- CHANGES.md | 8 ++- lib/tvdb_api/tvdb_api.py | 24 ++++---- lib/tvdb_api_v1/tvdb_api.py | 20 +++---- sickbeard/config.py | 19 +++++-- sickbeard/helpers.py | 63 ++++++++++++++++----- sickbeard/metadata/generic.py | 89 +++++++++--------------------- sickbeard/metadata/kodi.py | 58 ++++++++----------- sickbeard/metadata/mede8er.py | 29 +++++----- sickbeard/metadata/mediabrowser.py | 26 +++++---- sickbeard/metadata/tivo.py | 11 ++-- sickbeard/metadata/wdtv.py | 19 ++++--- sickbeard/metadata/xbmc_12plus.py | 58 ++++++++----------- 12 files changed, 204 insertions(+), 220 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ed6ac47a..15cce63c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py index 6aa7d113..c084fbda 100644 --- a/lib/tvdb_api/tvdb_api.py +++ b/lib/tvdb_api/tvdb_api.py @@ -398,17 +398,17 @@ class Tvdb: banners (True/False): 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'] actors (True/False): 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['scrubs']['_actors'][0]['name'] + >> t['scrubs']['actors'][0]['name'] u'Zach Braff' 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_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): 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 if k == 'filename': 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': 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': k = 'bannertype' banners[btype][btype2][bid][k] = v @@ -803,14 +803,14 @@ class Tvdb: try: for n in sorted(actor_list, key=lambda x: x['sortorder']): a.append({'character': {'id': None, - 'name': n.get('role', ''), + 'name': n.get('role', '').strip(), 'url': None, # not supported by tvdb - 'image': (None, self.config['url_artworkPrefix'] % n.get('image')) - [n.get('image')not in (None, '')], + 'image': (None, self.config['url_artworkPrefix'] % + n.get('image'))[any([n.get('image')])], }, 'person': {'id': None, # not supported by tvdb - 'name': n.get('name', ''), - 'url': '', # not supported by tvdb + 'name': n.get('name', '').strip(), + 'url': None, # not supported by tvdb 'image': None, # not supported by tvdb 'birthday': None, # not supported by tvdb 'deathday': None, # not supported by tvdb diff --git a/lib/tvdb_api_v1/tvdb_api.py b/lib/tvdb_api_v1/tvdb_api.py index d5854d03..7e70c89a 100644 --- a/lib/tvdb_api_v1/tvdb_api.py +++ b/lib/tvdb_api_v1/tvdb_api.py @@ -380,7 +380,7 @@ class TvdbV1: Retrieves the banners for a show. These are accessed 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'] actors (True/False): @@ -388,7 +388,7 @@ class TvdbV1: via the _actors key of a Show(), for example: >> t = Tvdb(actors=True) - >> t['scrubs']['_actors'][0]['name'] + >> t['scrubs']['actors'][0]['name'] u'Zach Braff' 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_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): logger.log('TVDB_API :: %s' % (msg.replace(self.config['apikey'], '')), log_level=log_level) @@ -699,7 +699,7 @@ class TvdbV1: >> t = Tvdb(banners = True) >> t['scrubs']['_banners'].keys() ['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' >> @@ -751,7 +751,7 @@ class TvdbV1: Actors are retrieved using t['show name]['_actors'], for example: >> t = Tvdb(actors = True) - >> actors = t['scrubs']['_actors'] + >> actors = t['scrubs']['actors'] >> type(actors) >> type(actors[0]) @@ -775,14 +775,14 @@ class TvdbV1: try: for n in sorted(actors_et['Actor'], key=lambda x: x['SortOrder']): a.append({'character': {'id': None, - 'name': n.get('Role', ''), + 'name': n.get('Role', '').strip(), 'url': None, # not supported by tvdb - 'image': (None, self.config['url_artworkPrefix'] % n.get('Image')) - [n.get('Image')not in (None, '')], + 'image': (None, self.config['url_artworkPrefix'] % + n.get('Image'))[any([n.get('Image')])], }, 'person': {'id': None, # not supported by tvdb - 'name': n.get('Name', ''), - 'url': '', # not supported by tvdb + 'name': n.get('Name', '').strip(), + 'url': None, # not supported by tvdb 'image': None, # not supported by tvdb 'birthday': None, # not supported by tvdb 'deathday': None, # not supported by tvdb diff --git a/sickbeard/config.py b/sickbeard/config.py index 819665df..507ddba1 100644 --- a/sickbeard/config.py +++ b/sickbeard/config.py @@ -847,20 +847,29 @@ class ConfigMigrator: sickbeard.CACHE_DIR = cache_default @staticmethod - def _migrate_v17(): + def add_ignore_words(wordlist): # 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(',') new_list = [] - for new_word in words_to_add: + 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 re.search(r'(?i)%s' % new_word, ignored): + if new_word in ignored: add_word = False if add_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']) diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py index 4971cc39..e42b0f57 100644 --- a/sickbeard/helpers.py +++ b/sickbeard/helpers.py @@ -20,9 +20,11 @@ from __future__ import print_function from __future__ import with_statement import base64 +import codecs import datetime import getpass import hashlib +import io import os import re import shutil @@ -360,7 +362,7 @@ def moveAndSymlinkFile(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 parents @@ -394,8 +396,9 @@ def make_dirs(path): ek.ek(os.mkdir, sofar) # use normpath to remove end separator, otherwise checks permissions against itself chmodAsParent(ek.ek(os.path.normpath, sofar)) - # do the library update for synoindex - notifiers.NotifierFactory().get('SYNOINDEX').addFolder(sofar) + if syno: + # do the library update for synoindex + notifiers.NotifierFactory().get('SYNOINDEX').addFolder(sofar) except (OSError, IOError) as e: logger.log(u'Failed creating %s : %s' % (sofar, ex(e)), logger.ERROR) return False @@ -1251,17 +1254,8 @@ def getURL(url, post_data=None, params=None, headers=None, timeout=30, session=N if savename: try: - with open(savename, 'wb') as fp: - for chunk in response.iter_content(chunk_size=1024): - 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) + write_file(savename, response, raw=True, raise_exceptions=raise_exceptions) + except (StandardError, Exception) as e: if raise_exceptions: raise e return @@ -1703,3 +1697,44 @@ def path_mapper(search, replace, subject): result = os.path.normpath(re.sub(delim, '/', result)) 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 diff --git a/sickbeard/metadata/generic.py b/sickbeard/metadata/generic.py index c4b3def6..660801e8 100644 --- a/sickbeard/metadata/generic.py +++ b/sickbeard/metadata/generic.py @@ -320,36 +320,31 @@ class GenericMetadata(): logger.DEBUG) nfo_file_path = self.get_show_file_path(show_obj) - try: - with ek.ek(open, nfo_file_path, 'r') as xmlFileObj: - show_xml = etree.ElementTree(file=xmlFileObj) + with ek.ek(open, nfo_file_path, 'r') as xmlFileObj: + show_xml = etree.ElementTree(file=xmlFileObj) - indexer = show_xml.find('indexer') - indexerid = show_xml.find('id') + indexer = show_xml.find('indexer') + indexerid = show_xml.find('id') - root = show_xml.getroot() - show_indexer = str(show_obj.indexer) - if None is not indexer: - indexer.text = show_indexer - else: - etree.SubElement(root, 'indexer').text = show_indexer + root = show_xml.getroot() + show_indexer = str(show_obj.indexer) + if None is not indexer: + indexer.text = show_indexer + else: + etree.SubElement(root, 'indexer').text = show_indexer - show_indexerid = str(show_obj.indexerid) - if None is not indexerid: - indexerid.text = show_indexerid - else: - etree.SubElement(root, 'id').text = show_indexerid + show_indexerid = str(show_obj.indexerid) + if None is not indexerid: + indexerid.text = show_indexerid + else: + etree.SubElement(root, 'id').text = show_indexerid - # Make it purdy - helpers.indentXML(root) + # Make it purdy + helpers.indentXML(root) - show_xml.write(nfo_file_path) - helpers.chmodAsParent(nfo_file_path) + helpers.write_file(nfo_file_path, show_xml, xmltree=True, utf8=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) + return True def create_fanart(self, show_obj): if self.fanart and show_obj and not self._has_fanart(show_obj): @@ -476,27 +471,10 @@ class GenericMetadata(): return False nfo_file_path = self.get_show_file_path(show_obj) - nfo_file_dir = ek.ek(os.path.dirname, nfo_file_path) - try: - 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 metadata file: %s' % nfo_file_path, logger.DEBUG) - logger.log(u"Writing show nfo file to " + nfo_file_path, logger.DEBUG) - - 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 + return helpers.write_file(nfo_file_path, data, xmltree=True, utf8=True) def write_ep_file(self, ep_obj): """ @@ -521,27 +499,10 @@ class GenericMetadata(): return False nfo_file_path = self.get_episode_file_path(ep_obj) - nfo_file_dir = ek.ek(os.path.dirname, nfo_file_path) - try: - 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 metadata file: %s' % nfo_file_path, logger.DEBUG) - logger.log(u"Writing episode nfo file to " + nfo_file_path, logger.DEBUG) - - 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 + return helpers.write_file(nfo_file_path, data, xmltree=True, utf8=True) def save_thumbnail(self, ep_obj): """ @@ -911,12 +872,12 @@ class GenericMetadata(): if not self._valid_show(indexer_show_obj, show_obj): 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, {}) for image_id in season_images.keys(): if season not in result: result[season] = {} - result[season][image_id] = season_images[image_id]['_bannerpath'] + result[season][image_id] = season_images[image_id]['bannerpath'] return result diff --git a/sickbeard/metadata/kodi.py b/sickbeard/metadata/kodi.py index 83e94d9d..e3ecaac9 100644 --- a/sickbeard/metadata/kodi.py +++ b/sickbeard/metadata/kodi.py @@ -187,24 +187,7 @@ class KODIMetadata(generic.GenericMetadata): if getattr(myShow, 'network', None) is not None: studio.text = myShow['network'] - if getattr(myShow, '_actors', None) is not None: - 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 + self.add_actor_element(myShow, etree, tv_node) # Make it purdy helpers.indentXML(tv_node) @@ -351,24 +334,7 @@ class KODIMetadata(generic.GenericMetadata): cur_actor_name = etree.SubElement(cur_actor, 'name') cur_actor_name.text = actor - if getattr(myEp, '_actors', None) is not None: - 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 + self.add_actor_element(myShow, etree, episode) # Make it purdy helpers.indentXML(rootNode) @@ -377,6 +343,26 @@ class KODIMetadata(generic.GenericMetadata): 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 metadata_class = KODIMetadata diff --git a/sickbeard/metadata/mede8er.py b/sickbeard/metadata/mede8er.py index 089b8156..01caf34f 100644 --- a/sickbeard/metadata/mede8er.py +++ b/sickbeard/metadata/mede8er.py @@ -199,14 +199,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata): Runtime.text = myShow['runtime'] cast = etree.SubElement(tv_node, "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() + self.add_actor_element(myShow, etree, cast) helpers.indentXML(rootNode) @@ -333,14 +326,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata): credits.text = credits_text cast = etree.SubElement(episode, "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() + self.add_actor_element(myShow, etree, cast) else: # append data from (if any) related episodes @@ -362,6 +348,17 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata): 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 metadata_class = Mede8erMetadata diff --git a/sickbeard/metadata/mediabrowser.py b/sickbeard/metadata/mediabrowser.py index b9dd7afb..529a412c 100644 --- a/sickbeard/metadata/mediabrowser.py +++ b/sickbeard/metadata/mediabrowser.py @@ -362,18 +362,20 @@ class MediaBrowserMetadata(generic.GenericMetadata): if getattr(myShow, 'network', None) is not None: Studio.text = myShow['network'] - Persons = etree.SubElement(tv_node, "Persons") - if getattr(myShow, 'actors', None) is not None: - for actor in myShow['_actors']: - cur_actor = etree.SubElement(Persons, "Person") - cur_actor_name = etree.SubElement(cur_actor, "Name") - cur_actor_name.text = actor['name'].strip() - cur_actor_type = etree.SubElement(cur_actor, "Type") - cur_actor_type.text = "Actor" - 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 + Persons = etree.SubElement(tv_node, 'Persons') + for actor in getattr(myShow, 'actors', []): + cur_actor = etree.SubElement(Persons, 'Person') + + cur_actor_name = etree.SubElement(cur_actor, 'Name') + cur_actor_name.text = actor['person']['name'] + + cur_actor_type = etree.SubElement(cur_actor, 'Type') + cur_actor_type.text = 'Actor' + + 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 helpers.indentXML(tv_node) diff --git a/sickbeard/metadata/tivo.py b/sickbeard/metadata/tivo.py index 516452f7..b0063491 100644 --- a/sickbeard/metadata/tivo.py +++ b/sickbeard/metadata/tivo.py @@ -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 # 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): 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. - if getattr(myShow, 'actors', None) is not None: - for actor in myShow["actors"].split('|'): - if actor: - data += ("vActor : " + actor + "\n") + for actor in getattr(myShow, 'actors', []): + data += ('vActor : %s\n' % 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']) # This is shown on both the Program screen and the Details screen. if getattr(myEp, 'rating', None) is not None: diff --git a/sickbeard/metadata/wdtv.py b/sickbeard/metadata/wdtv.py index 9fb498aa..34b51bf5 100644 --- a/sickbeard/metadata/wdtv.py +++ b/sickbeard/metadata/wdtv.py @@ -275,15 +275,16 @@ class WDTVMetadata(generic.GenericMetadata): if director_text is not None: director.text = director_text - if getattr(myShow, '_actors', None) is not None: - 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'] - 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 + for actor in getattr(myShow, 'actors', []): + cur_actor = etree.SubElement(episode, 'actor') + + cur_actor_name = etree.SubElement(cur_actor, 'name') + cur_actor_name.text = actor['person']['name'] + + 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 overview = etree.SubElement(episode, "overview") if curEpToWrite.description != None: diff --git a/sickbeard/metadata/xbmc_12plus.py b/sickbeard/metadata/xbmc_12plus.py index 28c86d4a..0b089971 100644 --- a/sickbeard/metadata/xbmc_12plus.py +++ b/sickbeard/metadata/xbmc_12plus.py @@ -187,24 +187,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata): if getattr(myShow, 'network', None) is not None: studio.text = myShow["network"] - if getattr(myShow, '_actors', None) is not None: - 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 + self.add_actor_element(myShow, etree, tv_node) # Make it purdy helpers.indentXML(tv_node) @@ -354,24 +337,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata): cur_actor_name = etree.SubElement(cur_actor, "name") cur_actor_name.text = actor - if getattr(myEp, '_actors', None) is not None: - 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 + self.add_actor_element(myShow, etree, episode) # Make it purdy helpers.indentXML(rootNode) @@ -380,6 +346,26 @@ class XBMC_12PlusMetadata(generic.GenericMetadata): 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 metadata_class = XBMC_12PlusMetadata