def load_from_nfo(self, location): if not os.path.isdir(self.show.location): sickrage.app.log.info( "{}: The show dir is missing, not bothering to try loading the episode NFO".format( self.show.indexer_id)) return False sickrage.app.log.debug( "{}: Loading episode details from the NFO file associated with {}".format(self.show.indexer_id, location)) if os.path.isfile(location): self.location = location if self.status == UNKNOWN: if is_media_file(self.location): sickrage.app.log.debug("7 Status changes from " + str(self.status) + " to " + str( Quality.status_from_name(self.location, anime=self.show.is_anime))) self.status = Quality.status_from_name(self.location, anime=self.show.is_anime) nfoFile = replace_extension(self.location, "nfo") sickrage.app.log.debug(str(self.show.indexer_id) + ": Using NFO name " + nfoFile) self.hasnfo = False if os.path.isfile(nfoFile): try: showXML = ElementTree(file=nfoFile) except (SyntaxError, ValueError) as e: sickrage.app.log.warning("Error loading the NFO, backing up the NFO and skipping for now: {}".format(e)) try: os.rename(nfoFile, nfoFile + ".old") except Exception as e: sickrage.app.log.warning("Failed to rename your episode's NFO file - you need to delete it or fix it: {}".format(e)) raise NoNFOException("Error in NFO format") for epDetails in showXML.iter('episodedetails'): if (epDetails.findtext('season') is None or int(epDetails.findtext('season')) != self.season) or (epDetails.findtext( 'episode') is None or int(epDetails.findtext('episode')) != self.episode): sickrage.app.log.debug("%s: NFO has an <episodedetails> block for a different episode - wanted S%02dE%02d but got " "S%02dE%02d" % (self.show.indexer_id, self.season or 0, self.episode or 0, int(epDetails.findtext('season')) or 0, int(epDetails.findtext('episode')) or 0)) continue if epDetails.findtext('title') is None or epDetails.findtext('aired') is None: raise NoNFOException("Error in NFO format (missing episode title or airdate)") self.name = epDetails.findtext('title') self.episode = try_int(epDetails.findtext('episode')) self.season = try_int(epDetails.findtext('season')) from sickrage.core.scene_numbering import get_scene_absolute_numbering, get_scene_numbering self.scene_absolute_number = get_scene_absolute_numbering( self.show.indexer_id, self.show.indexer, self.absolute_number, session=object_session(self) ) self.scene_season, self.scene_episode = get_scene_numbering( self.show.indexer_id, self.show.indexer, self.season, self.episode, session=object_session(self) ) self.description = epDetails.findtext('plot') or self.description self.airdate = datetime.date.min if epDetails.findtext('aired'): rawAirdate = [int(x) for x in epDetails.findtext('aired').split("-")] self.airdate = datetime.date(rawAirdate[0], rawAirdate[1], rawAirdate[2]) self.hasnfo = True self.hastbn = False if os.path.isfile(replace_extension(nfoFile, "tbn")): self.hastbn = True object_session(self).safe_commit() return self.hasnfo
def load_from_indexer(self, season=None, episode=None, cache=True, tvapi=None, cachedSeason=None): indexer_name = IndexerApi(self.indexer).name season = (self.season, season)[season is not None] episode = (self.episode, episode)[episode is not None] sickrage.app.log.debug("{}: Loading episode details from {} for episode S{:02d}E{:02d}".format( self.show.indexer_id, indexer_name, season or 0, episode or 0) ) indexer_lang = self.show.lang or sickrage.app.config.indexer_default_language try: if cachedSeason is None: t = tvapi if not t: lINDEXER_API_PARMS = IndexerApi(self.indexer).api_params.copy() lINDEXER_API_PARMS['cache'] = cache lINDEXER_API_PARMS['language'] = indexer_lang if self.show.dvdorder != 0: lINDEXER_API_PARMS['dvdorder'] = True t = IndexerApi(self.indexer).indexer(**lINDEXER_API_PARMS) myEp = t[self.show.indexer_id][season][episode] else: myEp = cachedSeason[episode] except (indexer_error, IOError) as e: sickrage.app.log.debug("{} threw up an error: {}".format(indexer_name, e)) # if the episode is already valid just log it, if not throw it up if self.name: sickrage.app.log.debug("{} timed out but we have enough info from other sources, allowing the error".format(indexer_name)) return False else: sickrage.app.log.error("{} timed out, unable to create the episode".format(indexer_name)) return False except (indexer_episodenotfound, indexer_seasonnotfound): sickrage.app.log.debug("Unable to find the episode on {}, has it been removed?".format(indexer_name)) # if I'm no longer on the Indexers but I once was then delete myself from the DB if self.indexer_id != -1: self.delete_episode() return False self.indexer_id = try_int(safe_getattr(myEp, 'id'), self.indexer_id) if not self.indexer_id: sickrage.app.log.warning("Failed to retrieve ID from " + IndexerApi(self.indexer).name) object_session(self).rollback() object_session(self).safe_commit() self.delete_episode() return False self.name = safe_getattr(myEp, 'episodename', self.name) if not myEp.get('episodename'): sickrage.app.log.info("This episode {} - S{:02d}E{:02d} has no name on {}. " "Setting to an empty string".format(self.show.name, season or 0, episode or 0, indexer_name)) if not myEp.get('absolutenumber'): sickrage.app.log.debug("This episode {} - S{:02d}E{:02d} has no absolute number on {}".format( self.show.name, season or 0, episode or 0, indexer_name)) else: sickrage.app.log.debug("{}: The absolute_number for S{:02d}E{:02d} is: {}".format( self.show.indexer_id, season or 0, episode or 0, myEp["absolutenumber"])) self.absolute_number = try_int(safe_getattr(myEp, 'absolutenumber'), self.absolute_number) self.season = season self.episode = episode from sickrage.core.scene_numbering import get_scene_absolute_numbering, get_scene_numbering self.scene_absolute_number = get_scene_absolute_numbering( self.show.indexer_id, self.show.indexer, self.absolute_number, session=object_session(self) ) self.scene_season, self.scene_episode = get_scene_numbering( self.show.indexer_id, self.show.indexer, self.season, self.episode, session=object_session(self) ) self.description = safe_getattr(myEp, 'overview', self.description) firstaired = safe_getattr(myEp, 'firstaired') or datetime.date.min try: rawAirdate = [int(x) for x in str(firstaired).split("-")] self.airdate = datetime.date(rawAirdate[0], rawAirdate[1], rawAirdate[2]) except (ValueError, IndexError, TypeError): sickrage.app.log.warning("Malformed air date of {} retrieved from {} for ({} - S{:02d}E{:02d})".format( firstaired, indexer_name, self.show.name, season or 0, episode or 0)) # if I'm incomplete on the indexer but I once was complete then just delete myself from the DB for now object_session(self).rollback() object_session(self).safe_commit() self.delete_episode() return False # don't update show status if show dir is missing, unless it's missing on purpose if not os.path.isdir(self.show.location) and not sickrage.app.config.create_missing_show_dirs and not sickrage.app.config.add_shows_wo_dir: sickrage.app.log.info("The show dir %s is missing, not bothering to change the episode statuses since " "it'd probably be invalid" % self.show.location) return False if self.location: sickrage.app.log.debug("%s: Setting status for S%02dE%02d based on status %s and location %s" % (self.show.indexer_id, season or 0, episode or 0, statusStrings[self.status], self.location)) if not os.path.isfile(self.location): if self.airdate >= datetime.date.today() or not self.airdate > datetime.date.min: sickrage.app.log.debug( "Episode airs in the future or has no airdate, marking it %s" % statusStrings[ UNAIRED]) self.status = UNAIRED elif self.status in [UNAIRED, UNKNOWN]: # Only do UNAIRED/UNKNOWN, it could already be snatched/ignored/skipped, or downloaded/archived to # disconnected media sickrage.app.log.debug( "Episode has already aired, marking it %s" % statusStrings[self.show.default_ep_status]) self.status = self.show.default_ep_status if self.season > 0 else SKIPPED # auto-skip specials else: sickrage.app.log.debug( "Not touching status [ %s ] It could be skipped/ignored/snatched/archived" % statusStrings[ self.status]) # if we have a media file then it's downloaded elif is_media_file(self.location): # leave propers alone, you have to either post-process them or manually change them back if self.status not in Quality.SNATCHED_PROPER + Quality.DOWNLOADED + Quality.SNATCHED + Quality.ARCHIVED: sickrage.app.log.debug( "5 Status changes from " + str(self.status) + " to " + str( Quality.status_from_name(self.location))) self.status = Quality.status_from_name(self.location, anime=self.show.is_anime) # shouldn't get here probably else: sickrage.app.log.debug("6 Status changes from " + str(self.status) + " to " + str(UNKNOWN)) self.status = UNKNOWN object_session(self).safe_commit() return True
def loadFromIndexer(self, season=None, episode=None, cache=True, tvapi=None, cachedSeason=None): if season is None: season = self.season if episode is None: episode = self.episode sickrage.LOGGER.debug("%s: Loading episode details from %s for episode S%02dE%02d" % (self.show.indexerid, sickrage.INDEXER_API(self.show.indexer).name, season or 0, episode or 0)) indexer_lang = self.show.lang try: if cachedSeason is None: if tvapi is None: lINDEXER_API_PARMS = sickrage.INDEXER_API(self.indexer).api_params.copy() if not cache: lINDEXER_API_PARMS[b'cache'] = False if indexer_lang: lINDEXER_API_PARMS[b'language'] = indexer_lang if self.show.dvdorder != 0: lINDEXER_API_PARMS[b'dvdorder'] = True t = sickrage.INDEXER_API(self.indexer).indexer(**lINDEXER_API_PARMS) else: t = tvapi myEp = t[self.show.indexerid][season][episode] else: myEp = cachedSeason[episode] except (indexer_error, IOError) as e: sickrage.LOGGER.debug("" + sickrage.INDEXER_API(self.indexer).name + " threw up an error: {}".format(e)) # if the episode is already valid just log it, if not throw it up if self.name: sickrage.LOGGER.debug("" + sickrage.INDEXER_API( self.indexer).name + " timed out but we have enough info from other sources, allowing the error") return else: sickrage.LOGGER.error("" + sickrage.INDEXER_API(self.indexer).name + " timed out, unable to create the episode") return False except (indexer_episodenotfound, indexer_seasonnotfound): sickrage.LOGGER.debug("Unable to find the episode on " + sickrage.INDEXER_API( self.indexer).name + "... has it been removed? Should I delete from db?") # if I'm no longer on the Indexers but I once was then delete myself from the DB if self.indexerid != -1: self.deleteEpisode() return if getattr(myEp, 'episodename', None) is None: sickrage.LOGGER.info("This episode %s - S%02dE%02d has no name on %s. Setting to an empty string" % ( self.show.name, season or 0, episode or 0, sickrage.INDEXER_API(self.indexer).name)) setattr(myEp, 'episodename', '') # # if I'm incomplete on TVDB but I once was complete then just delete myself from the DB for now # if self.indexerid != -1: # self.deleteEpisode() # return False if getattr(myEp, 'absolute_number', None) is None: sickrage.LOGGER.debug("This episode %s - S%02dE%02d has no absolute number on %s" % ( self.show.name, season or 0, episode or 0, sickrage.INDEXER_API(self.indexer).name)) else: sickrage.LOGGER.debug("%s: The absolute_number for S%02dE%02d is: %s " % ( self.show.indexerid, season or 0, episode or 0, myEp[b"absolute_number"])) self.absolute_number = int(myEp[b"absolute_number"]) self.name = getattr(myEp, 'episodename', "") self.season = season self.episode = episode xem_refresh(self.show.indexerid, self.show.indexer) self.scene_absolute_number = get_scene_absolute_numbering( self.show.indexerid, self.show.indexer, self.absolute_number ) self.scene_season, self.scene_episode = get_scene_numbering( self.show.indexerid, self.show.indexer, self.season, self.episode ) self.description = getattr(myEp, 'overview', "") firstaired = getattr(myEp, 'firstaired', None) if not firstaired or firstaired == "0000-00-00": firstaired = str(datetime.date.fromordinal(1)) rawAirdate = [int(x) for x in firstaired.split("-")] try: self.airdate = datetime.date(rawAirdate[0], rawAirdate[1], rawAirdate[2]) except (ValueError, IndexError): sickrage.LOGGER.warning("Malformed air date of %s retrieved from %s for (%s - S%02dE%02d)" % ( firstaired, sickrage.INDEXER_API(self.indexer).name, self.show.name, season or 0, episode or 0)) # if I'm incomplete on the indexer but I once was complete then just delete myself from the DB for now if self.indexerid != -1: self.deleteEpisode() return False # early conversion to int so that episode doesn't get marked dirty self.indexerid = getattr(myEp, 'id', None) if self.indexerid is None: sickrage.LOGGER.error("Failed to retrieve ID from " + sickrage.INDEXER_API(self.indexer).name) if self.indexerid != -1: self.deleteEpisode() return False # don't update show status if show dir is missing, unless it's missing on purpose if not os.path.isdir( self.show._location) and not sickrage.CREATE_MISSING_SHOW_DIRS and not sickrage.ADD_SHOWS_WO_DIR: sickrage.LOGGER.info( "The show dir %s is missing, not bothering to change the episode statuses since it'd probably be invalid" % self.show._location) return if self.location: sickrage.LOGGER.debug("%s: Setting status for S%02dE%02d based on status %s and location %s" % (self.show.indexerid, season or 0, episode or 0, statusStrings[self.status], self.location)) if not os.path.isfile(self.location): if self.airdate >= datetime.date.today() or self.airdate == datetime.date.fromordinal(1): sickrage.LOGGER.debug("Episode airs in the future or has no airdate, marking it %s" % statusStrings[ UNAIRED]) self.status = UNAIRED elif self.status in [UNAIRED, UNKNOWN]: # Only do UNAIRED/UNKNOWN, it could already be snatched/ignored/skipped, or downloaded/archived to disconnected media sickrage.LOGGER.debug( "Episode has already aired, marking it %s" % statusStrings[self.show.default_ep_status]) self.status = self.show.default_ep_status if self.season > 0 else SKIPPED # auto-skip specials else: sickrage.LOGGER.debug( "Not touching status [ %s ] It could be skipped/ignored/snatched/archived" % statusStrings[ self.status]) # if we have a media file then it's downloaded elif isMediaFile(self.location): # leave propers alone, you have to either post-process them or manually change them back if self.status not in Quality.SNATCHED_PROPER + Quality.DOWNLOADED + Quality.SNATCHED + Quality.ARCHIVED: sickrage.LOGGER.debug( "5 Status changes from " + str(self.status) + " to " + str( Quality.statusFromName(self.location))) self.status = Quality.statusFromName(self.location, anime=self.show.is_anime) # shouldn't get here probably else: sickrage.LOGGER.debug("6 Status changes from " + str(self.status) + " to " + str(UNKNOWN)) self.status = UNKNOWN
def loadFromNFO(self, location): if not os.path.isdir(self.show._location): sickrage.LOGGER.info( str( self.show.indexerid) + ": The show dir is missing, not bothering to try loading the episode NFO") return sickrage.LOGGER.debug( str( self.show.indexerid) + ": Loading episode details from the NFO file associated with " + location) self.location = location if self.location != "": if self.status == UNKNOWN: if isMediaFile(self.location): sickrage.LOGGER.debug("7 Status changes from " + str(self.status) + " to " + str( Quality.statusFromName(self.location, anime=self.show.is_anime))) self.status = Quality.statusFromName(self.location, anime=self.show.is_anime) nfoFile = replaceExtension(self.location, "nfo") sickrage.LOGGER.debug(str(self.show.indexerid) + ": Using NFO name " + nfoFile) if os.path.isfile(nfoFile): try: showXML = ElementTree(file=nfoFile) except (SyntaxError, ValueError) as e: sickrage.LOGGER.error("Error loading the NFO, backing up the NFO and skipping for now: {}".format(e)) try: os.rename(nfoFile, nfoFile + ".old") except Exception as e: sickrage.LOGGER.error( "Failed to rename your episode's NFO file - you need to delete it or fix it: {}".format( e)) raise NoNFOException("Error in NFO format") for epDetails in showXML.iter('episodedetails'): if epDetails.findtext('season') is None or int(epDetails.findtext('season')) != self.season or \ epDetails.findtext('episode') is None or int( epDetails.findtext('episode')) != self.episode: sickrage.LOGGER.debug( "%s: NFO has an <episodedetails> block for a different episode - wanted S%02dE%02d but got S%02dE%02d" % ( self.show.indexerid, self.season or 0, self.episode or 0, epDetails.findtext('season') or 0, epDetails.findtext('episode') or 0)) continue if epDetails.findtext('title') is None or epDetails.findtext('aired') is None: raise NoNFOException("Error in NFO format (missing episode title or airdate)") self.name = epDetails.findtext('title') self.episode = int(epDetails.findtext('episode')) self.season = int(epDetails.findtext('season')) xem_refresh(self.show.indexerid, self.show.indexer) self.scene_absolute_number = get_scene_absolute_numbering( self.show.indexerid, self.show.indexer, self.absolute_number ) self.scene_season, self.scene_episode = get_scene_numbering( self.show.indexerid, self.show.indexer, self.season, self.episode ) self.description = epDetails.findtext('plot') if self.description is None: self.description = "" if epDetails.findtext('aired'): rawAirdate = [int(x) for x in epDetails.findtext('aired').split("-")] self.airdate = datetime.date(rawAirdate[0], rawAirdate[1], rawAirdate[2]) else: self.airdate = datetime.date.fromordinal(1) self.hasnfo = True else: self.hasnfo = False if os.path.isfile(replaceExtension(nfoFile, "tbn")): self.hastbn = True else: self.hastbn = False
def loadFromDB(self, season, episode): sickrage.LOGGER.debug("%s: Loading episode details from DB for episode %s S%02dE%02d" % ( self.show.indexerid, self.show.name, season or 0, episode or 0)) sqlResults = main_db.MainDB().select( "SELECT * FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [self.show.indexerid, season, episode]) if len(sqlResults) > 1: raise MultipleEpisodesInDatabaseException("Your DB has two records for the same show somehow.") elif len(sqlResults) == 0: sickrage.LOGGER.debug("%s: Episode S%02dE%02d not found in the database" % ( self.show.indexerid, self.season or 0, self.episode or 0)) return False else: # NAMEIT sickrage.LOGGER.info(u"AAAAA from" + str(self.season)+"x"+str(self.episode) + " -" + self.name + " to " + str(sqlResults[0][b"name"])) if sqlResults[0][b"name"]: self.name = sqlResults[0][b"name"] self.season = season self.episode = episode self.absolute_number = sqlResults[0][b"absolute_number"] self.description = sqlResults[0][b"description"] if not self.description: self.description = "" if sqlResults[0][b"subtitles"] and sqlResults[0][b"subtitles"]: self.subtitles = sqlResults[0][b"subtitles"].split(",") self.subtitles_searchcount = sqlResults[0][b"subtitles_searchcount"] self.subtitles_lastsearch = sqlResults[0][b"subtitles_lastsearch"] self.airdate = datetime.date.fromordinal(int(sqlResults[0][b"airdate"])) # sickrage.LOGGER.debug(u"1 Status changes from " + str(self.status) + " to " + str(sqlResults[0][b"status"])) self.status = int(sqlResults[0][b"status"] or -1) # don't overwrite my location if sqlResults[0][b"location"] and sqlResults[0][b"location"]: self.location = os.path.normpath(sqlResults[0][b"location"]) if sqlResults[0][b"file_size"]: self.file_size = int(sqlResults[0][b"file_size"]) else: self.file_size = 0 self.indexerid = int(sqlResults[0][b"indexerid"]) self.indexer = int(sqlResults[0][b"indexer"]) xem_refresh(self.show.indexerid, self.show.indexer) self.scene_season = tryInt(sqlResults[0][b"scene_season"], 0) self.scene_episode = tryInt(sqlResults[0][b"scene_episode"], 0) self.scene_absolute_number = tryInt(sqlResults[0][b"scene_absolute_number"], 0) if self.scene_absolute_number == 0: self.scene_absolute_number = get_scene_absolute_numbering( self.show.indexerid, self.show.indexer, self.absolute_number ) if self.scene_season == 0 or self.scene_episode == 0: self.scene_season, self.scene_episode = get_scene_numbering( self.show.indexerid, self.show.indexer, self.season, self.episode ) if sqlResults[0][b"release_name"] is not None: self.release_name = sqlResults[0][b"release_name"] if sqlResults[0][b"is_proper"]: self.is_proper = int(sqlResults[0][b"is_proper"]) if sqlResults[0][b"version"]: self.version = int(sqlResults[0][b"version"]) if sqlResults[0][b"release_group"] is not None: self.release_group = sqlResults[0][b"release_group"] self.dirty = False return True