def update_show_indexer_metadata(self, show_obj): if self.show_metadata and show_obj and self._has_show_metadata( show_obj): logger.debug("Metadata provider " + self.name + " updating show indexer info metadata file for " + show_obj.name) nfo_file_path = self.get_show_file_path(show_obj) try: with open(nfo_file_path, 'rb') as xmlFileObj: showXML = ElementTree.ElementTree(file=xmlFileObj) indexerid = showXML.find('id') root = showXML.getroot() if indexerid is not None: if indexerid.text == str(show_obj.indexerid): return True indexerid.text = str(show_obj.indexerid) else: ElementTree.SubElement(root, "id").text = str(show_obj.indexerid) # Make it purdy helpers.indentXML(root) showXML.write(nfo_file_path, encoding='UTF-8') helpers.chmodAsParent(nfo_file_path) return True except IOError as e: logger.error("Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + str(e))
def update_episode_metadata(self, ep_obj): if self.episode_metadata and ep_obj and self._has_episode_metadata( ep_obj): logger.debug("Metadata provider " + self.name + " updating episode indexer info metadata file for " + ep_obj.pretty_name()) nfo_file_path = self.get_episode_file_path(ep_obj) attribute_map = { 'title': 'name', 'aired': 'airdate', 'season': 'season', 'episode': 'episode', 'showtitle': 'show.name', 'runtime': 'show.runtime', 'plot': 'description' } try: with open(nfo_file_path, 'rb') as xmlFileObj: episodeXML = ElementTree.ElementTree(file=xmlFileObj) changed = False for attribute in attribute_map: try: if not hasattr(ep_obj, attribute_map[attribute]): continue node = episodeXML.find(attribute) if node is None or node.text == str( getattr(ep_obj, attribute_map[attribute])): continue node.text = str( getattr(ep_obj, attribute_map[attribute])) changed = True except AttributeError: pass if not changed: return True root = episodeXML.getroot() # Make it purdy helpers.indentXML(root) episodeXML.write(nfo_file_path, encoding='UTF-8') helpers.chmodAsParent(nfo_file_path) return True except IOError as error: logger.warning( "Unable to write file to {} - are you sure the folder is writable? {}" .format(nfo_file_path, str(error))) except ElementTree.ParseError as error: logger.warning( "Error parsing existing nfo file at {} - {}".format( nfo_file_path, str(error)))
def _show_data(self, show_obj): """ Creates an elementTree XML structure for a MediaBrowser-style series.xml returns the resulting data object. show_obj: a TVShow instance to create the NFO for """ rootNode = ElementTree.Element("details") tv_node = ElementTree.SubElement(rootNode, "movie") tv_node.attrib["isExtra"] = "false" tv_node.attrib["isSet"] = "false" tv_node.attrib["isTV"] = "true" myShow = sickchill.indexer.series(show_obj) if not myShow: logger.info( "Unable to find show with id {} on {}, skipping it".format( show_obj.indexerid, show_obj.idxr.name)) return False # check for title and id if not (getattr(myShow, 'seriesName', None) and getattr(myShow, 'id', None)): logger.info( "Incomplete info for show with id {} on {}, skipping it". format(show_obj.indexerid, show_obj.idxr.name)) return False SeriesName = ElementTree.SubElement(tv_node, "title") SeriesName.text = myShow.seriesName if getattr(myShow, "genre", None): Genres = ElementTree.SubElement(tv_node, "genres") for genre in myShow.genre: if genre and genre.strip(): cur_genre = ElementTree.SubElement(Genres, "Genre") cur_genre.text = genre.strip() if getattr(myShow, 'firstAired', None): FirstAired = ElementTree.SubElement(tv_node, "premiered") FirstAired.text = myShow.firstAired if getattr(myShow, "firstAired", None): try: year_text = str( datetime.datetime.strptime(myShow.firstAired, dateFormat).year) if year_text: year = ElementTree.SubElement(tv_node, "year") year.text = year_text except Exception: pass if getattr(myShow, 'overview', None): plot = ElementTree.SubElement(tv_node, "plot") plot.text = myShow.overview if getattr(myShow, 'rating', None): try: rating = int(float(myShow.siteRating) * 10) except ValueError: rating = 0 if rating: Rating = ElementTree.SubElement(tv_node, "rating") Rating.text = str(rating) if getattr(myShow, 'status', None): Status = ElementTree.SubElement(tv_node, "status") Status.text = myShow.status if getattr(myShow, "contentRating", None): mpaa = ElementTree.SubElement(tv_node, "mpaa") mpaa.text = myShow.rating if getattr(myShow, 'imdb_id', None): imdb_id = ElementTree.SubElement(tv_node, "id") imdb_id.attrib["moviedb"] = "imdb" imdb_id.text = myShow.imdbId if getattr(myShow, 'id', None): indexerid = ElementTree.SubElement(tv_node, "indexerid") indexerid.text = str(myShow.id) if getattr(myShow, 'runtime', None): Runtime = ElementTree.SubElement(tv_node, "runtime") Runtime.text = myShow.runtime actors = show_obj.idxr.actors(myShow) if actors: cast = ElementTree.SubElement(tv_node, "cast") for actor in actors: if 'name' in actor and actor['name'].strip(): cur_actor = ElementTree.SubElement(cast, "actor") cur_actor.text = actor['name'].strip() helpers.indentXML(rootNode) data = ElementTree.ElementTree(rootNode) return data
def _ep_data(self, ep_obj): """ 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 """ eps_to_write = [ep_obj] + ep_obj.relatedEps myShow = ep_obj.idxr.series_from_episode(ep_obj) if not myShow: logger.info( "Unable to connect to {} while creating meta files - skipping". format(ep_obj.idxr.name)) return False rootNode = ElementTree.Element("details") movie = ElementTree.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 curEpToWrite in eps_to_write: myEp = curEpToWrite.idxr.episode(curEpToWrite) if not myEp: logger.info( "Metadata writer is unable to find episode {0:d}x{1:d} of {2} on {3}..." "has it been removed? Should I delete from db?".format( curEpToWrite.season, curEpToWrite.episode, curEpToWrite.show.name, ep_obj.idxr.name)) return None if curEpToWrite == ep_obj: # root (or single) episode if ep_obj.airdate != datetime.date.min and not myEp.get( 'firstAired'): myEp['firstAired'] = str(ep_obj.airdate) if not (myEp.get('episodeName') and myEp.get('firstAired')): return None episode = movie if curEpToWrite.name: EpisodeName = ElementTree.SubElement(episode, "title") EpisodeName.text = curEpToWrite.name SeasonNumber = ElementTree.SubElement(episode, "season") SeasonNumber.text = str(curEpToWrite.season) EpisodeNumber = ElementTree.SubElement(episode, "episode") EpisodeNumber.text = str(curEpToWrite.episode) if getattr(myShow, "firstAired", None): try: year_text = str( datetime.datetime.strptime(myShow.firstAired, dateFormat).year) if year_text: year = ElementTree.SubElement(episode, "year") year.text = year_text except Exception: pass if getattr(myShow, "overview", None): plot = ElementTree.SubElement(episode, "plot") plot.text = myShow.overview if curEpToWrite.description: Overview = ElementTree.SubElement(episode, "episodeplot") Overview.text = curEpToWrite.description if getattr(myShow, 'contentRating', None): mpaa = ElementTree.SubElement(episode, "mpaa") mpaa.text = myShow.rating if not ep_obj.relatedEps and myEp.get("rating"): try: rating = int((float(myEp.siteRating) * 10)) except ValueError: rating = 0 if rating: Rating = ElementTree.SubElement(episode, "rating") Rating.text = str(rating) if myEp.get('directors') and isinstance( myEp['directors'], list): for director in myEp['directors']: cur_director = ElementTree.SubElement( episode, "director") cur_director.text = director if myEp.get('writers') and isinstance(myEp['writers'], list): for writer in myEp['writers']: cur_writer = ElementTree.SubElement(episode, "credits") cur_writer.text = writer if myEp.get('guestStars') and isinstance( myEp['guestStars'], list): cast = ElementTree.SubElement(episode, "cast") for actor in myEp['guestStars']: cur_actor = ElementTree.SubElement(cast, "actor") cur_actor.text = actor else: # append data from (if any) related episodes if curEpToWrite.name: if not EpisodeName.text: EpisodeName.text = curEpToWrite.name else: EpisodeName.text = EpisodeName.text + ", " + curEpToWrite.name if curEpToWrite.description: if not Overview.text: Overview.text = curEpToWrite.description else: Overview.text = Overview.text + "\r" + curEpToWrite.description helpers.indentXML(rootNode) data = ElementTree.ElementTree(rootNode) return data
def _ep_data(self, ep_obj): """ 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 """ eps_to_write = [ep_obj] + ep_obj.relatedEps persons_dict = { 'Director': [], 'GuestStar': [], 'Writer': [] } myShow = ep_obj.idxr.series_from_episode(ep_obj) if not myShow: logger.info("Unable to connect to {} while creating meta files - skipping".format(ep_obj.idxr.name)) return False rootNode = ElementTree.Element("Item") # write an MediaBrowser XML containing info for all matching episodes for curEpToWrite in eps_to_write: myEp = curEpToWrite.idxr.episode(curEpToWrite) if not myEp: continue if curEpToWrite == ep_obj: # root (or single) episode # default to today's date for specials if firstAired is not set if ep_obj.airdate != datetime.date.min and myEp.get('firstAired'): myEp['firstAired'] = str(ep_obj.airdate) if ep_obj.season == 0 and not myEp.get('firstAired'): if ep_obj.show and ep_obj.show.startyear: myEp['firstAired'] = str(datetime.date.min.replace(year=ep_obj.show.startyear)) else: myEp['firstAired'] = str(datetime.date.today()) if not (myEp.get('episodeName') and myEp.get('firstAired')): return None episode = rootNode if curEpToWrite.name: EpisodeName = ElementTree.SubElement(episode, "EpisodeName") EpisodeName.text = curEpToWrite.name EpisodeNumber = ElementTree.SubElement(episode, "EpisodeNumber") EpisodeNumber.text = str(ep_obj.episode) if ep_obj.relatedEps: try: max_episode = max(e.episode for e in ep_obj.relatedEps if e) except (AttributeError, TypeError): max_episode = curEpToWrite.episode EpisodeNumberEnd = ElementTree.SubElement(episode, "EpisodeNumberEnd") EpisodeNumberEnd.text = str(max_episode) SeasonNumber = ElementTree.SubElement(episode, "SeasonNumber") SeasonNumber.text = str(curEpToWrite.season) if myEp.get('absoluteNumber') and not ep_obj.relatedEps: absolute_number = ElementTree.SubElement(episode, "absolute_number") absolute_number.text = str(myEp['absoluteNumber']) if curEpToWrite.airdate != datetime.date.min: FirstAired = ElementTree.SubElement(episode, "FirstAired") FirstAired.text = str(curEpToWrite.airdate) MetadataType = ElementTree.SubElement(episode, "Type") MetadataType.text = "Episode" if curEpToWrite.description: Overview = ElementTree.SubElement(episode, "Overview") Overview.text = curEpToWrite.description elif myEp.get("overview"): Overview = ElementTree.SubElement(episode, "Overview") Overview.text = myEp["overview"] if not ep_obj.relatedEps: if myEp.get('rating'): Rating = ElementTree.SubElement(episode, "Rating") Rating.text = myEp['siteRating'] if myEp.get('imdbId'): IMDB_ID = ElementTree.SubElement(episode, "IMDB_ID") IMDB_ID.text = myEp['imdbId'] IMDB = ElementTree.SubElement(episode, "IMDB") IMDB.text = myEp['imdbId'] IMDbId = ElementTree.SubElement(episode, "IMDbId") IMDbId.text = myEp['imdbId'] if myEp.get('id'): indexerid = ElementTree.SubElement(episode, "id") indexerid.text = str(myEp['id']) Persons = ElementTree.SubElement(episode, "Persons") for actor in ep_obj.idxr.actors(myShow): if not ('name' in actor and actor['name'].strip()): continue cur_actor = ElementTree.SubElement(Persons, "Person") cur_actor_name = ElementTree.SubElement(cur_actor, "Name") cur_actor_name.text = actor['name'].strip() cur_actor_type = ElementTree.SubElement(cur_actor, "Type") cur_actor_type.text = "Actor" if 'role' in actor and actor['role'].strip(): cur_actor_role = ElementTree.SubElement(cur_actor, "Role") cur_actor_role.text = actor['role'].strip() if myEp.get('language'): language = myEp.get('language')['overview'] else: language = settings.INDEXER_DEFAULT_LANGUAGE Language = ElementTree.SubElement(episode, "Language") Language.text = language if myEp.get('filename'): thumb = ElementTree.SubElement(episode, "filename") thumb.text = curEpToWrite.idxr.complete_image_url(myEp['filename']) else: # append data from (if any) related episodes if curEpToWrite.name: if not EpisodeName.text: EpisodeName.text = curEpToWrite.name else: EpisodeName.text = EpisodeName.text + ", " + curEpToWrite.name if curEpToWrite.description: if not Overview.text: Overview.text = curEpToWrite.description else: Overview.text = Overview.text + "\r" + curEpToWrite.description # collect all directors, guest stars and writers if myEp.get('directors'): persons_dict['Director'] += myEp['directors'] if myEp.get('guestStars'): persons_dict['GuestStar'] += myEp['guestStars'] if myEp.get('writers'): persons_dict['Writer'] += myEp['writers'] # fill in Persons section with collected directors, guest starts and writers for person_type, names in persons_dict.items(): # remove doubles names = list(set(names)) for cur_name in names: Person = ElementTree.SubElement(Persons, "Person") cur_person_name = ElementTree.SubElement(Person, "Name") cur_person_name.text = cur_name cur_person_type = ElementTree.SubElement(Person, "Type") cur_person_type.text = person_type helpers.indentXML(rootNode) return ElementTree.ElementTree(rootNode)
def _show_data(self, show_obj): """ Creates an elementTree XML structure for a MediaBrowser-style series.xml returns the resulting data object. show_obj: a TVShow instance to create the NFO for """ tv_node = ElementTree.Element("Series") myShow = sickchill.indexer.series(show_obj) if not myShow: logger.exception("Unable to find show with id {} on {}, skipping it".format(show_obj.indexerid, show_obj.indexer_name)) return False # check for title and id if not (getattr(myShow, 'seriesName', None) and getattr(myShow, 'id', None)): logger.info("Incomplete info for show with id {} on {}, skipping it".format(show_obj.indexerid, show_obj.indexer_name)) return False data = getattr(myShow, 'id', None) if data: indexerid = ElementTree.SubElement(tv_node, "id") indexerid.text = str(data) data = getattr(myShow, 'seriesName', None) if data: SeriesName = ElementTree.SubElement(tv_node, "SeriesName") SeriesName.text = data data = getattr(myShow, 'status', None) if data: Status = ElementTree.SubElement(tv_node, "Status") Status.text = data data = getattr(myShow, 'network', None) if data: Network = ElementTree.SubElement(tv_node, "Network") Network.text = data Studios = ElementTree.SubElement(tv_node, "Studios") Studio = ElementTree.SubElement(Studios, "Studio") Studio.text = data data = getattr(myShow, 'airsTime', None) if data: airsTime = ElementTree.SubElement(tv_node, "Airs_Time") airsTime.text = data data = getattr(myShow, 'airsDayOfWeek', None) if data: airsDayOfWeek = ElementTree.SubElement(tv_node, "Airs_DayOfWeek") airsDayOfWeek.text = data data = getattr(myShow, 'firstAired', None) if data: FirstAired = ElementTree.SubElement(tv_node, "FirstAired") FirstAired.text = data PremiereDate = ElementTree.SubElement(tv_node, "PremiereDate") PremiereDate.text = data try: year_text = str(datetime.datetime.strptime(data, dateFormat).year) if year_text: ProductionYear = ElementTree.SubElement(tv_node, "ProductionYear") ProductionYear.text = year_text except Exception: pass data = getattr(myShow, 'rating', None) if data: ContentRating = ElementTree.SubElement(tv_node, "ContentRating") ContentRating.text = data MPAARating = ElementTree.SubElement(tv_node, "MPAARating") MPAARating.text = data certification = ElementTree.SubElement(tv_node, "certification") certification.text = data Rating = ElementTree.SubElement(tv_node, "Rating") Rating.text = data MetadataType = ElementTree.SubElement(tv_node, "Type") MetadataType.text = "Series" data = getattr(myShow, 'overview', None) if data: Overview = ElementTree.SubElement(tv_node, "Overview") Overview.text = data data = getattr(myShow, 'runtime', None) if data: RunningTime = ElementTree.SubElement(tv_node, "RunningTime") RunningTime.text = data Runtime = ElementTree.SubElement(tv_node, "Runtime") Runtime.text = data data = getattr(myShow, 'imdbId', None) if data: imdb_id = ElementTree.SubElement(tv_node, "IMDB_ID") imdb_id.text = data imdb_id = ElementTree.SubElement(tv_node, "IMDB") imdb_id.text = data imdb_id = ElementTree.SubElement(tv_node, "IMDbId") imdb_id.text = data data = getattr(myShow, 'zap2itId', None) if data: Zap2ItId = ElementTree.SubElement(tv_node, "Zap2ItId") Zap2ItId.text = data if getattr(myShow, 'genre', []) and isinstance(myShow.genre, list): Genres = ElementTree.SubElement(tv_node, "Genres") for genre in myShow.genre: if genre.strip(): cur_genre = ElementTree.SubElement(Genres, "Genre") cur_genre.text = genre.strip() Genre = ElementTree.SubElement(tv_node, "Genre") Genre.text = "|".join(myShow.genre) helpers.indentXML(tv_node) return ElementTree.ElementTree(tv_node)
def _ep_data(self, ep_obj): """ 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 """ eps_to_write = [ep_obj] + ep_obj.relatedEps myShow = ep_obj.idxr.series_from_episode(ep_obj) rootNode = ElementTree.Element("details") # write an WDTV XML containing info for all matching episodes for curEpToWrite in eps_to_write: myEp = curEpToWrite.idxr.episode(curEpToWrite) if not myEp: logger.info( "Metadata writer is unable to find episode {0:d}x{1:d} of {2} on {3}..." "has it been removed? Should I delete from db?".format(curEpToWrite.season, curEpToWrite.episode, curEpToWrite.show.name, ep_obj.idxr.name) ) return None if ep_obj.airdate != datetime.date.min and not myEp.get("firstAired"): myEp["firstAired"] = str(ep_obj.airdate) if not (myEp.get("episodeName") and myEp.get("firstAired")): return None if len(eps_to_write) > 1: episode = ElementTree.SubElement(rootNode, "details") else: episode = rootNode if myEp.get("id"): episodeID = ElementTree.SubElement(episode, "id") episodeID.text = str(myEp["id"]) title = ElementTree.SubElement(episode, "title") title.text = ep_obj.pretty_name() if getattr(myShow, "seriesName", None): seriesName = ElementTree.SubElement(episode, "series_name") seriesName.text = myShow.seriesName if curEpToWrite.name: episodeName = ElementTree.SubElement(episode, "episode_name") episodeName.text = curEpToWrite.name seasonNumber = ElementTree.SubElement(episode, "season_number") seasonNumber.text = str(curEpToWrite.season) episodeNum = ElementTree.SubElement(episode, "episode_number") episodeNum.text = str(curEpToWrite.episode) firstAired = ElementTree.SubElement(episode, "firstAired") if curEpToWrite.airdate != datetime.date.min: firstAired.text = str(curEpToWrite.airdate) if getattr(myShow, "firstAired", None): try: year_text = str(datetime.datetime.strptime(myShow.firstAired, dateFormat).year) if year_text: year = ElementTree.SubElement(episode, "year") year.text = year_text except Exception: pass if curEpToWrite.season != 0 and getattr(myShow, "runtime", None): runtime = ElementTree.SubElement(episode, "runtime") runtime.text = myShow.runtime if getattr(myShow, "genre", None): genre = ElementTree.SubElement(episode, "genre") genre.text = " / ".join(myShow.genre) if myEp.get("directors") and isinstance(myEp["directors"], list): for director in myEp["directors"]: director_element = ElementTree.SubElement(episode, "director") director_element.text = director data = ep_obj.idxr.actors(myShow) for actor in data: if not ("name" in actor and actor["name"].strip()): continue cur_actor = ElementTree.SubElement(episode, "actor") cur_actor_name = ElementTree.SubElement(cur_actor, "name") cur_actor_name.text = actor["name"] if "role" in actor and actor["role"].strip(): cur_actor_role = ElementTree.SubElement(cur_actor, "role") cur_actor_role.text = actor["role"].strip() if curEpToWrite.description: overview = ElementTree.SubElement(episode, "overview") overview.text = curEpToWrite.description # Make it purdy helpers.indentXML(rootNode) data = ElementTree.ElementTree(rootNode) return data
def _show_data(self, show_obj): """ Creates an elementTree XML structure for an KODI-style tvshow.nfo and returns the resulting data object. show_obj: a TVShow instance to create the NFO for """ tv_node = ElementTree.Element("tvshow") myShow = sickchill.indexer.series(show_obj) if not myShow: logger.info( "Unable to find show with id {} on {}, skipping it".format( show_obj.indexerid, show_obj.idxr.name)) return False # check for title and id if not (getattr(myShow, "seriesName", None) and getattr(myShow, "id", None)): logger.info( "Incomplete info for show with id {} on {}, skipping it". format(show_obj.indexerid, show_obj.idxr.name)) return False title = ElementTree.SubElement(tv_node, "title") title.text = myShow.seriesName if getattr(myShow, "rating", None): mpaa = ElementTree.SubElement(tv_node, "mpaa") mpaa.text = str(myShow.rating) if getattr(myShow, "siteRating", None): rating = ElementTree.SubElement(tv_node, "rating") rating.text = str(myShow.siteRating) if getattr(myShow, "firstAired", None): try: year_text = str( datetime.datetime.strptime(myShow.firstAired, dateFormat).year) if year_text: year = ElementTree.SubElement(tv_node, "year") year.text = year_text except Exception: pass if getattr(myShow, "overview", None): plot = ElementTree.SubElement(tv_node, "plot") plot.text = myShow.overview if getattr(myShow, "id", None): episodeguide = ElementTree.SubElement(tv_node, "episodeguide") episodeguideurl = ElementTree.SubElement(episodeguide, "url") episodeguideurl.attrib = {"post": "yes", "cache": "auth.json"} episodeguideurl.text = show_obj.idxr.episode_guide_url(show_obj) indexerid = ElementTree.SubElement(tv_node, "id") indexerid.text = str(myShow.id) indexerid = ElementTree.SubElement(tv_node, "tvdbid") indexerid.text = str(myShow.id) if getattr(myShow, "genre", None) and isinstance(myShow.genre, list): for genre in myShow.genre: cur_genre = ElementTree.SubElement(tv_node, "genre") cur_genre.text = genre if show_obj.imdb_info.get("country_codes"): for country in self._split_info( show_obj.imdb_info["country_codes"]): try: cur_country_name = Country(country.upper()).name.title() except Exception: continue cur_country = ElementTree.SubElement(tv_node, "country") cur_country.text = cur_country_name if getattr(myShow, "firstAired", None): premiered = ElementTree.SubElement(tv_node, "premiered") premiered.text = myShow.firstAired if getattr(myShow, "network", None): studio = ElementTree.SubElement(tv_node, "studio") studio.text = myShow.network.strip() data = show_obj.idxr.actors(myShow) if data: for actor in data: cur_actor = ElementTree.SubElement(tv_node, "actor") if "name" in actor and actor["name"].strip(): cur_actor_name = ElementTree.SubElement(cur_actor, "name") cur_actor_name.text = actor["name"].strip() else: continue if "role" in actor and actor["role"].strip(): cur_actor_role = ElementTree.SubElement(cur_actor, "role") cur_actor_role.text = actor["role"].strip() if "image" in actor and actor["image"].strip(): cur_actor_thumb = ElementTree.SubElement( cur_actor, "thumb") cur_actor_thumb.text = show_obj.idxr.complete_image_url( actor["image"]) # Make it purdy helpers.indentXML(tv_node) data = ElementTree.ElementTree(tv_node) return data
def _ep_data(self, ep_obj): """ Creates an elementTree XML structure for an KODI-style episode.nfo and returns the resulting data object. show_obj: a TVEpisode instance to create the NFO for """ eps_to_write = [ep_obj] + ep_obj.relatedEps myShow = ep_obj.idxr.series_from_episode(ep_obj) if not myShow: logger.info( "Unable to find {} on {} while creating meta files, skipping". format(ep_obj.show.indexerid, ep_obj.idxr.name)) return if len(eps_to_write) > 1: rootNode = ElementTree.Element("kodimultiepisode") else: rootNode = ElementTree.Element("episodedetails") # write an NFO containing info for all matching episodes for curEpToWrite in eps_to_write: myEp = curEpToWrite.idxr.episode(curEpToWrite) if not myEp: logger.info( "Metadata writer is unable to find episode {0:d}x{1:d} of {2} on {3}..." "has it been removed? Should I delete from db?".format( curEpToWrite.season, curEpToWrite.episode, curEpToWrite.show.name, ep_obj.idxr.name)) return None if ep_obj.airdate != datetime.date.min and not myEp.get( "firstAired"): myEp["firstAired"] = str(ep_obj.airdate) if not myEp.get("episodeName"): logger.debug("Not generating nfo because the ep has no title") return None if not myEp.get("firstAired"): logger.debug( "Not generating nfo because the ep has no airdate") return None logger.debug("Creating metadata for episode " + str(ep_obj.season) + "x" + str(ep_obj.episode)) if len(eps_to_write) > 1: episode = ElementTree.SubElement(rootNode, "episodedetails") else: episode = rootNode if myEp.get("episodeName"): title = ElementTree.SubElement(episode, "title") title.text = myEp["episodeName"] if getattr(myShow, "seriesName", None): showtitle = ElementTree.SubElement(episode, "showtitle") showtitle.text = myShow.seriesName season = ElementTree.SubElement(episode, "season") season.text = str(curEpToWrite.season) episodenum = ElementTree.SubElement(episode, "episode") episodenum.text = str(curEpToWrite.episode) if myEp.get("id"): uniqueid = ElementTree.SubElement(episode, "uniqueid") uniqueid.text = str(myEp["id"]) if curEpToWrite.airdate != datetime.date.min: aired = ElementTree.SubElement(episode, "aired") aired.text = str(curEpToWrite.airdate) if myEp.get("overview"): plot = ElementTree.SubElement(episode, "plot") plot.text = myEp["overview"] if curEpToWrite.season and getattr(myShow, "runtime", None): runtime = ElementTree.SubElement(episode, "runtime") runtime.text = myShow.runtime if myEp.get("airedSeason"): displayseason = ElementTree.SubElement(episode, "displayseason") displayseason.text = str(myEp["airedSeason"]) if myEp.get("airedEpisodeNumber"): displayepisode = ElementTree.SubElement( episode, "displayepisode") displayepisode.text = str(myEp["airedEpisodeNumber"]) if myEp.get("filename"): thumb = ElementTree.SubElement(episode, "thumb") thumb.text = ep_obj.idxr.complete_image_url(myEp["filename"]) if myEp.get("rating") is not None: rating = ElementTree.SubElement(episode, "rating") rating.text = str(myEp["rating"]) if myEp.get("writers") and isinstance(myEp["writers"], list): for writer in myEp["writers"]: cur_writer = ElementTree.SubElement(episode, "credits") cur_writer.text = writer if myEp.get("directors") and isinstance(myEp["directors"], list): for director in myEp["directors"]: cur_director = ElementTree.SubElement(episode, "director") cur_director.text = director if myEp.get("guestStars") and isinstance(myEp["guestStars"], list): for actor in myEp["guestStars"]: cur_actor = ElementTree.SubElement(episode, "actor") cur_actor_name = ElementTree.SubElement(cur_actor, "name") cur_actor_name.text = actor for actor in ep_obj.idxr.actors(myShow): cur_actor = ElementTree.SubElement(episode, "actor") if "name" in actor and actor["name"].strip(): cur_actor_name = ElementTree.SubElement(cur_actor, "name") cur_actor_name.text = actor["name"].strip() else: continue if "role" in actor and actor["role"].strip(): cur_actor_role = ElementTree.SubElement(cur_actor, "role") cur_actor_role.text = actor["role"].strip() if "image" in actor and actor["image"].strip(): cur_actor_thumb = ElementTree.SubElement( cur_actor, "thumb") cur_actor_thumb.text = ep_obj.idxr.complete_image_url( actor["image"]) # Make it purdy helpers.indentXML(rootNode) return ElementTree.ElementTree(rootNode)