def generate_sample_ep(multi=None, abd=False, sports=False, anime_type=None): # make a fake episode object ep = FakeEpisode(2, 3, 3, "Ep Name") ep.status = Quality.composite_status(EpisodeStatus.DOWNLOADED, Qualities.HDTV) ep.airdate = date(2011, 3, 9) if abd: ep.release_name = 'Show.Name.2011.03.09.HDTV.XviD-RLSGROUP' ep.show.search_format = SearchFormat.AIR_BY_DATE elif sports: ep.release_name = 'Show.Name.2011.03.09.HDTV.XviD-RLSGROUP' ep.show.search_format = SearchFormat.SPORTS else: if anime_type != 3: ep.show.search_format = SearchFormat.ANIME ep.release_name = 'Show.Name.003.HDTV.XviD-RLSGROUP' else: ep.release_name = 'Show.Name.S02E03.HDTV.XviD-RLSGROUP' if multi is not None: ep.name = "Ep Name (1)" if anime_type != 3: ep.show.search_format = SearchFormat.ANIME ep.release_name = 'Show.Name.003-004.HDTV.XviD-RLSGROUP' second_ep = FakeEpisode(2, 4, 4, "Ep Name (2)") second_ep.status = Quality.composite_status( EpisodeStatus.DOWNLOADED, Qualities.HDTV) second_ep.release_name = ep.release_name ep.related_episodes.append(second_ep) else: ep.release_name = 'Show.Name.S02E03E04E05.HDTV.XviD-RLSGROUP' second_ep = FakeEpisode(2, 4, 4, "Ep Name (2)") second_ep.status = Quality.composite_status( EpisodeStatus.DOWNLOADED, Qualities.HDTV) second_ep.release_name = ep.release_name third_ep = FakeEpisode(2, 5, 5, "Ep Name (3)") third_ep.status = Quality.composite_status( EpisodeStatus.DOWNLOADED, Qualities.HDTV) third_ep.release_name = ep.release_name ep.related_episodes.append(second_ep) ep.related_episodes.append(third_ep) return ep
def mark_failed(series_id, series_provider_id, season, episode): """ Mark an episode as failed :param epObj: Episode object to mark as failed :return: empty string """ log_str = "" show_object = find_show(series_id, series_provider_id) if not show_object: return log_str try: episode_object = show_object.get_episode(season, episode) quality = Quality.split_composite_status(episode_object.status)[1] episode_object.status = Quality.composite_status( EpisodeStatus.FAILED, quality) episode_object.save() except EpisodeNotFoundException as e: sickrage.app.log.warning( "Unable to get episode, please set its status manually: {}". format(e)) return log_str
def log_failed(show_id, season, episode, release, provider=None, session=None): """ Log a failed download :param epObj: Episode object :param release: Release group :param provider: Provider used for snatch """ show_object = find_show(show_id, session=session) episode_object = show_object.get_episode(season, episode) status, quality = Quality.split_composite_status(episode_object.status) action = Quality.composite_status(FAILED, quality) History._log_history_item(action, show_id, season, episode, quality, release, provider, session=session)
def __init__(self, season, episode, absolute_number, name): self.name = name self.season = season self.episode = episode self.absolute_number = absolute_number self.airdate = datetime.date(2010, 3, 9) self.status = Quality.composite_status(DOWNLOADED, Quality.SDTV) self.release_name = 'Show.Name.S02E03.HDTV.XviD-RLSGROUP' self.release_group = 'RLSGROUP' self.is_proper = True self.show = FakeShow() self.scene_season = season self.scene_episode = episode self.scene_absolute_number = absolute_number self.related_episodes = []
def log_subtitle(show_id, season, episode, status, subtitle): """ Log download of subtitle :param showid: Showid of download :param season: Show season :param episode: Show episode :param status: Status of download :param subtitleResult: Result object """ resource = subtitle.language.opensubtitles provider = subtitle.provider_name status, quality = Quality.split_composite_status(status) action = Quality.composite_status(SUBTITLED, quality) History._log_history_item(action, show_id, season, episode, quality, resource, provider)
def log_snatch(search_result): """ Log history of snatch :param search_result: search result object """ for episode in search_result.episodes: quality = search_result.quality version = search_result.version provider = search_result.provider.name if search_result.provider else "unknown" action = Quality.composite_status(SNATCHED, search_result.quality) resource = search_result.name release_group = search_result.release_group History._log_history_item(action, search_result.show_id, search_result.season, episode, quality, resource, provider, version, release_group)
def refresh_dir(self): # make sure the show dir is where we think it is unless dirs are created on the fly if not os.path.isdir( self.location ) and not sickrage.app.config.create_missing_show_dirs: return False # load from dir try: self.load_episodes_from_dir() except Exception as e: sickrage.app.log.debug( "Error searching dir for episodes: {}".format(e)) sickrage.app.log.debug(traceback.format_exc()) # run through all locations from DB, check that they exist sickrage.app.log.debug( str(self.indexer_id) + ": Loading all episodes with a location from the database") for curEp in self.episodes: if curEp.location == '': continue curLoc = os.path.normpath(curEp.location) season = int(curEp.season) episode = int(curEp.episode) # if the path doesn't exist or if it's not in our show dir if not os.path.isfile(curLoc) or not os.path.normpath( curLoc).startswith(os.path.normpath(self.location)): # check if downloaded files still exist, update our data if this has changed if not sickrage.app.config.skip_removed_files: # if it used to have a file associated with it and it doesn't anymore then set it to # EP_DEFAULT_DELETED_STATUS if curEp.location and curEp.status in Quality.DOWNLOADED: if sickrage.app.config.ep_default_deleted_status == ARCHIVED: __, oldQuality = Quality.split_composite_status( curEp.status) new_status = Quality.composite_status( ARCHIVED, oldQuality) else: new_status = sickrage.app.config.ep_default_deleted_status sickrage.app.log.debug( "%s: Location for S%02dE%02d doesn't exist, " "removing it and changing our status to %s" % (self.indexer_id, season or 0, episode or 0, statusStrings[new_status])) curEp.status = new_status curEp.subtitles = '' curEp.subtitles_searchcount = 0 curEp.subtitles_lastsearch = 0 curEp.location = '' curEp.hasnfo = False curEp.hastbn = False curEp.release_name = '' else: if curEp.status in Quality.ARCHIVED: __, oldQuality = Quality.split_composite_status( curEp.status) curEp.status = Quality.composite_status( DOWNLOADED, oldQuality) # the file exists, set its modify file stamp if sickrage.app.config.airdate_episodes: curEp.airdateModifyStamp()
def make_ep_from_file(self, filename): if not os.path.isfile(filename): sickrage.app.log.info( str(self.indexer_id) + ": That isn't even a real file dude... " + filename) return None sickrage.app.log.debug( str(self.indexer_id) + ": Creating episode object from " + filename) try: parse_result = NameParser(validate_show=False).parse( filename, skip_scene_detection=True) except InvalidNameException: sickrage.app.log.debug("Unable to parse the filename " + filename + " into a valid episode") return None except InvalidShowException: sickrage.app.log.debug("Unable to parse the filename " + filename + " into a valid show") return None if not len(parse_result.episode_numbers): sickrage.app.log.info("parse_result: " + str(parse_result)) sickrage.app.log.warning("No episode number found in " + filename + ", ignoring it") return None # for now lets assume that any episode in the show dir belongs to that show season = parse_result.season_number if parse_result.season_number is not None else 1 root_ep = None for curEpNum in parse_result.episode_numbers: episode = int(curEpNum) sickrage.app.log.debug("%s: %s parsed to %s S%02dE%02d" % (self.indexer_id, filename, self.name, season or 0, episode or 0)) check_quality_again = False try: episode_obj = self.get_episode(season, episode) except EpisodeNotFoundException: object_session(self).add( TVEpisode( **{ 'showid': self.indexer_id, 'indexer': self.indexer, 'season': season, 'episode': episode, 'location': filename })) object_session(self).commit() episode_obj = self.get_episode(season, episode) # if there is a new file associated with this ep then re-check the quality if episode_obj.location and os.path.normpath( episode_obj.location) != os.path.normpath(filename): sickrage.app.log.debug( "The old episode had a different file associated with it, I will re-check " "the quality based on the new filename " + filename) check_quality_again = True # if the sizes are the same then it's probably the same file old_size = episode_obj.file_size episode_obj.location = filename same_file = old_size and episode_obj.file_size == old_size episode_obj.checkForMetaFiles() if root_ep is None: root_ep = episode_obj else: if episode_obj not in root_ep.related_episodes: root_ep.related_episodes.append(episode_obj) # if it's a new file then if not same_file: episode_obj.release_name = '' # if they replace a file on me I'll make some attempt at re-checking the quality unless I know it's the # same file if check_quality_again and not same_file: new_quality = Quality.name_quality(filename, self.is_anime) sickrage.app.log.debug("Since this file has been renamed") episode_obj.status = Quality.composite_status( DOWNLOADED, new_quality) # check for status/quality changes as long as it's a new file elif not same_file and is_media_file( filename ) and episode_obj.status not in Quality.DOWNLOADED + Quality.ARCHIVED + [ IGNORED ]: old_status, old_quality = Quality.split_composite_status( episode_obj.status) new_quality = Quality.name_quality(filename, self.is_anime) new_status = None # if it was snatched and now exists then set the status correctly if old_status == SNATCHED and old_quality <= new_quality: sickrage.app.log.debug( "STATUS: this ep used to be snatched with quality " + Quality.qualityStrings[old_quality] + " but a file exists with quality " + Quality.qualityStrings[new_quality] + " so I'm setting the status to DOWNLOADED") new_status = DOWNLOADED # if it was snatched proper and we found a higher quality one then allow the status change elif old_status == SNATCHED_PROPER and old_quality < new_quality: sickrage.app.log.debug( "STATUS: this ep used to be snatched proper with quality " + Quality.qualityStrings[old_quality] + " but a file exists with quality " + Quality.qualityStrings[new_quality] + " so I'm setting the status to DOWNLOADED") new_status = DOWNLOADED elif old_status not in (SNATCHED, SNATCHED_PROPER): new_status = DOWNLOADED if new_status is not None: sickrage.app.log.debug( "STATUS: we have an associated file, so setting the status from " + str(episode_obj.status) + " to DOWNLOADED/" + str( Quality.status_from_name(filename, anime=self.is_anime))) episode_obj.status = Quality.composite_status( new_status, new_quality) # creating metafiles on the root should be good enough if root_ep: root_ep.create_meta_files() object_session(self).commit() return root_ep
def snatch_episode(result, end_status=SNATCHED): """ Contains the internal logic necessary to actually "snatch" a result that has been found. :param result: SearchResult instance to be snatched. :param end_status: the episode status that should be used for the episode object once it's snatched. :return: boolean, True on success """ if result is None: return False show_object = find_show(result.show_id) result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickrage.app.config.allow_high_priority: # if it aired recently make it high priority for episode_number in result.episodes: if date.today() - show_object.get_episode( result.season, episode_number).airdate <= timedelta( days=7): result.priority = 1 if re.search(r'(^|[. _-])(proper|repack)([. _-]|$)', result.name, re.I) is not None: end_status = SNATCHED_PROPER # get result content result.content = result.provider.get_content(result.url) dlResult = False if result.type in ("nzb", "nzbdata"): if sickrage.app.config.nzb_method == "blackhole": dlResult = result.provider.download_result(result) elif sickrage.app.config.nzb_method == "sabnzbd": dlResult = SabNZBd.sendNZB(result) elif sickrage.app.config.nzb_method == "nzbget": is_proper = True if end_status == SNATCHED_PROPER else False dlResult = NZBGet.sendNZB(result, is_proper) elif sickrage.app.config.nzb_method == "download_station": client = get_client_instance(sickrage.app.config.nzb_method, client_type='nzb')() dlResult = client.sendNZB(result) else: sickrage.app.log.error("Unknown NZB action specified in config: " + sickrage.app.config.nzb_method) elif result.type in ("torrent", "torznab"): # add public trackers to torrent result if not result.provider.private: result = result.provider.add_trackers(result) if sickrage.app.config.torrent_method == "blackhole": dlResult = result.provider.download_result(result) else: if any([result.content, result.url.startswith('magnet:')]): client = get_client_instance( sickrage.app.config.torrent_method, client_type='torrent')() dlResult = client.send_torrent(result) else: sickrage.app.log.warning("Torrent file content is empty") else: sickrage.app.log.error( "Unknown result type, unable to download it (%r)" % result.type) # no download results found if not dlResult: return False FailedHistory.log_snatch(result) History.log_snatch(result) sickrage.app.alerts.message(_('Episode snatched'), result.name) trakt_data = [] for episode_number in result.episodes: episode_obj = show_object.get_episode(result.season, episode_number) if is_first_best_match(result): episode_obj.status = Quality.composite_status( SNATCHED_BEST, result.quality) else: episode_obj.status = Quality.composite_status( end_status, result.quality) episode_obj.save() # don't notify when we re-download an episode if episode_obj.status not in Quality.DOWNLOADED: try: Notifiers.mass_notify_snatch( episode_obj._format_pattern('%SN - %Sx%0E - %EN - %QN') + " from " + result.provider.name) except Exception: sickrage.app.log.debug("Failed to send snatch notification") trakt_data.append((episode_obj.season, episode_obj.episode)) data = sickrage.app.notifier_providers[ 'trakt'].trakt_episode_data_generate(trakt_data) if sickrage.app.config.use_trakt and sickrage.app.config.trakt_sync_watchlist: if data: sickrage.app.notifier_providers['trakt'].update_watchlist( show_object, data_episode=data, update="add") return True