def _parse_string(self, name, skip_scene_detection=False): if not name: return matches = [] bestResult = None for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes: match = cur_regex.match(name) if not match: continue result = ParseResult(name) result.which_regex = {cur_regex_name} result.score = 0 - cur_regex_num named_groups = match.groupdict().keys() if 'series_name' in named_groups: result.series_name = match.group('series_name') if result.series_name: result.series_name = self.clean_series_name( result.series_name) result.score += 1 if 'series_num' in named_groups and match.group('series_num'): result.score += 1 if 'season_num' in named_groups: tmp_season = int(match.group('season_num')) if cur_regex_name == 'bare' and tmp_season in (19, 20): continue if cur_regex_name == 'fov' and tmp_season > 500: continue result.season_number = tmp_season result.score += 1 if 'ep_num' in named_groups: ep_num = self._convert_number(match.group('ep_num')) if 'extra_ep_num' in named_groups and match.group( 'extra_ep_num'): tmp_episodes = range( ep_num, self._convert_number(match.group('extra_ep_num')) + 1) # if len(tmp_episodes) > 6: # continue else: tmp_episodes = [ep_num] result.episode_numbers = tmp_episodes result.score += 3 if 'ep_ab_num' in named_groups: ep_ab_num = self._convert_number(match.group('ep_ab_num')) result.score += 1 if 'extra_ab_ep_num' in named_groups and match.group( 'extra_ab_ep_num'): result.ab_episode_numbers = range( ep_ab_num, self._convert_number(match.group('extra_ab_ep_num')) + 1) result.score += 1 else: result.ab_episode_numbers = [ep_ab_num] if 'air_date' in named_groups: air_date = match.group('air_date') try: result.air_date = parser.parse(air_date, fuzzy=True).date() result.score += 1 except Exception: continue if 'extra_info' in named_groups: tmp_extra_info = match.group('extra_info') # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season if tmp_extra_info and cur_regex_name == 'season_only' and re.search( r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I): continue result.extra_info = tmp_extra_info result.score += 1 if 'release_group' in named_groups: result.release_group = match.group('release_group') result.score += 1 if 'version' in named_groups: # assigns version to anime file if detected using anime regex. Non-anime regex receives -1 version = match.group('version') if version: result.version = version else: result.version = 1 else: result.version = -1 matches.append(result) if len(matches): # pick best match with highest score based on placement bestResult = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score) bestResult.show = self.showObj bestResult.indexerid = self.showObj.indexerid if self.showObj else 0 if not self.naming_pattern: # try and create a show object for this result bestResult.show, bestResult.indexerid = self.get_show( bestResult.series_name) # confirm passed in show object indexer id matches result show object indexer id if self.showObj and bestResult.show: if self.showObj.indexerid == bestResult.show.indexerid: bestResult.show = self.showObj else: bestResult.show = None bestResult.indexerid = 0 elif self.showObj and not bestResult.show and not self.validate_show: bestResult.show = self.showObj # if this is a naming pattern test or result doesn't have a show object then return best result if not bestResult.show or self.naming_pattern: return bestResult # get quality bestResult.quality = Quality.nameQuality(name, bestResult.show.is_anime) new_episode_numbers = [] new_season_numbers = [] new_absolute_numbers = [] # if we have an air-by-date show then get the real season/episode numbers if bestResult.is_air_by_date: airdate = bestResult.air_date.toordinal() dbData = [ x for x in sickrage.app.main_db.get_many( 'tv_episodes', bestResult.show.indexerid) if x['indexer'] == bestResult.show.indexer and x['airdate'] == airdate ] season_number = None episode_numbers = [] if dbData: season_number = int(dbData[0]['season']) episode_numbers = [int(dbData[0]['episode'])] if not season_number or not episode_numbers: try: lINDEXER_API_PARMS = IndexerApi( bestResult.show.indexer).api_params.copy() lINDEXER_API_PARMS[ 'language'] = bestResult.show.lang or sickrage.app.config.indexer_default_language t = IndexerApi(bestResult.show.indexer).indexer( **lINDEXER_API_PARMS) epObj = t[bestResult.show.indexerid].airedOn( bestResult.air_date)[0] season_number = int(epObj["airedseason"]) episode_numbers = [int(epObj["airedepisodenumber"])] except indexer_episodenotfound: if bestResult.in_showlist: sickrage.app.log.warning( "Unable to find episode with date {air_date} for show {show}, " "skipping".format(air_date=bestResult.air_date, show=bestResult.show.name)) episode_numbers = [] except indexer_error as e: sickrage.app.log.warning( "Unable to contact " + IndexerApi(bestResult.show.indexer).name + ": {}".format(e)) episode_numbers = [] for epNo in episode_numbers: s = season_number e = epNo if bestResult.show.is_scene and not skip_scene_detection: (s, e) = get_indexer_numbering(bestResult.show.indexerid, bestResult.show.indexer, season_number, epNo) new_episode_numbers.append(e) new_season_numbers.append(s) elif bestResult.show.is_anime and bestResult.ab_episode_numbers: for epAbsNo in bestResult.ab_episode_numbers: a = epAbsNo if bestResult.show.is_scene: scene_season = get_scene_exception_by_name( bestResult.series_name)[1] a = get_indexer_absolute_numbering( bestResult.show.indexerid, bestResult.show.indexer, epAbsNo, True, scene_season) (s, e ) = bestResult.show.get_all_episodes_from_absolute_number( [a]) new_absolute_numbers.append(a) new_episode_numbers.extend(e) new_season_numbers.append(s) elif bestResult.season_number and bestResult.episode_numbers: for epNo in bestResult.episode_numbers: s = bestResult.season_number e = epNo if bestResult.show.is_scene and not skip_scene_detection: (s, e) = get_indexer_numbering( bestResult.show.indexerid, bestResult.show.indexer, bestResult.season_number, epNo) if bestResult.show.is_anime: a = get_absolute_number_from_season_and_episode( bestResult.show, s, e) if a: new_absolute_numbers.append(a) new_episode_numbers.append(e) new_season_numbers.append(s) # need to do a quick sanity check heregex. It's possible that we now have episodes # from more than one season (by tvdb numbering), and this is just too much # for sickrage, so we'd need to flag it. new_season_numbers = list( set(new_season_numbers)) # remove duplicates if len(new_season_numbers) > 1: raise InvalidNameException( "Scene numbering results episodes from " "seasons %s, (i.e. more than one) and " "sickrage does not support this. " "Sorry." % new_season_numbers) # I guess it's possible that we'd have duplicate episodes too, so lets # eliminate them new_episode_numbers = list(set(new_episode_numbers)) new_episode_numbers.sort() # maybe even duplicate absolute numbers so why not do them as well new_absolute_numbers = list(set(new_absolute_numbers)) new_absolute_numbers.sort() if len(new_absolute_numbers): bestResult.ab_episode_numbers = new_absolute_numbers if len(new_season_numbers) and len(new_episode_numbers): bestResult.episode_numbers = new_episode_numbers bestResult.season_number = new_season_numbers[0] if bestResult.show.is_scene and not skip_scene_detection: sickrage.app.log.debug( "Scene converted parsed result {} into {}".format( bestResult.original_name, bestResult)) # CPU sleep time.sleep(0.02) return bestResult
def _parse_string(self, name): if not name: return matches = [] bestResult = None for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes: match = cur_regex.match(name) if not match: continue result = ParseResult(name) result.which_regex = [cur_regex_name] result.score = 0 - cur_regex_num named_groups = match.groupdict().keys() if 'series_name' in named_groups: result.series_name = match.group('series_name') if result.series_name: result.series_name = self.clean_series_name(result.series_name) result.score += 1 if 'series_num' in named_groups and match.group('series_num'): result.score += 1 if 'season_num' in named_groups: tmp_season = int(match.group('season_num')) if cur_regex_name == 'bare' and tmp_season in (19, 20): continue result.season_number = tmp_season result.score += 1 if 'ep_num' in named_groups: ep_num = self._convert_number(match.group('ep_num')) result.score += 1 if 'extra_ep_num' in named_groups and match.group('extra_ep_num'): result.episode_numbers = range(ep_num, self._convert_number(match.group('extra_ep_num')) + 1) result.score += 1 else: result.episode_numbers = [ep_num] if 'ep_ab_num' in named_groups: ep_ab_num = self._convert_number(match.group('ep_ab_num')) result.score += 1 if 'extra_ab_ep_num' in named_groups and match.group('extra_ab_ep_num'): result.ab_episode_numbers = range(ep_ab_num, self._convert_number(match.group('extra_ab_ep_num')) + 1) result.score += 1 else: result.ab_episode_numbers = [ep_ab_num] if 'air_date' in named_groups: air_date = match.group('air_date') try: result.air_date = parser.parse(air_date, fuzzy=True).date() result.score += 1 except Exception: continue if 'extra_info' in named_groups: tmp_extra_info = match.group('extra_info') # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season if tmp_extra_info and cur_regex_name == 'season_only' and re.search( r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I): continue result.extra_info = tmp_extra_info result.score += 1 if 'release_group' in named_groups: result.release_group = match.group('release_group') result.score += 1 if 'version' in named_groups: # assigns version to anime file if detected using anime regex. Non-anime regex receives -1 version = match.group('version') if version: result.version = version else: result.version = 1 else: result.version = -1 matches.append(result) if len(matches): # pick best match with highest score based on placement bestResult = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score) show = None if not self.naming_pattern: # try and create a show object for this result show = self.get_show(bestResult.series_name, self.tryIndexers) # confirm passed in show object indexer id matches result show object indexer id if show: if self.showObj and show.indexerid != self.showObj.indexerid: show = None bestResult.show = show elif not show and self.showObj: bestResult.show = self.showObj # if this is a naming pattern test or result doesn't have a show object then return best result if not bestResult.show or self.naming_pattern: return bestResult # get quality bestResult.quality = Quality.nameQuality(name, bestResult.show.is_anime) new_episode_numbers = [] new_season_numbers = [] new_absolute_numbers = [] # if we have an air-by-date show then get the real season/episode numbers if bestResult.is_air_by_date: from sickrage.core.databases import main_db airdate = bestResult.air_date.toordinal() sql_result = main_db.MainDB().select( "SELECT season, episode FROM tv_episodes WHERE showid = ? AND indexer = ? AND airdate = ?", [bestResult.show.indexerid, bestResult.show.indexer, airdate]) season_number = None episode_numbers = [] if sql_result: season_number = int(sql_result[0][0]) episode_numbers = [int(sql_result[0][1])] if not season_number or not len(episode_numbers): try: lINDEXER_API_PARMS = srIndexerApi(bestResult.show.indexer).api_params.copy() if bestResult.show.lang: lINDEXER_API_PARMS['language'] = bestResult.show.lang t = srIndexerApi(bestResult.show.indexer).indexer(**lINDEXER_API_PARMS) epObj = t[bestResult.show.indexerid].airedOn(bestResult.air_date)[0] season_number = int(epObj["seasonnumber"]) episode_numbers = [int(epObj["episodenumber"])] except indexer_episodenotfound: sickrage.srCore.srLogger.warning( "Unable to find episode with date " + bestResult.air_date + " for show " + bestResult.show.name + ", skipping") episode_numbers = [] except indexer_error as e: sickrage.srCore.srLogger.warning( "Unable to contact " + srIndexerApi(bestResult.show.indexer).name + ": {}".format( e)) episode_numbers = [] for epNo in episode_numbers: s = season_number e = epNo if bestResult.show.is_scene: (s, e) = get_indexer_numbering(bestResult.show.indexerid, bestResult.show.indexer, season_number, epNo) new_episode_numbers.append(e) new_season_numbers.append(s) elif bestResult.show.is_anime and len(bestResult.ab_episode_numbers): scene_season = get_scene_exception_by_name(bestResult.series_name)[1] for epAbsNo in bestResult.ab_episode_numbers: a = epAbsNo if bestResult.show.is_scene: a = get_indexer_absolute_numbering(bestResult.show.indexerid, bestResult.show.indexer, epAbsNo, True, scene_season) (s, e) = get_all_episodes_from_absolute_number(bestResult.show, [a]) new_absolute_numbers.append(a) new_episode_numbers.extend(e) new_season_numbers.append(s) elif bestResult.season_number and len(bestResult.episode_numbers): for epNo in bestResult.episode_numbers: s = bestResult.season_number e = epNo if bestResult.show.is_scene: (s, e) = get_indexer_numbering(bestResult.show.indexerid, bestResult.show.indexer, bestResult.season_number, epNo) if bestResult.show.is_anime: a = get_absolute_number_from_season_and_episode(bestResult.show, s, e) if a: new_absolute_numbers.append(a) new_episode_numbers.append(e) new_season_numbers.append(s) # need to do a quick sanity check heregex. It's possible that we now have episodes # from more than one season (by tvdb numbering), and this is just too much # for sickrage, so we'd need to flag it. new_season_numbers = list(set(new_season_numbers)) # remove duplicates if len(new_season_numbers) > 1: raise InvalidNameException("Scene numbering results episodes from " "seasons %s, (i.e. more than one) and " "sickrage does not support this. " "Sorry." % new_season_numbers) # I guess it's possible that we'd have duplicate episodes too, so lets # eliminate them new_episode_numbers = list(set(new_episode_numbers)) new_episode_numbers.sort() # maybe even duplicate absolute numbers so why not do them as well new_absolute_numbers = list(set(new_absolute_numbers)) new_absolute_numbers.sort() if len(new_absolute_numbers): bestResult.ab_episode_numbers = new_absolute_numbers if len(new_season_numbers) and len(new_episode_numbers): bestResult.episode_numbers = new_episode_numbers bestResult.season_number = new_season_numbers[0] if bestResult.show.is_scene: sickrage.srCore.srLogger.debug( "Converted parsed result {} into {}".format(bestResult.original_name, bestResult)) # CPU sleep time.sleep(1) return bestResult