def process(self): self._log(u"Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") releaseName = show_name_helpers.determineReleaseName(self.dir_name, self.nzb_name) if releaseName is None: self._log(u"Warning: unable to find a valid release name.", logger.WARNING) raise exceptions.FailedProcessingFailed() try: parser = NameParser(False, convert=True) parsed = parser.parse(releaseName) except InvalidNameException: self._log(u"Error: release name is invalid: " + releaseName, logger.DEBUG) raise exceptions.FailedProcessingFailed() except InvalidShowException: self._log(u"Error: unable to parse release name " + releaseName + " into a valid show", logger.DEBUG) raise exceptions.FailedProcessingFailed() logger.log(u"name_parser info: ", logger.DEBUG) logger.log(u" - " + str(parsed.series_name), logger.DEBUG) logger.log(u" - " + str(parsed.season_number), logger.DEBUG) logger.log(u" - " + str(parsed.episode_numbers), logger.DEBUG) logger.log(u" - " + str(parsed.extra_info), logger.DEBUG) logger.log(u" - " + str(parsed.release_group), logger.DEBUG) logger.log(u" - " + str(parsed.air_date), logger.DEBUG) for episode in parsed.episode_numbers: segment = parsed.show.getEpisode(parsed.season_number, episode) cur_failed_queue_item = search_queue.FailedQueueItem(parsed.show, segment) sickbeard.searchQueueScheduler.action.add_item(cur_failed_queue_item) return True
def process(self): self._log(u"Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") releaseName = show_name_helpers.determineReleaseName(self.dir_name, self.nzb_name) if releaseName is None: self._log(u"Warning: unable to find a valid release name.", logger.WARNING) raise exceptions.FailedProcessingFailed() try: parser = NameParser(False, showObj=self.show, convert=True) parsed = parser.parse(releaseName) except InvalidNameException: self._log(u"Error: release name is invalid: " + releaseName, logger.DEBUG) raise exceptions.FailedProcessingFailed() except InvalidShowException: self._log(u"Error: unable to parse release name " + releaseName + " into a valid show", logger.DEBUG) raise exceptions.FailedProcessingFailed() logger.log(u"name_parser info: ", logger.DEBUG) logger.log(u" - " + str(parsed.series_name), logger.DEBUG) logger.log(u" - " + str(parsed.season_number), logger.DEBUG) logger.log(u" - " + str(parsed.episode_numbers), logger.DEBUG) logger.log(u" - " + str(parsed.extra_info), logger.DEBUG) logger.log(u" - " + str(parsed.release_group), logger.DEBUG) logger.log(u" - " + str(parsed.air_date), logger.DEBUG) for episode in parsed.episode_numbers: segment = parsed.show.getEpisode(parsed.season_number, episode) cur_failed_queue_item = search_queue.FailedQueueItem(parsed.show, [segment]) sickbeard.searchQueueScheduler.action.add_item(cur_failed_queue_item) return True
def process(self): """ Do the actual work :return: True """ self._log(u"Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") releaseName = show_name_helpers.determineReleaseName(self.dir_name, self.nzb_name) if not releaseName: self._log(u"Warning: unable to find a valid release name.", logger.WARNING) raise FailedPostProcessingFailedException() try: parsed = NameParser(False).parse(releaseName) except (InvalidNameException, InvalidShowException) as error: self._log(u"{}".format(error), logger.DEBUG) raise FailedPostProcessingFailedException() self._log(u"name_parser info: ", logger.DEBUG) self._log(u" - " + str(parsed.series_name), logger.DEBUG) self._log(u" - " + str(parsed.season_number), logger.DEBUG) self._log(u" - " + str(parsed.episode_numbers), logger.DEBUG) self._log(u" - " + str(parsed.extra_info), logger.DEBUG) self._log(u" - " + str(parsed.release_group), logger.DEBUG) self._log(u" - " + str(parsed.air_date), logger.DEBUG) for episode in parsed.episode_numbers: segment = parsed.show.getEpisode(parsed.season_number, episode) cur_failed_queue_item = search_queue.FailedQueueItem(parsed.show, [segment]) sickbeard.forcedSearchQueueScheduler.action.add_item(cur_failed_queue_item) return True
def process(self): """ Do the actual work :return: True """ self._log(u"Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") releaseName = show_name_helpers.determineReleaseName(self.dir_name, self.nzb_name) if not releaseName: self._log(u"Warning: unable to find a valid release name.", logger.WARNING) raise FailedPostProcessingFailedException() try: parsed = NameParser(False).parse(releaseName) except (InvalidNameException, InvalidShowException) as error: self._log(u"{0}".format(error), logger.DEBUG) raise FailedPostProcessingFailedException() self._log(u"name_parser info: ", logger.DEBUG) self._log(u" - " + str(parsed.series_name), logger.DEBUG) self._log(u" - " + str(parsed.season_number), logger.DEBUG) self._log(u" - " + str(parsed.episode_numbers), logger.DEBUG) self._log(u" - " + str(parsed.extra_info), logger.DEBUG) self._log(u" - " + str(parsed.release_group), logger.DEBUG) self._log(u" - " + str(parsed.air_date), logger.DEBUG) for episode in parsed.episode_numbers: segment = parsed.show.getEpisode(parsed.season_number, episode) cur_failed_queue_item = search_queue.FailedQueueItem(parsed.show, [segment]) sickbeard.searchQueueScheduler.action.add_item(cur_failed_queue_item) return True
def process(self): self._log(u"Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") releaseName = show_name_helpers.determineReleaseName( self.dir_name, self.nzb_name) if releaseName is None: self._log(u"Warning: unable to find a valid release name.", logger.WARNING) raise exceptions.FailedProcessingFailed() parser = NameParser(False) try: parsed = parser.parse(releaseName, True) except InvalidNameException: self._log(u"Error: release name is invalid: " + releaseName, logger.WARNING) raise exceptions.FailedProcessingFailed() logger.log(u"name_parser info: ", logger.DEBUG) logger.log(u" - " + str(parsed.series_name), logger.DEBUG) logger.log(u" - " + str(parsed.season_number), logger.DEBUG) logger.log(u" - " + str(parsed.episode_numbers), logger.DEBUG) logger.log(u" - " + str(parsed.extra_info), logger.DEBUG) logger.log(u" - " + str(parsed.release_group), logger.DEBUG) logger.log(u" - " + str(parsed.air_date), logger.DEBUG) show_id = self._get_show_id(parsed.series_name) if show_id is None: self._log(u"Warning: couldn't find show ID", logger.WARNING) raise exceptions.FailedProcessingFailed() self._log(u"Found show_id: " + str(show_id), logger.DEBUG) self._show_obj = helpers.findCertainShow(sickbeard.showList, show_id) if self._show_obj is None: self._log( u"Could not create show object. Either the show hasn't been added to SickBeard, or it's still loading (if SB was restarted recently)", logger.WARNING) raise exceptions.FailedProcessingFailed() # # Revert before fail, as fail alters the history # self._log(u"Reverting episodes...") # self.log += failed_history.revertEpisodes(self._show_obj, parsed.season_number, parsed.episode_numbers) # self._log(u"Marking release as bad: " + releaseName) # self.log += failed_history.logFailed(releaseName) self.log += failed_history.markFailed(self._show_obj, parsed.season_number, parsed.episode_numbers) # self._log(u"Marking release as Failed: " + releaseName) # self.log += failed_history.logFailed(releaseName) cur_failed_queue_item = search_queue.FailedQueueItem( self._show_obj, parsed.season_number) sickbeard.searchQueueScheduler.action.add_item(cur_failed_queue_item) return True
def process(self): self._log(u"Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") releaseName = show_name_helpers.determineReleaseName(self.dir_name, self.nzb_name) if releaseName is None: self._log(u"Warning: unable to find a valid release name.", logger.WARNING) raise exceptions.FailedProcessingFailed() parser = NameParser(False) try: parsed = parser.parse(releaseName, True) except InvalidNameException: self._log(u"Error: release name is invalid: " + releaseName, logger.WARNING) raise exceptions.FailedProcessingFailed() logger.log(u"name_parser info: ", logger.DEBUG) logger.log(u" - " + str(parsed.series_name), logger.DEBUG) logger.log(u" - " + str(parsed.season_number), logger.DEBUG) logger.log(u" - " + str(parsed.episode_numbers), logger.DEBUG) logger.log(u" - " + str(parsed.extra_info), logger.DEBUG) logger.log(u" - " + str(parsed.release_group), logger.DEBUG) logger.log(u" - " + str(parsed.air_date), logger.DEBUG) show_id = self._get_show_id(parsed.series_name) if show_id is None: self._log(u"Warning: couldn't find show ID", logger.WARNING) raise exceptions.FailedProcessingFailed() self._log(u"Found show_id: " + str(show_id), logger.DEBUG) self._show_obj = helpers.findCertainShow(sickbeard.showList, show_id) if self._show_obj is None: self._log(u"Could not create show object. Either the show hasn't been added to SickBeard, or it's still loading (if SB was restarted recently)", logger.WARNING) raise exceptions.FailedProcessingFailed() # # Revert before fail, as fail alters the history # self._log(u"Reverting episodes...") # self.log += failed_history.revertEpisodes(self._show_obj, parsed.season_number, parsed.episode_numbers) # self._log(u"Marking release as bad: " + releaseName) # self.log += failed_history.logFailed(releaseName) self.log += failed_history.markFailed(self._show_obj, parsed.season_number, parsed.episode_numbers) # self._log(u"Marking release as Failed: " + releaseName) # self.log += failed_history.logFailed(releaseName) cur_failed_queue_item = search_queue.FailedQueueItem(self._show_obj, parsed.season_number) sickbeard.searchQueueScheduler.action.add_item(cur_failed_queue_item) return True
def process(self): self._log(u"Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") releaseName = show_name_helpers.determineReleaseName( self.dir_name, self.nzb_name) if releaseName is None: self._log(u"Warning: unable to find a valid release name.", logger.WARNING) raise exceptions.FailedProcessingFailed() parser = NameParser(False) try: parsed = parser.parse(releaseName) except InvalidNameException: self._log(u"Error: release name is invalid: " + releaseName, logger.WARNING) raise exceptions.FailedProcessingFailed() logger.log(u"name_parser info: ", logger.DEBUG) logger.log(u" - " + str(parsed.series_name), logger.DEBUG) logger.log(u" - " + str(parsed.season_number), logger.DEBUG) logger.log(u" - " + str(parsed.episode_numbers), logger.DEBUG) logger.log(u" - " + str(parsed.extra_info), logger.DEBUG) logger.log(u" - " + str(parsed.release_group), logger.DEBUG) logger.log(u" - " + str(parsed.air_date), logger.DEBUG) logger.log(u" - " + str(parsed.sports_event_date), logger.DEBUG) self._show_obj = sickbeard.helpers.get_show_by_name(parsed.series_name) if self._show_obj is None: self._log( u"Could not create show object. Either the show hasn't been added to SickBeard, or it's still loading (if SB was restarted recently)", logger.WARNING) raise exceptions.FailedProcessingFailed() # scene -> indexer numbering parsed = parsed.convert(self._show_obj) segment = {parsed.season_number: []} for episode in parsed.episode_numbers: epObj = self._show_obj.getEpisode(parsed.season_number, episode) segment[parsed.season_number].append(epObj) cur_failed_queue_item = search_queue.FailedQueueItem( self._show_obj, segment) sickbeard.searchQueueScheduler.action.add_item(cur_failed_queue_item) return True
def process(self): """ Do the actual work :return: True """ self._log("Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") releaseName = show_name_helpers.determineReleaseName( self.dir_name, self.nzb_name) if releaseName is None: self._log("Warning: unable to find a valid release name.", logging.WARNING) raise FailedPostProcessingFailedException() try: parser = NameParser(False) parsed = parser.parse(releaseName) except InvalidNameException: self._log("Error: release name is invalid: " + releaseName, logging.DEBUG) raise FailedPostProcessingFailedException() except InvalidShowException: self._log( "Error: unable to parse release name " + releaseName + " into a valid show", logging.DEBUG) raise FailedPostProcessingFailedException() logging.debug("name_parser info: ") logging.debug(" - " + str(parsed.series_name)) logging.debug(" - " + str(parsed.season_number)) logging.debug(" - " + str(parsed.episode_numbers)) logging.debug(" - " + str(parsed.extra_info)) logging.debug(" - " + str(parsed.release_group)) logging.debug(" - " + str(parsed.air_date)) for episode in parsed.episode_numbers: segment = parsed.show.getEpisode(parsed.season_number, episode) cur_failed_queue_item = search_queue.FailedQueueItem( parsed.show, [segment]) sickbeard.searchQueueScheduler.action.add_item( cur_failed_queue_item) return True
def process(self): self._log(u"Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") releaseName = show_name_helpers.determineReleaseName(self.dir_name, self.nzb_name) if releaseName is None: self._log(u"Warning: unable to find a valid release name.", logger.WARNING) raise exceptions.FailedProcessingFailed() try: parser = NameParser(False, convert=True) parsed = parser.parse(releaseName) except InvalidNameException: self._log(u"Error: release name is invalid: " + releaseName, logger.WARNING) raise exceptions.FailedProcessingFailed() except InvalidShowException: self._log(u"Error: unable to parse release name " + releaseName + " into a valid show", logger.WARNING) raise exceptions.FailedProcessingFailed logger.log(u"name_parser info: ", logger.DEBUG) logger.log(u" - " + str(parsed.series_name), logger.DEBUG) logger.log(u" - " + str(parsed.season_number), logger.DEBUG) logger.log(u" - " + str(parsed.episode_numbers), logger.DEBUG) logger.log(u" - " + str(parsed.extra_info), logger.DEBUG) logger.log(u" - " + str(parsed.release_group), logger.DEBUG) logger.log(u" - " + str(parsed.air_date), logger.DEBUG) logger.log(u" - " + str(parsed.sports_event_date), logger.DEBUG) if parsed.show is None: self._log( u"Could not create show object. Either the show hasn't been added to SickRage, or it's still loading (if SB was restarted recently)", logger.WARNING, ) raise exceptions.FailedProcessingFailed() segment = {parsed.season_number: []} for episode in parsed.episode_numbers: epObj = parsed.show.getEpisode(parsed.season_number, episode) segment[parsed.season_number].append(epObj) cur_failed_queue_item = search_queue.FailedQueueItem(parsed.show, segment) sickbeard.searchQueueScheduler.action.add_item(cur_failed_queue_item) return True
def process(self): """ Post-process a given file """ self._log(u"Processing " + self.file_path + " (" + str(self.nzb_name) + ")") if ek.ek(os.path.isdir, self.file_path): self._log(u"File " + self.file_path + " seems to be a directory") return False for ignore_file in self.IGNORED_FILESTRINGS: if ignore_file in self.file_path: self._log(u"File " + self.file_path + " is ignored type, skipping") return False # reset per-file stuff self.in_history = False # try to find the file info (indexer_id, season, episodes) = self._find_info() if not (indexer_id and season and len(episodes)): self._log(u"Can't find the show on any of the Indexers, skipping", logger.WARNING) return False # retrieve/create the corresponding TVEpisode objects ep_obj = self._get_ep_obj(indexer_id, season, episodes) # get the quality of the episode we're processing new_ep_quality = self._get_quality(ep_obj) logger.log(u"Quality of the episode we're processing: " + str(new_ep_quality), logger.DEBUG) # see if this is a priority download (is it snatched, in history, PROPER, or BEST) priority_download = self._is_priority(ep_obj, new_ep_quality) self._log(u"Is ep a priority download: " + str(priority_download), logger.DEBUG) # set the status of the episodes for curEp in [ep_obj] + ep_obj.relatedEps: curEp.status = common.Quality.compositeStatus(common.SNATCHED, new_ep_quality) # check for an existing file existing_file_status = self._checkForExistingFile(ep_obj.location) # if it's not priority then we don't want to replace smaller files in case it was a mistake if not priority_download: # if there's an existing file that we don't want to replace stop here if existing_file_status in (PostProcessor.EXISTS_LARGER, PostProcessor.EXISTS_SAME): self._log( u"File exists and we are not going to replace it because it's not smaller, quitting post-processing", logger.ERROR) return False elif existing_file_status == PostProcessor.EXISTS_SMALLER: self._log(u"File exists and is smaller than the new file so I'm going to replace it", logger.DEBUG) elif existing_file_status != PostProcessor.DOESNT_EXIST: self._log(u"Unknown existing file status. This should never happen, please log this as a bug.", logger.ERROR) return False # if the file is priority then we're going to replace it even if it exists else: self._log( u"This download is marked a priority download so I'm going to replace an existing file if I find one", logger.DEBUG) # delete the existing file (and company) for cur_ep in [ep_obj] + ep_obj.relatedEps: try: self._delete(cur_ep.location, associated_files=True) # clean up any left over folders if cur_ep.location: helpers.delete_empty_folders(ek.ek(os.path.dirname, cur_ep.location), keep_dir=ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed("Unable to delete the existing files") # if the show directory doesn't exist then make it if allowed if not ek.ek(os.path.isdir, ep_obj.show._location) and sickbeard.CREATE_MISSING_SHOW_DIRS: self._log(u"Show directory doesn't exist, creating it", logger.DEBUG) try: ek.ek(os.mkdir, ep_obj.show._location) # do the library update for synoindex notifiers.synoindex_notifier.addFolder(ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed("Unable to create the show directory: " + ep_obj.show._location) # get metadata for the show (but not episode because it hasn't been fully processed) ep_obj.show.writeMetadata(True) # update the ep info before we rename so the quality & release name go into the name properly for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_release_name = None # use the best possible representation of the release name if self.good_results[self.NZB_NAME]: cur_release_name = self.nzb_name if cur_release_name.lower().endswith('.nzb'): cur_release_name = cur_release_name.rpartition('.')[0] elif self.good_results[self.FOLDER_NAME]: cur_release_name = self.folder_name elif self.good_results[self.FILE_NAME]: cur_release_name = self.file_name # take the extension off the filename, it's not needed if '.' in self.file_name: cur_release_name = self.file_name.rpartition('.')[0] if cur_release_name: self._log("Found release name " + cur_release_name, logger.DEBUG) cur_ep.release_name = cur_release_name else: logger.log("good results: " + repr(self.good_results), logger.DEBUG) if ep_obj.status in common.Quality.SNATCHED_BEST: cur_ep.status = common.Quality.compositeStatus(common.ARCHIVED, new_ep_quality) else: cur_ep.status = common.Quality.compositeStatus(common.DOWNLOADED, new_ep_quality) cur_ep.subtitles = [] cur_ep.subtitles_searchcount = 0 cur_ep.subtitles_lastsearch = '0001-01-01 00:00:00' cur_ep.is_proper = self.is_proper cur_ep.saveToDB() # Just want to keep this consistent for failed handling right now releaseName = show_name_helpers.determineReleaseName(self.folder_path, self.nzb_name) if releaseName is not None: failed_history.logSuccess(releaseName) else: self._log(u"Couldn't find release in snatch history", logger.WARNING) # find the destination folder try: proper_path = ep_obj.proper_path() proper_absolute_path = ek.ek(os.path.join, ep_obj.show.location, proper_path) dest_path = ek.ek(os.path.dirname, proper_absolute_path) except exceptions.ShowDirNotFoundException: raise exceptions.PostProcessingFailed( u"Unable to post-process an episode if the show dir doesn't exist, quitting") self._log(u"Destination folder for this episode: " + dest_path, logger.DEBUG) # create any folders we need helpers.make_dirs(dest_path) # figure out the base name of the resulting episode file if sickbeard.RENAME_EPISODES: orig_extension = self.file_name.rpartition('.')[-1] new_base_name = ek.ek(os.path.basename, proper_path) new_file_name = new_base_name + '.' + orig_extension else: # if we're not renaming then there's no new base name, we'll just use the existing name new_base_name = None new_file_name = self.file_name try: # move the episode and associated files to the show dir if self.process_method == "copy": self._copy(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "move": self._move(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "hardlink": self._hardlink(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "symlink": self._moveAndSymlink(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) else: logger.log(u"Unknown process method: " + str(self.process_method), logger.ERROR) raise exceptions.PostProcessingFailed("Unable to move the files to their new home") except (OSError, IOError): raise exceptions.PostProcessingFailed("Unable to move the files to their new home") # download subtitles if sickbeard.USE_SUBTITLES and ep_obj.show.subtitles: for curEp in [ep_obj]: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) cur_ep.downloadSubtitles(force=True) # put the new location in the database for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) cur_ep.saveToDB() # log it to history history.logDownload(ep_obj, self.file_path, new_ep_quality, self.release_group) # send notifications notifiers.notify_download(ep_obj._format_pattern('%SN - %Sx%0E - %EN - %QN')) # generate nfo/tbn ep_obj.createMetaFiles() ep_obj.saveToDB() # do the library update for XBMC notifiers.xbmc_notifier.update_library(ep_obj.show.name) # do the library update for Plex notifiers.plex_notifier.update_library() # do the library update for NMJ # nmj_notifier kicks off its library update when the notify_download is issued (inside notifiers) # do the library update for Synology Indexer notifiers.synoindex_notifier.addFile(ep_obj.location) # do the library update for pyTivo notifiers.pytivo_notifier.update_library(ep_obj) # do the library update for Trakt notifiers.trakt_notifier.update_library(ep_obj) self._run_extra_scripts(ep_obj) return True
def process(self): """ Post-process a given file """ self._log(u"Processing " + self.file_path + " (" + str(self.nzb_name) + ")") if ek.ek(os.path.isdir, self.file_path): self._log(u"File " + self.file_path + " seems to be a directory") return False for ignore_file in self.IGNORED_FILESTRINGS: if ignore_file in self.file_path: self._log(u"File " + self.file_path + " is ignored type, skipping") return False # reset per-file stuff self.in_history = False # try to find the file info (tvdb_id, season, episodes) = self._find_info() # if we don't have it then give up if not tvdb_id or season == None or not episodes: self._log(u"Can't find show id from TVDB or season or episode, skipping", logger.WARNING) return False # retrieve/create the corresponding TVEpisode objects ep_obj = self._get_ep_obj(tvdb_id, season, episodes) # get the quality of the episode we're processing new_ep_quality = self._get_quality(ep_obj) logger.log(u"Quality of the episode we're processing: " + str(new_ep_quality), logger.DEBUG) # see if this is a priority download (is it snatched, in history, or PROPER) priority_download = self._is_priority(ep_obj, new_ep_quality) self._log(u"Is ep a priority download: " + str(priority_download), logger.DEBUG) # set the status of the episodes for curEp in [ep_obj] + ep_obj.relatedEps: curEp.status = common.Quality.compositeStatus(common.SNATCHED, new_ep_quality) # check for an existing file existing_file_status = self._checkForExistingFile(ep_obj.location) # if it's not priority then we don't want to replace smaller files in case it was a mistake if not priority_download: # if there's an existing file that we don't want to replace stop here if existing_file_status in (PostProcessor.EXISTS_LARGER, PostProcessor.EXISTS_SAME): self._log(u"File exists and we are not going to replace it because it's not smaller, quitting post-processing", logger.ERROR) return False elif existing_file_status == PostProcessor.EXISTS_SMALLER: self._log(u"File exists and is smaller than the new file so I'm going to replace it", logger.DEBUG) elif existing_file_status != PostProcessor.DOESNT_EXIST: self._log(u"Unknown existing file status. This should never happen, please log this as a bug.", logger.ERROR) return False # if the file is priority then we're going to replace it even if it exists else: self._log(u"This download is marked a priority download so I'm going to replace an existing file if I find one", logger.DEBUG) # delete the existing file (and company) for cur_ep in [ep_obj] + ep_obj.relatedEps: try: self._delete(cur_ep.location, associated_files=True) # clean up any left over folders if cur_ep.location: helpers.delete_empty_folders(ek.ek(os.path.dirname, cur_ep.location), keep_dir=ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed("Unable to delete the existing files") # if the show directory doesn't exist then make it if allowed if not ek.ek(os.path.isdir, ep_obj.show._location) and sickbeard.CREATE_MISSING_SHOW_DIRS: self._log(u"Show directory doesn't exist, creating it", logger.DEBUG) try: ek.ek(os.mkdir, ep_obj.show._location) # do the library update for synoindex notifiers.synoindex_notifier.addFolder(ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed("Unable to create the show directory: " + ep_obj.show._location) # get metadata for the show (but not episode because it hasn't been fully processed) ep_obj.show.writeMetadata(True) # update the ep info before we rename so the quality & release name go into the name properly for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_release_name = None # use the best possible representation of the release name if self.good_results[self.NZB_NAME]: cur_release_name = self.nzb_name if cur_release_name.lower().endswith('.nzb'): cur_release_name = cur_release_name.rpartition('.')[0] elif self.good_results[self.FOLDER_NAME]: cur_release_name = self.folder_name elif self.good_results[self.FILE_NAME]: cur_release_name = self.file_name # take the extension off the filename, it's not needed if '.' in self.file_name: cur_release_name = self.file_name.rpartition('.')[0] if cur_release_name: self._log("Found release name " + cur_release_name, logger.DEBUG) cur_ep.release_name = cur_release_name else: logger.log("good results: " + repr(self.good_results), logger.DEBUG) cur_ep.status = common.Quality.compositeStatus(common.DOWNLOADED, new_ep_quality) cur_ep.subtitles = [] cur_ep.subtitles_searchcount = 0 cur_ep.subtitles_lastsearch = '0001-01-01 00:00:00' cur_ep.is_proper = self.is_proper cur_ep.saveToDB() # Just want to keep this consistent for failed handling right now releaseName = show_name_helpers.determineReleaseName(self.folder_path, self.nzb_name) if releaseName is not None: failed_history.logSuccess(releaseName) else: self._log(u"Couldn't find release in snatch history", logger.WARNING) # find the destination folder try: proper_path = ep_obj.proper_path() proper_absolute_path = ek.ek(os.path.join, ep_obj.show.location, proper_path) dest_path = ek.ek(os.path.dirname, proper_absolute_path) except exceptions.ShowDirNotFoundException: raise exceptions.PostProcessingFailed(u"Unable to post-process an episode if the show dir doesn't exist, quitting") self._log(u"Destination folder for this episode: " + dest_path, logger.DEBUG) # create any folders we need helpers.make_dirs(dest_path) # figure out the base name of the resulting episode file if sickbeard.RENAME_EPISODES: orig_extension = self.file_name.rpartition('.')[-1] new_base_name = ek.ek(os.path.basename, proper_path) new_file_name = new_base_name + '.' + orig_extension else: # if we're not renaming then there's no new base name, we'll just use the existing name new_base_name = None new_file_name = self.file_name try: # move the episode and associated files to the show dir if self.process_method == "copy": self._copy(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "move": self._move(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "hardlink": self._hardlink(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "symlink": self._moveAndSymlink(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) else: logger.log(u"Unknown process method: " + sickbeard.PROCESS_METHOD, logger.ERROR) raise exceptions.PostProcessingFailed("Unable to move the files to their new home") except (OSError, IOError): raise exceptions.PostProcessingFailed("Unable to move the files to their new home") # download subtitles if sickbeard.USE_SUBTITLES and ep_obj.show.subtitles: for curEp in [ep_obj]: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) cur_ep.downloadSubtitles(force=True) # put the new location in the database for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) cur_ep.saveToDB() # log it to history history.logDownload(ep_obj, self.file_path, new_ep_quality, self.release_group) # send notifications notifiers.notify_download(ep_obj._format_pattern('%SN - %Sx%0E - %EN - %QN')) # generate nfo/tbn ep_obj.createMetaFiles() ep_obj.saveToDB() # do the library update for XBMC notifiers.xbmc_notifier.update_library(ep_obj.show.name) # do the library update for Plex notifiers.plex_notifier.update_library() # do the library update for NMJ # nmj_notifier kicks off its library update when the notify_download is issued (inside notifiers) # do the library update for Synology Indexer notifiers.synoindex_notifier.addFile(ep_obj.location) # do the library update for pyTivo notifiers.pytivo_notifier.update_library(ep_obj) # do the library update for Trakt notifiers.trakt_notifier.update_library(ep_obj) self._run_extra_scripts(ep_obj) return True
def process(self): """ Post-process a given file """ self._log(u"Processing " + self.file_path + " (" + str(self.nzb_name) + ")") if ek.ek(os.path.isdir, self.file_path): self._log(u"File " + self.file_path + " seems to be a directory") return False for ignore_file in self.IGNORED_FILESTRINGS: if ignore_file in self.file_path: self._log(u"File " + self.file_path + " is ignored type, skipping") return False # reset per-file stuff self.in_history = False # reset the anidb episode object self.anidbEpisode = None # try to find the file info (show, season, episodes, quality, version) = self._find_info() if not show: self._log(u"This show isn't in your list, you need to add it to SB before post-processing an episode", logger.WARNING) raise exceptions.PostProcessingFailed() elif season == None or not episodes: self._log(u"Not enough information to determine what episode this is", logger.DEBUG) self._log(u"Quitting post-processing", logger.DEBUG) return False # retrieve/create the corresponding TVEpisode objects ep_obj = self._get_ep_obj(show, season, episodes) # get the quality of the episode we're processing if quality: self._log(u"Snatch history had a quality in it, using that: " + common.Quality.qualityStrings[quality], logger.DEBUG) new_ep_quality = quality else: new_ep_quality = self._get_quality(ep_obj) logger.log(u"Quality of the episode we're processing: " + str(new_ep_quality), logger.DEBUG) # see if this is a priority download (is it snatched, in history, PROPER, or BEST) priority_download = self._is_priority(ep_obj, new_ep_quality) self._log(u"Is ep a priority download: " + str(priority_download), logger.DEBUG) # get the version of the episode we're processing if version: self._log(u"Snatch history had a version in it, using that: v" + str(version), logger.DEBUG) new_ep_version = version else: new_ep_version = -1 # check for an existing file existing_file_status = self._checkForExistingFile(ep_obj.location) # if it's not priority then we don't want to replace smaller files in case it was a mistake if not priority_download: # if there's an existing file that we don't want to replace stop here if existing_file_status == PostProcessor.EXISTS_LARGER: if self.is_proper: self._log( u"File exists and new file is smaller, new file is a proper/repack, marking it safe to replace", logger.DEBUG) return True else: self._log(u"File exists and new file is smaller, marking it unsafe to replace", logger.DEBUG) return False elif existing_file_status == PostProcessor.EXISTS_SAME: self._log(u"File exists and new file is same size, marking it unsafe to replace", logger.DEBUG) return False # if the file is priority then we're going to replace it even if it exists else: self._log( u"This download is marked a priority download so I'm going to replace an existing file if I find one", logger.DEBUG) # delete the existing file (and company) for cur_ep in [ep_obj] + ep_obj.relatedEps: try: self._delete(cur_ep.location, associated_files=True) # clean up any left over folders if cur_ep.location: helpers.delete_empty_folders(ek.ek(os.path.dirname, cur_ep.location), keep_dir=ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed("Unable to delete the existing files") # set the status of the episodes # for curEp in [ep_obj] + ep_obj.relatedEps: # curEp.status = common.Quality.compositeStatus(common.SNATCHED, new_ep_quality) # if the show directory doesn't exist then make it if allowed if not ek.ek(os.path.isdir, ep_obj.show._location) and sickbeard.CREATE_MISSING_SHOW_DIRS: self._log(u"Show directory doesn't exist, creating it", logger.DEBUG) try: ek.ek(os.mkdir, ep_obj.show._location) # do the library update for synoindex notifiers.synoindex_notifier.addFolder(ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed("Unable to create the show directory: " + ep_obj.show._location) # get metadata for the show (but not episode because it hasn't been fully processed) ep_obj.show.writeMetadata(True) # update the ep info before we rename so the quality & release name go into the name properly sql_l = [] for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: if self.release_name: self._log("Found release name " + self.release_name, logger.DEBUG) cur_ep.release_name = self.release_name else: cur_ep.release_name = "" if ep_obj.status in common.Quality.SNATCHED_BEST: cur_ep.status = common.Quality.compositeStatus(common.ARCHIVED, new_ep_quality) else: cur_ep.status = common.Quality.compositeStatus(common.DOWNLOADED, new_ep_quality) cur_ep.subtitles = [] cur_ep.subtitles_searchcount = 0 cur_ep.subtitles_lastsearch = '0001-01-01 00:00:00' cur_ep.is_proper = self.is_proper cur_ep.version = new_ep_version if self.release_group: cur_ep.release_group = self.release_group else: cur_ep.release_group = "" sql_l.append(cur_ep.get_sql()) if len(sql_l) > 0: myDB = db.DBConnection() myDB.mass_action(sql_l) # Just want to keep this consistent for failed handling right now releaseName = show_name_helpers.determineReleaseName(self.folder_path, self.nzb_name) if releaseName is not None: failed_history.logSuccess(releaseName) else: self._log(u"Couldn't find release in snatch history", logger.WARNING) # find the destination folder try: proper_path = ep_obj.proper_path() proper_absolute_path = ek.ek(os.path.join, ep_obj.show.location, proper_path) dest_path = ek.ek(os.path.dirname, proper_absolute_path) except exceptions.ShowDirNotFoundException: raise exceptions.PostProcessingFailed( u"Unable to post-process an episode if the show dir doesn't exist, quitting") self._log(u"Destination folder for this episode: " + dest_path, logger.DEBUG) # create any folders we need helpers.make_dirs(dest_path) # figure out the base name of the resulting episode file if sickbeard.RENAME_EPISODES: orig_extension = self.file_name.rpartition('.')[-1] new_base_name = ek.ek(os.path.basename, proper_path) new_file_name = new_base_name + '.' + orig_extension else: # if we're not renaming then there's no new base name, we'll just use the existing name new_base_name = None new_file_name = self.file_name # add to anidb if ep_obj.show.is_anime and sickbeard.ANIDB_USE_MYLIST: self._add_to_anidb_mylist(self.file_path) try: # move the episode and associated files to the show dir if self.process_method == "copy": self._copy(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "move": self._move(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "hardlink": self._hardlink(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "symlink": self._moveAndSymlink(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) else: logger.log(u"Unknown process method: " + str(self.process_method), logger.ERROR) raise exceptions.PostProcessingFailed("Unable to move the files to their new home") except (OSError, IOError): raise exceptions.PostProcessingFailed("Unable to move the files to their new home") # download subtitles if sickbeard.USE_SUBTITLES and ep_obj.show.subtitles: for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) cur_ep.downloadSubtitles(force=True) # put the new location in the database sql_l = [] for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) sql_l.append(cur_ep.get_sql()) if len(sql_l) > 0: myDB = db.DBConnection() myDB.mass_action(sql_l) # set file modify stamp to show airdate if sickbeard.AIRDATE_EPISODES: for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.airdateModifyStamp() # generate nfo/tbn ep_obj.createMetaFiles() # log it to history history.logDownload(ep_obj, self.file_path, new_ep_quality, self.release_group, new_ep_version) # send notifications notifiers.notify_download(ep_obj._format_pattern('%SN - %Sx%0E - %EN - %QN')) # do the library update for KODI notifiers.kodi_notifier.update_library(ep_obj.show.name) # do the library update for Plex notifiers.plex_notifier.update_library() # do the library update for NMJ # nmj_notifier kicks off its library update when the notify_download is issued (inside notifiers) # do the library update for Synology Indexer notifiers.synoindex_notifier.addFile(ep_obj.location) # do the library update for pyTivo notifiers.pytivo_notifier.update_library(ep_obj) # do the library update for Trakt notifiers.trakt_notifier.update_library(ep_obj) self._run_extra_scripts(ep_obj) return True
def process(self): """ Post-process a given file """ self._log(u"Processing " + self.file_path + " (" + str(self.nzb_name) + ")") if ek.ek(os.path.isdir, self.file_path): self._log(u"File " + self.file_path + " seems to be a directory") return False for ignore_file in self.IGNORED_FILESTRINGS: if ignore_file in self.file_path: self._log(u"File " + self.file_path + " is ignored type, skipping") return False # reset per-file stuff self.in_history = False # reset the anidb episode object self.anidbEpisode = None # try to find the file info (show, season, episodes, quality, version) = self._find_info() if not show: self._log( u"This show isn't in your list, you need to add it to SB before post-processing an episode", logger.WARNING) raise exceptions.PostProcessingFailed() elif season == None or not episodes: self._log( u"Not enough information to determine what episode this is", logger.DEBUG) self._log(u"Quitting post-processing", logger.DEBUG) return False # retrieve/create the corresponding TVEpisode objects ep_obj = self._get_ep_obj(show, season, episodes) # get the quality of the episode we're processing if quality: self._log( u"Snatch history had a quality in it, using that: " + common.Quality.qualityStrings[quality], logger.DEBUG) new_ep_quality = quality else: new_ep_quality = self._get_quality(ep_obj) logger.log( u"Quality of the episode we're processing: " + str(new_ep_quality), logger.DEBUG) # see if this is a priority download (is it snatched, in history, PROPER, or BEST) priority_download = self._is_priority(ep_obj, new_ep_quality) self._log(u"Is ep a priority download: " + str(priority_download), logger.DEBUG) # get the version of the episode we're processing if version: self._log( u"Snatch history had a version in it, using that: v" + str(version), logger.DEBUG) new_ep_version = version else: new_ep_version = -1 # check for an existing file existing_file_status = self._checkForExistingFile(ep_obj.location) # if it's not priority then we don't want to replace smaller files in case it was a mistake if not priority_download: # if there's an existing file that we don't want to replace stop here if existing_file_status == PostProcessor.EXISTS_LARGER: if self.is_proper: self._log( u"File exists and new file is smaller, new file is a proper/repack, marking it safe to replace", logger.DEBUG) return True else: self._log( u"File exists and new file is smaller, marking it unsafe to replace", logger.DEBUG) return False elif existing_file_status == PostProcessor.EXISTS_SAME: self._log( u"File exists and new file is same size, marking it unsafe to replace", logger.DEBUG) return False # if the file is priority then we're going to replace it even if it exists else: self._log( u"This download is marked a priority download so I'm going to replace an existing file if I find one", logger.DEBUG) # delete the existing file (and company) for cur_ep in [ep_obj] + ep_obj.relatedEps: try: self._delete(cur_ep.location, associated_files=True) # clean up any left over folders if cur_ep.location: helpers.delete_empty_folders( ek.ek(os.path.dirname, cur_ep.location), keep_dir=ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed( "Unable to delete the existing files") # set the status of the episodes # for curEp in [ep_obj] + ep_obj.relatedEps: # curEp.status = common.Quality.compositeStatus(common.SNATCHED, new_ep_quality) # if the show directory doesn't exist then make it if allowed if not ek.ek( os.path.isdir, ep_obj.show._location) and sickbeard.CREATE_MISSING_SHOW_DIRS: self._log(u"Show directory doesn't exist, creating it", logger.DEBUG) try: ek.ek(os.mkdir, ep_obj.show._location) # do the library update for synoindex notifiers.synoindex_notifier.addFolder(ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed( "Unable to create the show directory: " + ep_obj.show._location) # get metadata for the show (but not episode because it hasn't been fully processed) ep_obj.show.writeMetadata(True) # update the ep info before we rename so the quality & release name go into the name properly sql_l = [] trakt_data = [] for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: if self.release_name: self._log("Found release name " + self.release_name, logger.DEBUG) cur_ep.release_name = self.release_name else: cur_ep.release_name = "" if ep_obj.status in common.Quality.SNATCHED_BEST: cur_ep.status = common.Quality.compositeStatus( common.ARCHIVED, new_ep_quality) else: cur_ep.status = common.Quality.compositeStatus( common.DOWNLOADED, new_ep_quality) cur_ep.subtitles = [] cur_ep.subtitles_searchcount = 0 cur_ep.subtitles_lastsearch = '0001-01-01 00:00:00' cur_ep.is_proper = self.is_proper cur_ep.version = new_ep_version if self.release_group: cur_ep.release_group = self.release_group else: cur_ep.release_group = "" sql_l.append(cur_ep.get_sql()) trakt_data.append((cur_ep.season, cur_ep.episode)) data = notifiers.trakt_notifier.trakt_episode_data_generate(trakt_data) if sickbeard.USE_TRAKT and sickbeard.TRAKT_SYNC_WATCHLIST and sickbeard.TRAKT_REMOVE_WATCHLIST: logger.log( u"Remove episodes, showid: indexerid " + str(show.indexerid) + ", Title " + str(show.name) + " to Traktv Watchlist", logger.DEBUG) if data: notifiers.trakt_notifier.update_watchlist(show, data_episode=data, update="remove") if len(sql_l) > 0: myDB = db.DBConnection() myDB.mass_action(sql_l) # Just want to keep this consistent for failed handling right now releaseName = show_name_helpers.determineReleaseName( self.folder_path, self.nzb_name) if releaseName is not None: failed_history.logSuccess(releaseName) else: self._log(u"Couldn't find release in snatch history", logger.WARNING) # find the destination folder try: proper_path = ep_obj.proper_path() proper_absolute_path = ek.ek(os.path.join, ep_obj.show.location, proper_path) dest_path = ek.ek(os.path.dirname, proper_absolute_path) except exceptions.ShowDirNotFoundException: raise exceptions.PostProcessingFailed( u"Unable to post-process an episode if the show dir doesn't exist, quitting" ) self._log(u"Destination folder for this episode: " + dest_path, logger.DEBUG) # create any folders we need helpers.make_dirs(dest_path) # figure out the base name of the resulting episode file if sickbeard.RENAME_EPISODES: orig_extension = self.file_name.rpartition('.')[-1] new_base_name = ek.ek(os.path.basename, proper_path) new_file_name = new_base_name + '.' + orig_extension else: # if we're not renaming then there's no new base name, we'll just use the existing name new_base_name = None new_file_name = self.file_name # add to anidb if ep_obj.show.is_anime and sickbeard.ANIDB_USE_MYLIST: self._add_to_anidb_mylist(self.file_path) try: # move the episode and associated files to the show dir if self.process_method == "copy": self._copy(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "move": self._move(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "hardlink": self._hardlink( self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) elif self.process_method == "symlink": self._moveAndSymlink( self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES, sickbeard.USE_SUBTITLES and ep_obj.show.subtitles) else: logger.log( u"Unknown process method: " + str(self.process_method), logger.ERROR) raise exceptions.PostProcessingFailed( "Unable to move the files to their new home") except (OSError, IOError): raise exceptions.PostProcessingFailed( "Unable to move the files to their new home") # download subtitles if sickbeard.USE_SUBTITLES and ep_obj.show.subtitles: for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) cur_ep.downloadSubtitles(force=True) # put the new location in the database sql_l = [] for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) sql_l.append(cur_ep.get_sql()) if len(sql_l) > 0: myDB = db.DBConnection() myDB.mass_action(sql_l) # set file modify stamp to show airdate if sickbeard.AIRDATE_EPISODES: for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.airdateModifyStamp() # generate nfo/tbn ep_obj.createMetaFiles() # log it to history history.logDownload(ep_obj, self.file_path, new_ep_quality, self.release_group, new_ep_version) # send notifications notifiers.notify_download( ep_obj._format_pattern('%SN - %Sx%0E - %EN - %QN')) # do the library update for KODI notifiers.kodi_notifier.update_library(ep_obj.show.name) # do the library update for Plex notifiers.plex_notifier.update_library() # do the library update for NMJ # nmj_notifier kicks off its library update when the notify_download is issued (inside notifiers) # do the library update for Synology Indexer notifiers.synoindex_notifier.addFile(ep_obj.location) # do the library update for pyTivo notifiers.pytivo_notifier.update_library(ep_obj) # do the library update for Trakt notifiers.trakt_notifier.update_library(ep_obj) self._run_extra_scripts(ep_obj) return True
def process(self): """ Post-process a given file """ self._log(u'Processing %s%s' % (self.file_path, (u'<br />.. from nzb %s' % str(self.nzb_name), u'')[None is self.nzb_name])) if ek.ek(os.path.isdir, self.file_path): self._log(u'File %s<br />.. seems to be a directory' % self.file_path) return False for ignore_file in self.IGNORED_FILESTRINGS: if ignore_file in self.file_path: self._log(u'File %s<br />.. is ignored type, skipping' % self.file_path) return False # reset per-file stuff self.in_history = False self.anidbEpisode = None # try to find the file info (show, season, episodes, quality) = self._find_info() # if we don't have it then give up if not show: self._log(u'Please add the show to your SickGear then try to post process an episode', logger.WARNING) raise exceptions.PostProcessingFailed() elif None is season or not episodes: self._log(u'Quitting this post process, could not determine what episode this is', logger.DEBUG) return False # retrieve/create the corresponding TVEpisode objects ep_obj = self._get_ep_obj(show, season, episodes) # get the quality of the episode we're processing if common.Quality.UNKNOWN == quality: new_ep_quality = self._get_quality(ep_obj) else: new_ep_quality = quality self._log(u'Using "%s" quality from the snatch history' % common.Quality.qualityStrings[new_ep_quality], logger.DEBUG) # see if it's safe to replace existing episode (is download snatched, PROPER, better quality) if not self._safe_replace(ep_obj, new_ep_quality): # if it's not safe to replace, stop here self._log(u'Quitting this post process', logger.DEBUG) return False # delete the existing file (and company) for cur_ep in [ep_obj] + ep_obj.relatedEps: try: self._delete(cur_ep.location, associated_files=True) # clean up any left over folders if cur_ep.location: helpers.delete_empty_folders(ek.ek(os.path.dirname, cur_ep.location), keep_dir=ep_obj.show.location) except (OSError, IOError): raise exceptions.PostProcessingFailed(u'Unable to delete the existing files') # set the status of the episodes # for curEp in [ep_obj] + ep_obj.relatedEps: # curEp.status = common.Quality.compositeStatus(common.SNATCHED, new_ep_quality) # if the show directory doesn't exist then make it if allowed if not ek.ek(os.path.isdir, ep_obj.show.location) and sickbeard.CREATE_MISSING_SHOW_DIRS: self._log(u'Show directory does not exist, creating it', logger.DEBUG) try: ek.ek(os.mkdir, ep_obj.show.location) # do the library update for synoindex notifiers.synoindex_notifier.addFolder(ep_obj.show.location) except (OSError, IOError): raise exceptions.PostProcessingFailed(u'Unable to create show directory: ' + ep_obj.show.location) # get metadata for the show (but not episode because it hasn't been fully processed) ep_obj.show.writeMetadata(True) # if we're processing an episode of type anime, get the anime version anime_version = (-1, self.anime_version)[ep_obj.show.is_anime and None is not self.anime_version and self.anime_version] # update the ep info before we rename so the quality & release name go into the name properly sql_l = [] for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: if self.release_name: self._log(u'Found release name ' + self.release_name, logger.DEBUG) cur_ep.release_name = self.release_name or '' cur_ep.status = common.Quality.compositeStatus( **({'status': common.DOWNLOADED, 'quality': new_ep_quality}, {'status': common.ARCHIVED, 'quality': new_ep_quality}) [ep_obj.status in common.Quality.SNATCHED_BEST]) cur_ep.release_group = self.release_group or '' cur_ep.is_proper = self.is_proper cur_ep.version = anime_version cur_ep.subtitles = [] cur_ep.subtitles_searchcount = 0 cur_ep.subtitles_lastsearch = '0001-01-01 00:00:00' sql = cur_ep.get_sql() if None is not sql: sql_l.append(sql) if 0 < len(sql_l): my_db = db.DBConnection() my_db.mass_action(sql_l) # Just want to keep this consistent for failed handling right now release_name = show_name_helpers.determineReleaseName(self.folder_path, self.nzb_name) if None is not release_name: failed_history.logSuccess(release_name) else: self._log(u'No release found in snatch history', logger.WARNING) # find the destination folder try: proper_path = ep_obj.proper_path() proper_absolute_path = ek.ek(os.path.join, ep_obj.show.location, proper_path) dest_path = ek.ek(os.path.dirname, proper_absolute_path) except exceptions.ShowDirNotFoundException: raise exceptions.PostProcessingFailed( u'Unable to post process an episode because the show dir does not exist, quitting') self._log(u'Destination folder for this episode is ' + dest_path, logger.DEBUG) # create any folders we need if not helpers.make_dirs(dest_path): raise exceptions.PostProcessingFailed(u'Unable to create destination folder: ' + dest_path) # figure out the base name of the resulting episode file if sickbeard.RENAME_EPISODES: new_base_name = ek.ek(os.path.basename, proper_path) new_file_name = new_base_name + '.' + self.file_name.rpartition('.')[-1] else: # if we're not renaming then there's no new base name, we'll just use the existing name new_base_name = None new_file_name = self.file_name # add to anidb if sickbeard.ANIDB_USE_MYLIST and ep_obj.show.is_anime: self._add_to_anidb_mylist(self.file_path) try: # move the episode and associated files to the show dir args_link = {'file_path': self.file_path, 'new_path': dest_path, 'new_base_name': new_base_name, 'associated_files': sickbeard.MOVE_ASSOCIATED_FILES} args_cpmv = {'subtitles': sickbeard.USE_SUBTITLES and ep_obj.show.subtitles, 'action_tmpl': u' %s<br />.. to %s'} args_cpmv.update(args_link) if 'copy' == self.process_method: self._copy(**args_cpmv) elif 'move' == self.process_method: self._move(**args_cpmv) elif 'hardlink' == self.process_method: self._hardlink(**args_link) elif 'symlink' == self.process_method: self._move_and_symlink(**args_link) else: logger.log(u'Unknown process method: ' + str(self.process_method), logger.ERROR) raise exceptions.PostProcessingFailed(u'Unable to move the files to the new location') except (OSError, IOError): raise exceptions.PostProcessingFailed(u'Unable to move the files to the new location') # download subtitles dosubs = sickbeard.USE_SUBTITLES and ep_obj.show.subtitles # put the new location in the database sql_l = [] for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) if dosubs: cur_ep.downloadSubtitles(force=True) # set file modify stamp to show airdate if sickbeard.AIRDATE_EPISODES: cur_ep.airdateModifyStamp() sql = cur_ep.get_sql() if None is not sql: sql_l.append(sql) if 0 < len(sql_l): my_db = db.DBConnection() my_db.mass_action(sql_l) # generate nfo/tbn ep_obj.createMetaFiles() # log it to history history.logDownload(ep_obj, self.file_path, new_ep_quality, self.release_group, anime_version) # send notifications notifiers.notify_download(ep_obj._format_pattern('%SN - %Sx%0E - %EN - %QN')) # do the library update for XBMC notifiers.xbmc_notifier.update_library(ep_obj.show.name) # do the library update for Kodi notifiers.kodi_notifier.update_library(ep_obj.show.name) # do the library update for Plex notifiers.plex_notifier.update_library(ep_obj) # do the library update for NMJ # nmj_notifier kicks off its library update when the notify_download is issued (inside notifiers) # do the library update for Synology Indexer notifiers.synoindex_notifier.addFile(ep_obj.location) # do the library update for pyTivo notifiers.pytivo_notifier.update_library(ep_obj) # do the library update for Trakt notifiers.trakt_notifier.update_library(ep_obj) self._run_extra_scripts(ep_obj) return True
def process(self): """ Post-process a given file """ self._log(u"Processing " + self.file_path + " (" + str(self.nzb_name) + ")") if ek.ek(os.path.isdir, self.file_path): self._log(u"File " + self.file_path + " seems to be a directory") return False # reset per-file stuff self.in_history = False # try to find the file info (tvdb_id, season, episodes, quality) = self._find_info() # if we don't have it then give up if not tvdb_id or season == None or not episodes: self._log(u"Not enough information to determine what episode this is", logger.Info) self._log(u"Quitting post-processing") return False # retrieve/create the corresponding TVEpisode objects ep_obj = self._get_ep_obj(tvdb_id, season, episodes) # get the quality of the episode we're processing if quality: self._log(u"Snatch history had a quality in it, using that: " + common.Quality.qualityStrings[quality]) new_ep_quality = quality else: new_ep_quality = self._get_quality(ep_obj) logger.log(u"Quality of the processing episode: " + str(new_ep_quality)) # see if this is a priority download (is it snatched, in history, or PROPER) safe_replace = self._safe_replace(ep_obj, new_ep_quality) # set the status of the episodes if not safe_replace: # if it's not priority then we don't want to replace smaller files in case it was a mistake # if there's an existing file that we don't want to replace stop here #return False self._log(u"Quitting post-processing") return False # if the file is priority then we're going to replace it even if it exists else: self._log(u"This download is marked as safe to replace existing file") # delete the existing file (and company) for cur_ep in [ep_obj] + ep_obj.relatedEps: try: self._delete(cur_ep.location, associated_files=True) # clean up any left over folders if cur_ep.location: helpers.delete_empty_folders(ek.ek(os.path.dirname, cur_ep.location), keep_dir=ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed(u"Unable to delete the existing files") # if the show directory doesn't exist then make it if allowed if not ek.ek(os.path.isdir, ep_obj.show._location) and sickbeard.CREATE_MISSING_SHOW_DIRS: self._log(u"Show directory doesn't exist, creating it") try: ek.ek(os.mkdir, ep_obj.show._location) # do the library update for synoindex notifiers.synoindex_notifier.addFolder(ep_obj.show._location) except (OSError, IOError): raise exceptions.PostProcessingFailed(u"Unable to create the show directory: " + ep_obj.show._location) # get metadata for the show (but not episode because it hasn't been fully processed) ep_obj.show.writeMetadata(True) # update the ep info before we rename so the quality & release name go into the name properly for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_release_name = None # use the best possible representation of the release name if self.good_results[self.NZB_NAME]: cur_release_name = self.nzb_name if cur_release_name.lower().endswith('.nzb'): cur_release_name = cur_release_name.rpartition('.')[0] elif self.good_results[self.FILE_NAME]: cur_release_name = self.file_name # take the extension off the filename, it's not needed if '.' in self.file_name: cur_release_name = self.file_name.rpartition('.')[0] elif self.good_results[self.FOLDER_NAME]: cur_release_name = self.folder_name if cur_release_name: self._log("Found release name " + cur_release_name) cur_ep.release_name = cur_release_name else: logger.log(u"good results: " + repr(self.good_results)) cur_ep.status = common.Quality.compositeStatus(common.DOWNLOADED, new_ep_quality) cur_ep.saveToDB() releaseName = show_name_helpers.determineReleaseName(self.folder_path, self.nzb_name) if releaseName is not None: failed_history.logSuccess(releaseName) else: self._log(u"Couldn't find release in snatch history", logger.WARNING) # find the destination folder try: proper_path = ep_obj.proper_path() proper_absolute_path = ek.ek(os.path.join, ep_obj.show.location, proper_path) dest_path = ek.ek(os.path.dirname, proper_absolute_path) except exceptions.ShowDirNotFoundException: raise exceptions.PostProcessingFailed(u"Unable to post-process an episode if the show dir doesn't exist, quitting") self._log(u"Destination folder for this episode: " + dest_path) # create any folders we need if not helpers.make_dirs(dest_path): raise exceptions.PostProcessingFailed(u"Unable to create destination folder: " + dest_path) # figure out the base name of the resulting episode file if sickbeard.RENAME_EPISODES: orig_extension = self.file_name.rpartition('.')[-1] new_base_name = ek.ek(os.path.basename, proper_path) new_file_name = new_base_name + '.' + orig_extension else: # if we're not renaming then there's no new base name, we'll just use the existing name new_base_name = None new_file_name = self.file_name try: # move the episode and associated files to the show dir if sickbeard.KEEP_PROCESSED_DIR: self._copy(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES) else: self._move(self.file_path, dest_path, new_base_name, sickbeard.MOVE_ASSOCIATED_FILES) except (OSError, IOError): raise exceptions.PostProcessingFailed(u"Unable to move the files to destination folder: " + dest_path) # put the new location in the database for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock: cur_ep.location = ek.ek(os.path.join, dest_path, new_file_name) cur_ep.saveToDB() # log it to history history.logDownload(ep_obj, self.file_path, new_ep_quality, self.release_group) # send notifications notifiers.notify_download(ep_obj.prettyName()) # generate nfo/tbn ep_obj.createMetaFiles() ep_obj.saveToDB() # do the library update for XBMC # do the library update for Plex notifiers.update_library(ep_obj) # do the library update for NMJ # nmj_notifier kicks off its library update when the notify_download is issued (inside notifiers) # do the library update for Synology Indexer # do the library update for pyTivo # do the library update for Trakt self._run_extra_scripts(ep_obj) return True