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 dumpHTML(data): dumpName = os.path.join(settings.CACHE_DIR, 'custom_torrent.html') try: fileOut = open(dumpName, 'wb') fileOut.write(data) fileOut.close() helpers.chmodAsParent(dumpName) except IOError as error: logger.exception('Unable to save the file: {0}'.format(str(error))) return False logger.info('Saved custom_torrent html dump {0} '.format(dumpName)) return True
def write_ep_file(self, ep_obj): """ Generates and writes ep_obj's metadata under the given path with the given filename root. Uses the episode's name with the extension in _ep_nfo_extension. ep_obj: TVEpisode object for which to create the metadata file_name_path: The file name to use for this metadata. Note that the extension will be automatically added based on _ep_nfo_extension. This should include an absolute path. Note that this method expects that _ep_data will return an ElementTree object. If your _ep_data returns data in another format yo'll need to override this method. """ data = self._ep_data(ep_obj) if not data: return False # def print_data(d): # for child in d.getroot(): # print(str(child.tag), str(child.text)) # print_data(data) nfo_file_path = self.get_episode_file_path(ep_obj) nfo_file_dir = os.path.dirname(nfo_file_path) try: if not os.path.isdir(nfo_file_dir): logger.debug("Metadata dir didn't exist, creating it at " + nfo_file_dir) os.makedirs(nfo_file_dir) helpers.chmodAsParent(nfo_file_dir) logger.debug("Writing episode nfo file to " + nfo_file_path) nfo_file = open(nfo_file_path, 'wb') data.write(nfo_file, encoding='UTF-8') nfo_file.close() helpers.chmodAsParent(nfo_file_path) except IOError as e: logger.error("Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + str(e)) return False return True
def write_show_file(self, show_obj): """ Generates and writes show_obj's metadata under the given path to the filename given by get_show_file_path() show_obj: TVShow object for which to create the metadata path: An absolute or relative path where we should put the file. Note that the file name will be the default show_filename. Note that this method expects that _show_data will return an ElementTree object. If your _show_data returns data in another format yo'll need to override this method. """ data = self._show_data(show_obj) if not data: return False nfo_file_path = self.get_show_file_path(show_obj) nfo_file_dir = os.path.dirname(nfo_file_path) try: if not os.path.isdir(nfo_file_dir): logger.debug("Metadata dir didn't exist, creating it at " + nfo_file_dir) os.makedirs(nfo_file_dir) helpers.chmodAsParent(nfo_file_dir) logger.debug("Writing show nfo file to " + nfo_file_path) nfo_file = open(nfo_file_path, 'wb') data.write(nfo_file, encoding="utf-8", xml_declaration=True) nfo_file.close() helpers.chmodAsParent(nfo_file_path) except IOError as e: logger.error("Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + str(e)) return False return True
def _write_image(image_data, image_path, overwrite=False): """ Saves the data in image_data to the location image_path. Returns True/False to represent success or failure. image_data: binary image data to write to file image_path: file location to save the image to """ # don't bother overwriting it if not overwrite and os.path.isfile(image_path): logger.debug("Image already exists, not downloading") return False image_dir = os.path.dirname(image_path) if not image_data: logger.debug( "Unable to retrieve image to save in {0}, skipping".format( image_path)) return False try: if not os.path.isdir(image_dir): logger.debug("Metadata dir didn't exist, creating it at " + image_dir) os.makedirs(image_dir) helpers.chmodAsParent(image_dir) outFile = open(image_path, 'wb') outFile.write(image_data) outFile.close() helpers.chmodAsParent(image_path) except IOError as e: logger.error("Unable to write image to " + image_path + " - are you sure the show folder is writable? " + str(e)) return False return True
def write_ep_file(self, ep_obj): """ Generates and writes ep_obj's metadata under the given path with the given filename root. Uses the episode's name with the extension in _ep_nfo_extension. ep_obj: TVEpisode object for which to create the metadata filename_path: The file name to use for this metadata. Note that the extension will be automatically added based on _ep_nfo_extension. This should include an absolute path. """ data = self._ep_data(ep_obj) if not data: return False nfo_file_path = self.get_episode_file_path(ep_obj) nfo_file_dir = os.path.dirname(nfo_file_path) try: if not os.path.isdir(nfo_file_dir): logger.debug("Metadata dir didn't exist, creating it at " + nfo_file_dir) os.makedirs(nfo_file_dir) helpers.chmodAsParent(nfo_file_dir) logger.debug("Writing episode nfo file to " + nfo_file_path) data.write(nfo_file_path) helpers.chmodAsParent(nfo_file_path) except EnvironmentError as e: logger.error("Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + str(e)) return False return True
def addNewShow( self, whichSeries=None, indexerLang=None, rootDir=None, defaultStatus=None, quality_preset=None, anyQualities=None, bestQualities=None, season_folders=None, subtitles=None, subtitles_sr_metadata=None, fullShowPath=None, other_shows=None, skipShow=None, providedIndexer=None, anime=None, scene=None, blacklist=None, whitelist=None, defaultStatusAfter=None, ): """ Receive tvdb id, dir, and other options and create a show from them. If extra show dirs are provided then it forwards back to newShow, if not it goes to /home. """ if not indexerLang: indexerLang = settings.INDEXER_DEFAULT_LANGUAGE # grab our list of other dirs if given if not other_shows: other_shows = [] elif not isinstance(other_shows, list): other_shows = [other_shows] def finishAddShow(): # if there are no extra shows then go home if not other_shows: return self.redirect("/home/") # peel off the next one next_show_dir = other_shows[0] rest_of_show_dirs = other_shows[1:] # go to add the next show return self.newShow(next_show_dir, rest_of_show_dirs) # if we're skipping then behave accordingly if skipShow: return finishAddShow() # sanity check on our inputs if (not rootDir and not fullShowPath) or not whichSeries: return _( "Missing params, no Indexer ID or folder: {show_to_add} and {root_dir}/{show_path}" ).format(show_to_add=whichSeries, root_dir=rootDir, show_path=fullShowPath) # figure out what show we're adding and where series_pieces = whichSeries.split("|") if (whichSeries and rootDir) or (whichSeries and fullShowPath and len(series_pieces) > 1): if len(series_pieces) < 6: logger.error( "Unable to add show due to show selection. Not enough arguments: {0}" .format((repr(series_pieces)))) ui.notifications.error( _("Unknown error. Unable to add show due to problem with show selection." )) return self.redirect("/addShows/existingShows/") indexer = int(series_pieces[1]) indexer_id = int(series_pieces[3]) # Show name was sent in UTF-8 in the form show_name = xhtml_unescape(series_pieces[4]) else: # if no indexer was provided use the default indexer set in General settings if not providedIndexer: providedIndexer = settings.INDEXER_DEFAULT indexer = int(providedIndexer) indexer_id = int(whichSeries) show_name = os.path.basename( os.path.normpath(xhtml_unescape(fullShowPath))) # use the whole path if it's given, or else append the show name to the root dir to get the full show path if fullShowPath: show_dir = os.path.normpath(xhtml_unescape(fullShowPath)) extra_check_dir = show_dir else: folder_name = show_name s = sickchill.indexer.series_by_id(indexerid=indexer_id, indexer=indexer, language=indexerLang) if settings.ADD_SHOWS_WITH_YEAR and s.firstAired: try: year = "({0})".format( dateutil.parser.parse(s.firstAired).year) if year not in folder_name: folder_name = "{0} {1}".format(s.seriesName, year) except (TypeError, ValueError): logger.info( _("Could not append the show year folder for the show: {0}" ).format(folder_name)) show_dir = os.path.join( rootDir, sanitize_filename(xhtml_unescape(folder_name))) extra_check_dir = os.path.join( rootDir, sanitize_filename(xhtml_unescape(show_name))) # blanket policy - if the dir exists you should have used "add existing show" numbnuts if (os.path.isdir(show_dir) or os.path.isdir(extra_check_dir)) and not fullShowPath: ui.notifications.error( _("Unable to add show"), _("Folder {show_dir} exists already").format( show_dir=show_dir)) return self.redirect("/addShows/existingShows/") # don't create show dir if config says not to if settings.ADD_SHOWS_WO_DIR: logger.info("Skipping initial creation of " + show_dir + " due to config.ini setting") else: dir_exists = helpers.makeDir(show_dir) if not dir_exists: logger.exception("Unable to create the folder " + show_dir + ", can't add the show") ui.notifications.error( _("Unable to add show"), _("Unable to create the folder {show_dir}, can't add the show" ).format(show_dir=show_dir)) # Don't redirect to default page because user wants to see the new show return self.redirect("/home/") else: helpers.chmodAsParent(show_dir) # prepare the inputs for passing along scene = config.checkbox_to_value(scene) anime = config.checkbox_to_value(anime) season_folders = config.checkbox_to_value(season_folders) subtitles = config.checkbox_to_value(subtitles) subtitles_sr_metadata = config.checkbox_to_value(subtitles_sr_metadata) if whitelist: whitelist = short_group_names(whitelist) if blacklist: blacklist = short_group_names(blacklist) if not anyQualities: anyQualities = [] if not bestQualities or try_int(quality_preset, None): bestQualities = [] if not isinstance(anyQualities, list): anyQualities = [anyQualities] if not isinstance(bestQualities, list): bestQualities = [bestQualities] newQuality = Quality.combineQualities([int(q) for q in anyQualities], [int(q) for q in bestQualities]) # add the show settings.showQueueScheduler.action.add_show( indexer, indexer_id, showDir=show_dir, default_status=int(defaultStatus), quality=newQuality, season_folders=season_folders, lang=indexerLang, subtitles=subtitles, subtitles_sr_metadata=subtitles_sr_metadata, anime=anime, scene=scene, paused=None, blacklist=blacklist, whitelist=whitelist, default_status_after=int(defaultStatusAfter), root_dir=rootDir, ) ui.notifications.message( _("Show added"), _("Adding the specified show into {show_dir}").format( show_dir=show_dir)) return finishAddShow()