def _get_ep_obj(self, tvdb_id, season, episodes): show_obj = None self._log(u"Loading show object for tvdb_id "+str(tvdb_id), logger.DEBUG) # find the show in the showlist try: show_obj = helpers.findCertainShow(sickbeard.showList, tvdb_id) except exceptions.MultipleShowObjectsException: raise #TODO: later I'll just log this, for now I want to know about it ASAP if not show_obj: self._log(u"This show isn't in your list, you need to add it to SB before post-processing an episode", logger.ERROR) raise exceptions.PostProcessingFailed() root_ep = None for cur_episode in episodes: episode = int(cur_episode) self._log(u"Retrieving episode object for " + str(season) + "x" + str(episode), logger.DEBUG) # now that we've figured out which episode this file is just load it manually try: curEp = show_obj.getEpisode(season, episode) except exceptions.EpisodeNotFoundException, e: self._log(u"Unable to create episode: "+ex(e), logger.DEBUG) raise exceptions.PostProcessingFailed() if root_ep == None: root_ep = curEp root_ep.relatedEps = [] else: root_ep.relatedEps.append(curEp)
def _get_ep_obj(self, indexer_id, indexer, season, episodes): """ Retrieve the TVEpisode object requested. indexer_id: The indexerid of the show (int) season: The season of the episode (int) episodes: A list of episodes to find (list of ints) If the episode(s) can be found then a TVEpisode object with the correct related eps will be instantiated and returned. If the episode can't be found then None will be returned. """ self._log( u"Loading show object with Indexer ID:[" + str(indexer_id) + "] for Indexer:[" + str(sickbeard.indexerApi(indexer).name) + "]", logger.DEBUG) # find the show in the showlist try: show_obj = helpers.findCertainShow(sickbeard.showList, indexer_id) except exceptions.MultipleShowObjectsException: raise #TODO: later I'll just log this, for now I want to know about it ASAP # if we can't find the show then there's nothing we can really do if not show_obj: self._log( u"This show isn't in your list, you need to add it to SB before post-processing an episode", logger.ERROR) raise exceptions.PostProcessingFailed() root_ep = None for cur_episode in episodes: self._log( u"Retrieving episode object for " + str(season) + "x" + str(cur_episode), logger.DEBUG) # detect and convert scene numbered releases season, cur_episode = sickbeard.scene_numbering.get_indexer_numbering( indexer_id, indexer, season, cur_episode) # now that we've figured out which episode this file is just load it manually try: curEp = show_obj.getEpisode(season, cur_episode) except exceptions.EpisodeNotFoundException, e: self._log(u"Unable to create episode: " + ex(e), logger.DEBUG) raise exceptions.PostProcessingFailed() self._log( u"Episode object has been converted from Scene numbering " + str(curEp.scene_season) + "x" + str(curEp.scene_episode) + " to Indexer numbering" + str(curEp.season) + "x" + str(curEp.episode)) # associate all the episodes together under a single root episode if root_ep == None: root_ep = curEp root_ep.relatedEps = [] elif curEp not in root_ep.relatedEps: root_ep.relatedEps.append(curEp)
def _get_ep_obj(self, tvdb_id, season, episodes, scene=False): """ Retrieve the TVEpisode object requested. tvdb_id: The TVDBID of the show (int) season: The season of the episode (int) episodes: A list of episodes to find (list of ints) If the episode(s) can be found then a TVEpisode object with the correct related eps will be instantiated and returned. If the episode can't be found then None will be returned. """ show_obj = None sceneMsg = "" if scene: sceneMsg = "(scene numbers) " self._log(u"Loading show object for tvdb_id " + str(tvdb_id), logger.DEBUG) # find the show in the showlist try: show_obj = helpers.findCertainShow(sickbeard.showList, tvdb_id) except exceptions.MultipleShowObjectsException: raise #TODO: later I'll just log this, for now I want to know about it ASAP # if we can't find the show then there's nothing we can really do if not show_obj: self._log( u"This show isn't in your list, you need to add it to SB before post-processing an episode", logger.ERROR) raise exceptions.PostProcessingFailed() root_ep = None for cur_episode in episodes: episode = int(cur_episode) self._log( u"Retrieving episode object for " + sceneMsg + str(season) + "x" + str(episode), logger.DEBUG) # now that we've figured out which episode this file is just load it manually try: curEp = show_obj.getEpisode(season, episode, scene=scene) except exceptions.EpisodeNotFoundException, e: self._log(u"Unable to create episode: " + ex(e), logger.DEBUG) raise exceptions.PostProcessingFailed() # associate all the episodes together under a single root episode if root_ep == None: root_ep = curEp if not scene: root_ep.relatedEps = [] else: self._log("Adding a related episode: " + str(curEp.season) + "x" + str(curEp.episode)) root_ep.relatedEps.append(curEp)
def _get_ep_obj(self, show, season, episodes): """ Retrieve the TVEpisode object requested. show: The show object belonging to the show we want to process season: The season of the episode (int) episodes: A list of episodes to find (list of ints) If the episode(s) can be found then a TVEpisode object with the correct related eps will be instantiated and returned. If the episode can't be found then None will be returned. """ root_ep = None for cur_episode in episodes: self._log( u"Retrieving episode object for " + str(season) + "x" + str(cur_episode), logger.DEBUG) # now that we've figured out which episode this file is just load it manually try: curEp = show.getEpisode(season, cur_episode) if not curEp: raise exceptions.EpisodeNotFoundException() except exceptions.EpisodeNotFoundException, e: self._log(u"Unable to create episode: " + ex(e), logger.DEBUG) raise exceptions.PostProcessingFailed() # associate all the episodes together under a single root episode if root_ep == None: root_ep = curEp root_ep.relatedEps = [] elif curEp not in root_ep.relatedEps: root_ep.relatedEps.append(curEp)
def process(self): """ Post-process a given file """ self._log(u"Processing "+self.file_path+" ("+str(self.nzb_name)+")") # 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: 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.DEBUG) 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) except OSError, IOError: raise exceptions.PostProcessingFailed("Unable to delete the existing files")
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 is 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(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], logger.DEBUG) 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), logger.DEBUG) # see if it's safe to replace existing episode (is download snatched, PROPER, better quality) safe_replace = self._safe_replace(ep_obj, new_ep_quality) # if it's not safe to replace, stop here if not safe_replace: self._log(u"Quitting post-processing", logger.DEBUG) return False # if the file is safe to replace 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", 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(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", 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 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: if self.release_name: self._log(u"Found release name " + self.release_name, logger.DEBUG) cur_ep.release_name = self.release_name else: cur_ep.release_name = "" cur_ep.status = common.Quality.compositeStatus(common.DOWNLOADED, new_ep_quality) # 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 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 notifiers download notification if not ep_obj.show.skip_notices: notifiers.notify_download(ep_obj.prettyName()) # generate nfo/tbn ep_obj.createMetaFiles() ep_obj.saveToDB() # send notifiers library update notifiers.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 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: 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.DEBUG) 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.saveToDB() # 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 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( "Unable to move the files to their new home") # 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) # download subtitles if sickbeard.USE_SUBTITLES and ep_obj.show.subtitles: cur_ep.downloadSubtitles() # send notifications notifiers.notify_download(ep_obj.prettyName()) # 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
# 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) except OSError, IOError: raise exceptions.PostProcessingFailed("Unable to delete the existing files") # find the destination folder try: dest_path = self._find_ep_destination_folder(ep_obj) 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) # if the dir doesn't exist (new season folder) then make it if not ek.ek(os.path.isdir, dest_path): self._log(u"Season folder didn't exist, creating it", logger.DEBUG) try: ek.ek(os.mkdir, dest_path) helpers.chmodAsParent(dest_path) except OSError, IOError: raise exceptions.PostProcessingFailed("Unable to create the episode's destination folder: "+dest_path) # update the statuses before we rename so the quality goes into the name properly for cur_ep in [ep_obj] + ep_obj.relatedEps: with cur_ep.lock:
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 " + self.file_path + " (" + str(self.nzb_name) + ")") # 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: 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.DEBUG) 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) # if renaming is turned on then rename the episode (and associated files, if necessary) if sickbeard.RENAME_EPISODES: new_file_name = helpers.sanitizeFileName(ep_obj.prettyName()) try: self._rename(self.file_path, new_file_name, sickbeard.MOVE_ASSOCIATED_FILES) except OSError, IOError: raise exceptions.PostProcessingFailed( "Unable to rename the files") # remember the new name of the file new_file_path = ek.ek( os.path.join, self.folder_path, new_file_name + '.' + self.file_name.rpartition('.')[-1]) self._log(u"After renaming the new file path is " + new_file_path, logger.DEBUG)
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) 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 elif self.good_results[self.FOLDER_NAME]: cur_release_name = self.folder_name