def test_HDTV(self): from sickrage.core.common import Quality self.assertEqual( Quality.HDTV, Quality.name_quality("Test.Show.S01E02.720p.HDTV.x264-GROUP")) self.assertEqual( Quality.HDTV, Quality.name_quality("Test.Show.S01E02.HR.WS.PDTV.x264-GROUP"))
def test_FULLHDBLURAY(self): from sickrage.core.common import Quality self.assertEqual( Quality.FULLHDBLURAY, Quality.name_quality("Test.Show.S01E02.1080p.BluRay.x264-GROUP")) self.assertEqual( Quality.FULLHDBLURAY, Quality.name_quality("Test.Show.S01E02.1080p.HDDVD.x264-GROUP"))
def test_FULLHDWEBDL(self): from sickrage.core.common import Quality self.assertEqual( Quality.FULLHDWEBDL, Quality.name_quality("Test.Show.S01E02.1080p.WEB-DL-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.name_quality("Test.Show.S01E02.1080p.WEBRip-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.name_quality( "Test.Show.S01E02.WEBRip.1080p.H.264.AAC.2.0-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.name_quality( "Test.Show.S01E02.WEBRip.1080p.H264.AAC.2.0-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.name_quality( "Test.Show.S01E02.1080p.iTunes.H.264.AAC-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.name_quality( "Test Show S01E02 1080p iTunes H 264 AAC-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.name_quality( "Test_Show_S01E02_1080p_iTunes_H_264_AAC-GROUP"))
def test_RAWHDTV(self): from sickrage.core.common import Quality self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test.Show.S01E02.720p.HDTV.DD5.1.MPEG2-GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test.Show.S01E02.1080i.HDTV.DD2.0.MPEG2-GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test.Show.S01E02.1080i.HDTV.H.264.DD2.0-GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test Show - S01E02 - 1080i HDTV MPA1.0 H.264 - GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test.Show.S01E02.1080i.HDTV.DD.5.1.h264-GROUP"))
def test_HDWEBDL(self): from sickrage.core.common import Qualities from sickrage.core.common import Quality self.assertEqual( Qualities.HDWEBDL, Quality.name_quality("Test.Show.S01E02.720p.WEB-DL-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality("Test.Show.S01E02.720p.WEBRip-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.WEBRip.720p.H.264.AAC.2.0-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.720p.WEB-DL.AAC2.0.H.264-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test Show S01E02 720p WEB-DL AAC2 0 H 264-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test_Show.S01E02_720p_WEB-DL_AAC2.0_H264-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.720p.WEB-DL.AAC2.0.H264-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.720p.iTunes.Rip.H264.AAC-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.720p.AMZN.WEBRip.DDP5.1.x264-GROUP"))
def _get_proper_list(self): """ Walk providers for propers """ session = sickrage.app.main_db.session() propers = {} final_propers = [] search_date = datetime.datetime.today() - datetime.timedelta(days=2) orig_thread_name = threading.currentThread().getName() for show in get_show_list(): wanted = self._get_wanted(show, search_date) if not wanted: sickrage.app.log.debug("Nothing needs to be downloaded for {}, skipping".format(show.name)) continue self._lastProperSearch = self._get_last_proper_search(show.indexer_id) # for each provider get a list of the for providerID, providerObj in sickrage.app.search_providers.sort(randomize=sickrage.app.config.randomize_providers).items(): # check provider type and provider is enabled if not sickrage.app.config.use_nzbs and providerObj.type in [NZBProvider.type, NewznabProvider.type]: continue elif not sickrage.app.config.use_torrents and providerObj.type in [TorrentProvider.type, TorrentRssProvider.type]: continue elif not providerObj.is_enabled: continue threading.currentThread().setName(orig_thread_name + " :: [" + providerObj.name + "]") sickrage.app.log.info("Searching for any new PROPER releases from " + providerObj.name) try: for season, episode in wanted: for x in providerObj.find_propers(show.indexer_id, season, episode): if not re.search(r'(^|[. _-])(proper|repack)([. _-]|$)', x.name, re.I): sickrage.app.log.debug('Found a non-proper, we have caught and skipped it.') continue name = self._generic_name(x.name) if name not in propers: sickrage.app.log.debug("Found new proper: " + x.name) x.provider = providerObj propers[name] = x except AuthException as e: sickrage.app.log.warning("Authentication error: {}".format(e)) continue except Exception as e: sickrage.app.log.debug("Error while searching " + providerObj.name + ", skipping: {}".format(e)) sickrage.app.log.debug(traceback.format_exc()) continue threading.currentThread().setName(orig_thread_name) self._set_last_proper_search(show.indexer_id, datetime.datetime.today().toordinal()) # take the list of unique propers and get it sorted by sorted_propers = sorted(propers.values(), key=operator.attrgetter('date'), reverse=True) for curProper in sorted_propers: try: parse_result = NameParser(False).parse(curProper.name) except InvalidNameException: sickrage.app.log.debug("Unable to parse the filename " + curProper.name + " into a valid episode") continue except InvalidShowException: sickrage.app.log.debug("Unable to parse the filename " + curProper.name + " into a valid show") continue if not parse_result.series_name: continue if not parse_result.episode_numbers: sickrage.app.log.debug("Ignoring " + curProper.name + " because it's for a full season rather than specific episode") continue show = find_show(parse_result.indexer_id) sickrage.app.log.debug("Successful match! Result " + parse_result.original_name + " matched to show " + show.name) # set the indexer_id in the db to the show's indexer_id curProper.indexer_id = parse_result.indexer_id # set the indexer in the db to the show's indexer curProper.indexer = show.indexer # populate our Proper instance curProper.season = parse_result.season_number if parse_result.season_number is not None else 1 curProper.episode = parse_result.episode_numbers[0] curProper.release_group = parse_result.release_group curProper.version = parse_result.version curProper.quality = Quality.name_quality(curProper.name, parse_result.is_anime) curProper.content = None # filter release best_result = pick_best_result(curProper) if not best_result: sickrage.app.log.debug("Proper " + curProper.name + " were rejected by our release filters.") continue # only get anime proper if it has release group and version if show.is_anime: if not best_result.release_group and best_result.version == -1: sickrage.app.log.debug("Proper " + best_result.name + " doesn't have a release group and version, ignoring it") continue # check if we actually want this proper (if it's the right quality) dbData = session.query(MainDB.TVEpisode).filter_by(showid=best_result.indexer_id, season=best_result.season, episode=best_result.episode).one_or_none() if not dbData: continue # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones) old_status, old_quality = Quality.split_composite_status(int(dbData.status)) if old_status not in (DOWNLOADED, SNATCHED) or old_quality != best_result.quality: continue # check if we actually want this proper (if it's the right release group and a higher version) if show.is_anime: old_version = int(dbData.version) old_release_group = dbData.release_group if not -1 < old_version < best_result.version: continue sickrage.app.log.info("Found new anime v" + str(best_result.version) + " to replace existing v" + str(old_version)) if old_release_group != best_result.release_group: sickrage.app.log.info("Skipping proper from release group: {}, does not match existing release " "group: {}".format(best_result.release_group, old_release_group)) continue # if the show is in our list and there hasn't been a proper already added for that particular episode # then add it to our list of propers if best_result.indexer_id != -1 and (best_result.indexer_id, best_result.season, best_result.episode) not in map( operator.attrgetter('indexer_id', 'season', 'episode'), final_propers): sickrage.app.log.info("Found a proper that we need: " + str(best_result.name)) final_propers.append(best_result) return final_propers
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 _parse_string(self, name, skip_scene_detection=False): if not name: return session = sickrage.app.main_db.session() matches = [] best_result = 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) 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 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 = list( 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 if 'ep_ab_num' in named_groups: ep_ab_num = self._convert_number(match.group('ep_ab_num')) if 'extra_ab_ep_num' in named_groups and match.group( 'extra_ab_ep_num'): result.ab_episode_numbers = list( range( ep_ab_num, self._convert_number( match.group('extra_ab_ep_num')) + 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 += cur_regex_num 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 if 'release_group' in named_groups: result.release_group = match.group('release_group') 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 result.score += len([ x for x in result.__dict__ if getattr(result, x, None) is not None ]) matches.append(result) if len(matches): # pick best match with highest score based on placement best_result = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score) show_obj = None best_result.series_id = self.show_obj.series_id if self.show_obj else 0 best_result.series_provider_id = self.show_obj.series_provider_id if self.show_obj else SeriesProviderID.THETVDB if not self.naming_pattern: # try and create a show object for this result result = self.get_show(best_result.series_name) if result and len(result) == 2: best_result.series_id, best_result.series_provider_id = result if best_result.series_id and best_result.series_provider_id: show_obj = find_show(best_result.series_id, best_result.series_provider_id) # if this is a naming pattern test or result doesn't have a show object then return best result if not show_obj or self.naming_pattern: return best_result # get quality best_result.quality = Quality.name_quality(name, show_obj.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 best_result.is_air_by_date: try: dbData = session.query(MainDB.TVEpisode).filter_by( series_id=show_obj.series_id, series_provider_id=show_obj.series_provider_id, airdate=best_result.air_date).one() season_number = int(dbData.season) episode_numbers = [int(dbData.episode)] except (orm.exc.NoResultFound, orm.exc.MultipleResultsFound): season_number = None episode_numbers = [] if not season_number or not episode_numbers: series_provider_language = show_obj.lang or sickrage.app.config.general.series_provider_default_language series_info = show_obj.series_provider.get_series_info( show_obj.series_id, language=series_provider_language) if series_info: ep_obj = series_info.aired_on(best_result.air_date) if not ep_obj: if best_result.in_showlist: sickrage.app.log.warning( f"Unable to find episode with date {best_result.air_date} for show {show_obj.name}, skipping" ) episode_numbers = [] else: season_number = int(ep_obj[0]["seasonNumber"]) episode_numbers = [int(ep_obj[0]["episodeNumber"])] for epNo in episode_numbers: s = season_number e = epNo if show_obj.scene and not skip_scene_detection: (s, e) = get_series_provider_numbering( show_obj.series_id, show_obj.series_provider_id, season_number, epNo) if s != -1: new_season_numbers.append(s) if e != -1: new_episode_numbers.append(e) elif show_obj.is_anime and best_result.ab_episode_numbers: for epAbsNo in best_result.ab_episode_numbers: a = epAbsNo if show_obj.scene: scene_result = show_obj.get_scene_exception_by_name( best_result.series_name) if scene_result: a = get_series_provider_absolute_numbering( show_obj.series_id, show_obj.series_provider_id, epAbsNo, True, scene_result[1]) (s, e) = show_obj.get_all_episodes_from_absolute_number([a]) if a != -1: new_absolute_numbers.append(a) new_season_numbers.append(s) new_episode_numbers.extend(e) elif best_result.season_number and best_result.episode_numbers: for epNo in best_result.episode_numbers: s = best_result.season_number e = epNo if show_obj.scene and not skip_scene_detection: (s, e) = get_series_provider_numbering( show_obj.series_id, show_obj.series_provider_id, best_result.season_number, epNo) if show_obj.is_anime: a = get_absolute_number_from_season_and_episode( show_obj.series_id, show_obj.series_provider_id, s, e) if a not in [-1, None]: new_absolute_numbers.append(a) if s != -1: new_season_numbers.append(s) if e != -1: new_episode_numbers.append(e) # need to do a quick sanity check here. 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( f"Scene numbering results episodes from seasons {new_season_numbers}, (i.e. more than one) and sickrage does not support this. Sorry." ) # 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): best_result.ab_episode_numbers = new_absolute_numbers if len(new_season_numbers) and len(new_episode_numbers): best_result.episode_numbers = new_episode_numbers best_result.season_number = new_season_numbers[0] if show_obj.scene and not skip_scene_detection: sickrage.app.log.debug( f"Scene converted parsed result {best_result.original_name} into {best_result}" ) # CPU sleep time.sleep(0.02) return best_result
def test_SDDVD(self): from sickrage.core.common import Quality self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.DVDRiP.XViD-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.DVDRiP.DiVX-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.DVDRiP.x264-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.DVDRip.WS.XViD-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.DVDRip.WS.DiVX-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.DVDRip.WS.x264-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.BDRIP.XViD-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.BDRIP.DiVX-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.BDRIP.x264-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.BDRIP.WS.XViD-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.BDRIP.WS.DiVX-GROUP")) self.assertEqual( Quality.SDDVD, Quality.name_quality("Test.Show.S01E02.BDRIP.WS.x264-GROUP"))
def test_SDTV(self): from sickrage.core.common import Quality self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.PDTV.XViD-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.PDTV.x264-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.HDTV.XViD-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.HDTV.x264-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.DSR.XViD-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.DSR.x264-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.TVRip.XViD-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.TVRip.x264-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.WEBRip.XViD-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.WEBRip.x264-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.WEB-DL.x264-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.WEB-DL.AAC2.0.H.264-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02 WEB-DL H 264-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02_WEB-DL_H_264-GROUP")) self.assertEqual( Quality.SDTV, Quality.name_quality("Test.Show.S01E02.WEB-DL.AAC2.0.H264-GROUP"))
def test_UNKNOWN(self): from sickrage.core.common import Quality self.assertEqual(Quality.UNKNOWN, Quality.name_quality("Test.Show.S01E02-SICKRAGE"))
def test_FULLHDTV(self): from sickrage.core.common import Quality self.assertEqual( Quality.FULLHDTV, Quality.name_quality("Test.Show.S01E02.1080p.HDTV.x264-GROUP"))
def parse(self, data, mode, **kwargs): """ Parse search results for items. :param data: The raw response from a search :param mode: The current mode used to search, e.g. RSS :return: A list of items found """ results = [] hdtext = [ ' Versione 720p', ' V 720p', ' V 720', ' V HEVC', ' V HEVC', ' V 1080', ' Versione 1080p', ' 720p HEVC', ' Ver 720', ' 720p HEVC', ' 720p' ] with bs4_parser(data) as html: torrent_table = html.find(class_='showrelease_tb') torrent_rows = torrent_table('tr') if torrent_table else [] # Continue only if at least one release is found if len(torrent_rows) < 3: sickrage.app.log.debug( 'Data returned from provider does not contain any torrents' ) return results # Skip column headers for row in torrent_table('tr')[1:]: cells = row('td') if not cells: continue try: title = unidecode(cells[6].text) title = title.replace('·', '').replace(',', '') title = title.replace('by', '-').strip() title = title.strip('-').strip() download_url = cells[1].find('a')['href'] if not all([title, download_url]): continue seeders = try_int(cells[4].text, 1) leechers = try_int(cells[3].text) filename_qt = self._reverse_quality( self._episode_quality(title)) for text in hdtext: title1 = title title = title.replace(text, filename_qt) if title != title1: break if Quality.name_quality(title) == Quality.UNKNOWN: title += filename_qt if self._has_only_subs(title) and not self.subtitle: sickrage.app.log.debug( 'Torrent is only subtitled, skipping: {}'.format( title)) continue if self.engrelease and not self._is_english(title): sickrage.app.log.debug( "Torrent isn't english audio/subtitled, skipping: {} " .format(title)) continue size = -1 results += [{ 'title': title, 'link': download_url, 'size': size, 'seeders': seeders, 'leechers': leechers }] if mode != 'RSS': sickrage.app.log.debug( "Found result: {}".format(title)) except Exception: sickrage.app.log.error('Failed parsing provider') return results