def _ep_data(self, ep_obj): # type: (sickbeard.tv.TVEpisode) -> Optional[Union[bool, etree.Element]] """ Creates an elementTree XML structure for an XBMC-style episode.nfo and returns the resulting data object. show_obj: a TVEpisode instance to create the NFO for """ ep_obj_list_to_write = [ep_obj] + ep_obj.related_ep_obj show_lang = ep_obj.show_obj.lang tvinfo_config = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).api_params.copy() tvinfo_config['actors'] = True if show_lang and not 'en' == show_lang: tvinfo_config['language'] = show_lang if 0 != ep_obj.show_obj.dvdorder: tvinfo_config['dvdorder'] = True try: t = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).setup(**tvinfo_config) show_info = t[ep_obj.show_obj.prodid] except BaseTVinfoShownotfound as e: raise exceptions_helper.ShowNotFoundException(ex(e)) except BaseTVinfoError as e: logger.log( 'Unable to connect to %s while creating meta files - skipping - %s' % (sickbeard.TVInfoAPI(ep_obj.show_obj.tvid).name, ex(e)), logger.ERROR) return if not self._valid_show(show_info, ep_obj.show_obj): return if 1 < len(ep_obj_list_to_write): rootNode = etree.Element('xbmcmultiepisode') else: rootNode = etree.Element('episodedetails') # write an NFO containing info for all matching episodes for cur_ep_obj in ep_obj_list_to_write: try: ep_info = show_info[cur_ep_obj.season][cur_ep_obj.episode] except (BaseTVinfoEpisodenotfound, BaseTVinfoSeasonnotfound) as e: logger.log( 'Unable to find episode %sx%s on %s.. has it been removed? Should I delete from db?' % (cur_ep_obj.season, cur_ep_obj.episode, sickbeard.TVInfoAPI(ep_obj.show_obj.tvid).name)) return None except (BaseException, Exception): logger.log( u'Not generating nfo because failed to fetched tv info data at this time', logger.DEBUG) return None if None is getattr(ep_info, 'firstaired', None): ep_info['firstaired'] = str(datetime.date.fromordinal(1)) if None is getattr(ep_info, 'episodename', None): logger.log(u'Not generating nfo because the ep has no title', logger.DEBUG) return None logger.log( u'Creating metadata for episode ' + str(ep_obj.season) + 'x' + str(ep_obj.episode), logger.DEBUG) if 1 < len(ep_obj_list_to_write): episode = etree.SubElement(rootNode, 'episodedetails') else: episode = rootNode title = etree.SubElement(episode, 'title') if None is not cur_ep_obj.name: title.text = '%s' % cur_ep_obj.name showtitle = etree.SubElement(episode, 'showtitle') if None is not cur_ep_obj.show_obj.name: showtitle.text = '%s' % cur_ep_obj.show_obj.name season = etree.SubElement(episode, 'season') season.text = str(cur_ep_obj.season) episodenum = etree.SubElement(episode, 'episode') episodenum.text = str(cur_ep_obj.episode) uniqueid = etree.SubElement(episode, 'uniqueid') uniqueid.text = str(cur_ep_obj.epid) aired = etree.SubElement(episode, 'aired') if cur_ep_obj.airdate != datetime.date.fromordinal(1): aired.text = str(cur_ep_obj.airdate) else: aired.text = '' plot = etree.SubElement(episode, 'plot') if None is not cur_ep_obj.description: plot.text = '%s' % cur_ep_obj.description runtime = etree.SubElement(episode, 'runtime') if 0 != cur_ep_obj.season: if None is not getattr(show_info, 'runtime', None): runtime.text = '%s' % show_info['runtime'] displayseason = etree.SubElement(episode, 'displayseason') if None is not getattr(ep_info, 'airsbefore_season', None): displayseason_text = ep_info['airsbefore_season'] if None is not displayseason_text: displayseason.text = '%s' % displayseason_text displayepisode = etree.SubElement(episode, 'displayepisode') if None is not getattr(ep_info, 'airsbefore_episode', None): displayepisode_text = ep_info['airsbefore_episode'] if None is not displayepisode_text: displayepisode.text = '%s' % displayepisode_text thumb = etree.SubElement(episode, 'thumb') thumb_text = getattr(ep_info, 'filename', None) if None is not thumb_text: thumb.text = '%s' % thumb_text watched = etree.SubElement(episode, 'watched') watched.text = 'false' credits = etree.SubElement(episode, 'credits') credits_text = getattr(ep_info, 'writer', None) if None is not credits_text: credits.text = '%s' % credits_text director = etree.SubElement(episode, 'director') director_text = getattr(ep_info, 'director', None) if None is not director_text: director.text = '%s' % director_text rating = etree.SubElement(episode, 'rating') rating_text = getattr(ep_info, 'rating', None) if None is not rating_text: rating.text = '%s' % rating_text gueststar_text = getattr(ep_info, 'gueststars', None) if isinstance(gueststar_text, string_types): for actor in (x.strip() for x in gueststar_text.split('|') if x.strip()): cur_actor = etree.SubElement(episode, 'actor') cur_actor_name = etree.SubElement(cur_actor, 'name') cur_actor_name.text = '%s' % actor self.add_actor_element(show_info, etree, episode) # Make it purdy sg_helpers.indent_xml(rootNode) data = etree.ElementTree(rootNode) return data
def _ep_data(self, ep_obj): # type: (sickbeard.tv.TVEpisode) -> Optional[Union[bool, etree.Element]] """ Creates an elementTree XML structure for a WDTV style episode.xml and returns the resulting data object. ep_obj: a TVShow instance to create the NFO for """ ep_obj_list_to_write = [ep_obj] + ep_obj.related_ep_obj show_lang = ep_obj.show_obj.lang try: tvinfo_config = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).api_params.copy() tvinfo_config['actors'] = True if show_lang and not 'en' == show_lang: tvinfo_config['language'] = show_lang if 0 != ep_obj.show_obj.dvdorder: tvinfo_config['dvdorder'] = True t = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).setup(**tvinfo_config) show_info = t[ep_obj.show_obj.prodid] except BaseTVinfoShownotfound as e: raise exceptions_helper.ShowNotFoundException(ex(e)) except BaseTVinfoError as e: logger.log( "Unable to connect to %s while creating meta files - skipping - %s" % (sickbeard.TVInfoAPI(ep_obj.show_obj.tvid).name, ex(e)), logger.ERROR) return False if not self._valid_show(show_info, ep_obj.show_obj): return rootNode = etree.Element("details") data = None # write an WDTV XML containing info for all matching episodes for cur_ep_obj in ep_obj_list_to_write: try: ep_info = show_info[cur_ep_obj.season][cur_ep_obj.episode] except (BaseException, Exception): logger.log( "Unable to find episode %sx%s on %s... has it been removed? Should I delete from db?" % (cur_ep_obj.season, cur_ep_obj.episode, sickbeard.TVInfoAPI(ep_obj.show_obj.tvid).name)) return None if None is getattr(ep_info, 'firstaired', None) and 0 == ep_obj.season: ep_info["firstaired"] = str(datetime.date.fromordinal(1)) if None is getattr(ep_info, 'episodename', None) or None is getattr( ep_info, 'firstaired', None): return None if 1 < len(ep_obj_list_to_write): episode = etree.SubElement(rootNode, "details") else: episode = rootNode episodeID = etree.SubElement(episode, "id") episodeID.text = str(cur_ep_obj.epid) title = etree.SubElement(episode, "title") title.text = '%s' % ep_obj.pretty_name() seriesName = etree.SubElement(episode, "series_name") if None is not getattr(show_info, 'seriesname', None): seriesName.text = '%s' % show_info["seriesname"] episodeName = etree.SubElement(episode, "episode_name") if None is not cur_ep_obj.name: episodeName.text = '%s' % cur_ep_obj.name seasonNumber = etree.SubElement(episode, "season_number") seasonNumber.text = str(cur_ep_obj.season) episodeNum = etree.SubElement(episode, "episode_number") episodeNum.text = str(cur_ep_obj.episode) firstAired = etree.SubElement(episode, "firstaired") if cur_ep_obj.airdate != datetime.date.fromordinal(1): firstAired.text = str(cur_ep_obj.airdate) year = etree.SubElement(episode, "year") year_text = self.get_show_year(ep_obj.show_obj, show_info) if year_text: year.text = '%s' % year_text runtime = etree.SubElement(episode, "runtime") if 0 != cur_ep_obj.season: if None is not getattr(show_info, 'runtime', None): runtime.text = '%s' % show_info["runtime"] genre = etree.SubElement(episode, "genre") if None is not getattr(show_info, 'genre', None): genre.text = " / ".join( [x for x in show_info["genre"].split('|') if x]) director = etree.SubElement(episode, "director") director_text = getattr(ep_info, 'director', None) if None is not director_text: director.text = '%s' % director_text for actor in getattr(show_info, 'actors', []): cur_actor = etree.SubElement(episode, 'actor') cur_actor_name = etree.SubElement(cur_actor, 'name') cur_actor_name.text = '%s' % actor['person']['name'] cur_actor_role = etree.SubElement(cur_actor, 'role') cur_actor_role_text = '%s' % actor['character']['name'] if cur_actor_role_text: cur_actor_role.text = '%s' % cur_actor_role_text overview = etree.SubElement(episode, "overview") if None is not cur_ep_obj.description: overview.text = '%s' % cur_ep_obj.description # Make it purdy sg_helpers.indent_xml(rootNode) data = etree.ElementTree(rootNode) return data
def _ep_data(self, ep_obj): # type: (sickbeard.tv.TVEpisode) -> Optional[Union[bool, etree.Element]] """ Creates an elementTree XML structure for a MediaBrowser style episode.xml and returns the resulting data object. show_obj: a TVShow instance to create the NFO for """ ep_obj_list_to_write = [ep_obj] + ep_obj.related_ep_obj show_lang = ep_obj.show_obj.lang try: # There's gotta be a better way of doing this but we don't wanna # change the language value elsewhere tvinfo_config = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).api_params.copy() if show_lang and not 'en' == show_lang: tvinfo_config['language'] = show_lang if 0 != ep_obj.show_obj.dvdorder: tvinfo_config['dvdorder'] = True t = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).setup(**tvinfo_config) show_info = t[ep_obj.show_obj.prodid] except BaseTVinfoShownotfound as e: raise exceptions_helper.ShowNotFoundException(ex(e)) except BaseTVinfoError as e: logger.log( 'Unable to connect to %s while creating meta files - skipping - %s' % (sickbeard.TVInfoAPI(ep_obj.show_obj.tvid).name, ex(e)), logger.ERROR) return False if not self._valid_show(show_info, ep_obj.show_obj): return rootNode = etree.Element('details') movie = etree.SubElement(rootNode, 'movie') movie.attrib['isExtra'] = 'false' movie.attrib['isSet'] = 'false' movie.attrib['isTV'] = 'true' # write an MediaBrowser XML containing info for all matching episodes for cur_ep_obj in ep_obj_list_to_write: try: ep_info = show_info[cur_ep_obj.season][cur_ep_obj.episode] except (BaseException, Exception): logger.log( u'Unable to find episode %sx%s on tvdb... has it been removed? Should I delete from db?' % (cur_ep_obj.season, cur_ep_obj.episode)) return None if cur_ep_obj == ep_obj: # root (or single) episode # default to today's date for specials if firstaired is not set if None is ep_info['firstaired'] and 0 == ep_obj.season: ep_info['firstaired'] = str(datetime.date.fromordinal(1)) if None is ep_info['episodename'] or None is ep_info[ 'firstaired']: return None episode = movie EpisodeName = etree.SubElement(episode, 'title') if None is not cur_ep_obj.name: EpisodeName.text = '%s' % cur_ep_obj.name else: EpisodeName.text = '' SeasonNumber = etree.SubElement(episode, 'season') SeasonNumber.text = str(cur_ep_obj.season) EpisodeNumber = etree.SubElement(episode, 'episode') EpisodeNumber.text = str(ep_obj.episode) year = etree.SubElement(episode, 'year') year_text = self.get_show_year(ep_obj.show_obj, show_info) if year_text: year.text = '%s' % year_text plot = etree.SubElement(episode, 'plot') if None is not show_info['overview']: plot.text = '%s' % show_info['overview'] Overview = etree.SubElement(episode, 'episodeplot') if None is not cur_ep_obj.description: Overview.text = '%s' % cur_ep_obj.description else: Overview.text = '' mpaa = etree.SubElement(episode, 'mpaa') if None is not show_info['contentrating']: mpaa.text = '%s' % show_info['contentrating'] if not ep_obj.related_ep_obj: if None is not ep_info['rating']: try: rating = int((float(ep_info['rating']) * 10)) except ValueError: rating = 0 Rating = etree.SubElement(episode, 'rating') rating_text = str(rating) if None is not rating_text: Rating.text = '%s' % rating_text director = etree.SubElement(episode, 'director') director_text = ep_info['director'] if None is not director_text: director.text = '%s' % director_text credits = etree.SubElement(episode, 'credits') credits_text = ep_info['writer'] if None is not credits_text: credits.text = '%s' % credits_text cast = etree.SubElement(episode, 'cast') self.add_actor_element(show_info, etree, cast) else: # append data from (if any) related episodes if cur_ep_obj.name: if not EpisodeName.text: EpisodeName.text = '%s' % cur_ep_obj.name else: EpisodeName.text = '%s, %s' % (EpisodeName.text, cur_ep_obj.name) if cur_ep_obj.description: if not Overview.text: Overview.text = '%s' % cur_ep_obj.description else: Overview.text = '%s\r%s' % (Overview.text, cur_ep_obj.description) sg_helpers.indent_xml(rootNode) data = etree.ElementTree(rootNode) return data
def _ep_data(self, ep_obj): # type: (sickbeard.tv.TVEpisode) -> Optional[Union[bool, etree.Element]] """ Creates an elementTree XML structure for a MediaBrowser style episode.xml and returns the resulting data object. show_obj: a TVShow instance to create the NFO for """ ep_obj_list_to_write = [ep_obj] + ep_obj.related_ep_obj persons_dict = {'Director': [], 'GuestStar': [], 'Writer': []} show_lang = ep_obj.show_obj.lang try: tvinfo_config = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).api_params.copy() tvinfo_config['actors'] = True if show_lang and not 'en' == show_lang: tvinfo_config['language'] = show_lang if 0 != ep_obj.show_obj.dvdorder: tvinfo_config['dvdorder'] = True t = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).setup(**tvinfo_config) show_info = t[ep_obj.show_obj.prodid] except Exception as e: if check_exception_type(e, ExceptionTuples.tvinfo_shownotfound): raise exceptions_helper.ShowNotFoundException(ex(e)) elif check_exception_type(e, ExceptionTuples.tvinfo_error): logger.log( "Unable to connect to %s while creating meta files - skipping - %s" % (sickbeard.TVInfoAPI(ep_obj.show_obj.tvid).name, ex(e)), logger.ERROR) return False else: raise e if not self._valid_show(show_info, ep_obj.show_obj): return rootNode = etree.Element("Item") # write an MediaBrowser XML containing info for all matching episodes for cur_ep_obj in ep_obj_list_to_write: try: ep_info = show_info[cur_ep_obj.season][cur_ep_obj.episode] except (BaseException, Exception): logger.log( "Unable to find episode %sx%s on %s.. has it been removed? Should I delete from db?" % (cur_ep_obj.season, cur_ep_obj.episode, sickbeard.TVInfoAPI(ep_obj.show_obj.tvid).name)) return None if cur_ep_obj == ep_obj: # root (or single) episode # default to today's date for specials if firstaired is not set if None is getattr(ep_info, 'firstaired', None) and 0 == ep_obj.season: ep_info['firstaired'] = str(datetime.date.fromordinal(1)) if None is getattr(ep_info, 'episodename', None) or None is getattr( ep_info, 'firstaired', None): return None episode = rootNode EpisodeName = etree.SubElement(episode, "EpisodeName") if None is not cur_ep_obj.name: EpisodeName.text = '%s' % cur_ep_obj.name else: EpisodeName.text = "" EpisodeNumber = etree.SubElement(episode, "EpisodeNumber") EpisodeNumber.text = str(ep_obj.episode) if ep_obj.related_ep_obj: EpisodeNumberEnd = etree.SubElement( episode, "EpisodeNumberEnd") EpisodeNumberEnd.text = str(cur_ep_obj.episode) SeasonNumber = etree.SubElement(episode, "SeasonNumber") SeasonNumber.text = str(cur_ep_obj.season) if not ep_obj.related_ep_obj: absolute_number = etree.SubElement(episode, "absolute_number") if None is not getattr(ep_info, 'absolute_number', None): absolute_number.text = '%s' % ep_info['absolute_number'] FirstAired = etree.SubElement(episode, "FirstAired") if cur_ep_obj.airdate != datetime.date.fromordinal(1): FirstAired.text = str(cur_ep_obj.airdate) else: FirstAired.text = "" MetadataType = etree.SubElement(episode, "Type") MetadataType.text = "Episode" Overview = etree.SubElement(episode, "Overview") if None is not cur_ep_obj.description: Overview.text = '%s' % cur_ep_obj.description else: Overview.text = "" if not ep_obj.related_ep_obj: Rating = etree.SubElement(episode, "Rating") if None is not getattr(ep_info, 'rating', None): Rating.text = '%s' % ep_info['rating'] IMDB_ID = etree.SubElement(episode, "IMDB_ID") IMDB = etree.SubElement(episode, "IMDB") IMDbId = etree.SubElement(episode, "IMDbId") if None is not getattr(show_info, 'imdb_id', None): IMDB_ID.text = '%s' % show_info['imdb_id'] IMDB.text = '%s' % show_info['imdb_id'] IMDbId.text = '%s' % show_info['imdb_id'] prodid = etree.SubElement(episode, "id") prodid.text = str(cur_ep_obj.show_obj.prodid) tvid = etree.SubElement(episode, "indexer") tvid.text = str(cur_ep_obj.show_obj.tvid) Persons = etree.SubElement(episode, "Persons") Language = etree.SubElement(episode, "Language") try: Language.text = '%s' % cur_ep_obj.show_obj.lang except (BaseException, Exception): Language.text = 'en' # tvrage api doesn't provide language so we must assume a value here thumb = etree.SubElement(episode, "filename") # TODO: See what this is needed for.. if its still needed # just write this to the NFO regardless of whether it actually exists or not # note: renaming files after nfo generation will break this, tough luck thumb_text = self.get_episode_thumb_path(ep_obj) if thumb_text: thumb.text = '%s' % thumb_text else: # append data from (if any) related episodes EpisodeNumberEnd.text = str(cur_ep_obj.episode) if cur_ep_obj.name: if not EpisodeName.text: EpisodeName.text = '%s' % cur_ep_obj.name else: EpisodeName.text = '%s, %s' % (EpisodeName.text, cur_ep_obj.name) if cur_ep_obj.description: if not Overview.text: Overview.text = '%s' % cur_ep_obj.description else: Overview.text = '%s\r%s' % (Overview.text, cur_ep_obj.description) # collect all directors, guest stars and writers if None is not getattr(ep_info, 'director', None): persons_dict['Director'] += [ x.strip() for x in ep_info['director'].split('|') if x ] if None is not getattr(ep_info, 'gueststars', None): persons_dict['GuestStar'] += [ x.strip() for x in ep_info['gueststars'].split('|') if x ] if None is not getattr(ep_info, 'writer', None): persons_dict['Writer'] += [ x.strip() for x in ep_info['writer'].split('|') if x ] # fill in Persons section with collected directors, guest starts and writers for person_type, names in iteritems(persons_dict): # remove doubles names = list(set(names)) for cur_name in names: Person = etree.SubElement(Persons, "Person") cur_person_name = etree.SubElement(Person, "Name") cur_person_name.text = '%s' % cur_name cur_person_type = etree.SubElement(Person, "Type") cur_person_type.text = '%s' % person_type helpers.indent_xml(rootNode) data = etree.ElementTree(rootNode) return data
def _ep_data(self, ep_obj): # type: (sickbeard.tv.TVEpisode) -> Optional[Union[bool, AnyStr]] """ Creates a key value structure for a Tivo episode metadata file and returns the resulting data object. ep_obj: a TVEpisode instance to create the metadata file for. Lookup the show in http://thetvdb.com/ using the python library: https://github.com/dbr/indexer_api/ The results are saved in the object show_info. The key values for the tivo metadata file are from: http://pytivo.sourceforge.net/wiki/index.php/Metadata """ data = '' ep_obj_list_to_write = [ep_obj] + ep_obj.related_ep_obj show_lang = ep_obj.show_obj.lang try: tvinfo_config = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).api_params.copy() tvinfo_config['actors'] = True if show_lang and not 'en' == show_lang: tvinfo_config['language'] = show_lang if 0 != ep_obj.show_obj.dvdorder: tvinfo_config['dvdorder'] = True t = sickbeard.TVInfoAPI( ep_obj.show_obj.tvid).setup(**tvinfo_config) show_info = t[ep_obj.show_obj.prodid] except BaseTVinfoShownotfound as e: raise exceptions_helper.ShowNotFoundException(ex(e)) except BaseTVinfoError as e: logger.log( "Unable to connect to %s while creating meta files - skipping - %s" % (sickbeard.TVInfoAPI(ep_obj.show_obj.tvid).name, ex(e)), logger.ERROR) return False if not self._valid_show(show_info, ep_obj.show_obj): return for cur_ep_obj in ep_obj_list_to_write: try: ep_info = show_info[cur_ep_obj.season][cur_ep_obj.episode] except (BaseException, Exception): logger.log( "Unable to find episode %sx%s on %s... has it been removed? Should I delete from db?" % (cur_ep_obj.season, cur_ep_obj.episode, sickbeard.TVInfoAPI(ep_obj.show_obj.tvid).name)) return None if None is getattr(ep_info, 'firstaired', None) and 0 == ep_obj.season: ep_info["firstaired"] = str(datetime.date.fromordinal(1)) if None is getattr(ep_info, 'episodename', None) or None is getattr( ep_info, 'firstaired', None): return None if None is not getattr(show_info, 'seriesname', None): data += ("title : " + show_info["seriesname"] + "\n") data += ("seriesTitle : " + show_info["seriesname"] + "\n") data += ("episodeTitle : " + cur_ep_obj._format_pattern('%Sx%0E %EN') + "\n") # This should be entered for episodic shows and omitted for movies. The standard tivo format is to enter # the season number followed by the episode number for that season. For example, enter 201 for season 2 # episode 01. # This only shows up if you go into the Details from the Program screen. # This seems to disappear once the video is transferred to TiVo. # NOTE: May not be correct format, missing season, but based on description from wiki leaving as is. data += ("episodeNumber : " + str(cur_ep_obj.episode) + "\n") # Must be entered as true or false. If true, the year from originalAirDate will be shown in parentheses # after the episode's title and before the description on the Program screen. # FIXME: Hardcode isEpisode to true for now, not sure how to handle movies data += "isEpisode : true\n" # Write the synopsis of the video here # Micrsoft Word's smartquotes can die in a fire. sanitizedDescription = cur_ep_obj.description # Replace double curly quotes sanitizedDescription = sanitizedDescription.replace( u"\u201c", "\"").replace(u"\u201d", "\"") # Replace single curly quotes sanitizedDescription = sanitizedDescription.replace( u"\u2018", "'").replace(u"\u2019", "'").replace(u"\u02BC", "'") data += ("description : " + sanitizedDescription + "\n") # Usually starts with "SH" and followed by 6-8 digits. # Tivo uses zap2it for thier data, so the series id is the zap2it_id. if None is not getattr(show_info, 'zap2it_id', None): data += ("seriesId : " + show_info["zap2it_id"] + "\n") # This is the call sign of the channel the episode was recorded from. if None is not getattr(show_info, 'network', None): data += ("callsign : " + show_info["network"] + "\n") # 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 if cur_ep_obj.airdate != datetime.date.fromordinal(1): data += ("originalAirDate : " + str(cur_ep_obj.airdate) + "T00:00:00Z\n") # This shows up at the beginning of the description on the Program screen and on the Details screen. for actor in getattr(show_info, '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 None is not getattr(ep_info, 'rating', None): try: rating = float(ep_info['rating']) except ValueError: rating = 0.0 # convert 10 to 4 star rating. 4 * rating / 10 # only whole numbers or half numbers work. multiply by 2, round, divide by 2.0 rating = round(8 * rating / 10) / 2.0 data += ("starRating : " + str(rating) + "\n") # This is shown on both the Program screen and the Details screen. # It uses the standard TV rating system of: TV-Y7, TV-Y, TV-G, TV-PG, TV-14, TV-MA and TV-NR. if None is not getattr(show_info, 'contentrating', None): data += ("tvRating : " + str(show_info["contentrating"]) + "\n") # This field can be repeated as many times as necessary or omitted completely. if ep_obj.show_obj.genre: for genre in ep_obj.show_obj.genre.split('|'): if genre: data += ("vProgramGenre : " + str(genre) + "\n") # NOTE: The following are metadata keywords are not used # displayMajorNumber # showingBits # displayMinorNumber # colorCode # vSeriesGenre # vGuestStar, vDirector, vExecProducer, vProducer, vWriter, vHost, vChoreographer # partCount # partIndex return data