def regexSearch(season=-1): if show_name_helpers.isGoodResult(name, curShow, False, season=season): logger.log(u"Successfully matched " + name + " to " + curShow.name + " with regex", logger.DEBUG) tvdb_id = curShow.tvdbid tvdb_lang = curShow.lang return True return False
def _test_is_good_name(self, name, show): """ Test if name is good :param name: :param show: :return: """ self.assertTrue(show_name_helpers.isGoodResult(name, show))
def searchProviders(show, season, episode=None, manualSearch=False): logger.log(u"Searching for stuff we need from " + show.name + " season " + str(season)) foundResults = {} didSearch = False seasonSearch = False # gather all episodes for season and then pick out the wanted episodes and compare to determin if we want whole season or just a few episodes if episode is None: seasonEps = show.getAllEpisodes(season) wantedEps = [ x for x in seasonEps if show.getOverview(x.status) in (Overview.WANTED, Overview.QUAL) ] if len(seasonEps) == len(wantedEps): seasonSearch = True else: ep_obj = show.getEpisode(season, episode) wantedEps = [ep_obj] for curProvider in providers.sortedProviderList(): if not curProvider.isActive(): continue try: curResults = curProvider.getSearchResults(show, season, wantedEps, seasonSearch, manualSearch) # make a list of all the results for this provider for curEp in curResults: # skip non-tv crap curResults[curEp] = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), curResults[curEp]) if curEp in foundResults: foundResults[curEp] += curResults[curEp] else: foundResults[curEp] = curResults[curEp] except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) continue except Exception, e: logger.log( u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue
def regexSearch(season=-1): if show_name_helpers.isGoodResult(name, curShow, False, season=season): logger.log( u"Successfully matched " + name + " to " + curShow.name + " with regex", logger.DEBUG) tvdb_id = curShow.tvdbid tvdb_lang = curShow.lang return True return False
def filterSearchResults(show, results): foundResults = {} # make a list of all the results for this provider for curEp in results: # skip non-tv crap results[curEp] = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), results[curEp]) if curEp in foundResults: foundResults[curEp] += results[curEp] else: foundResults[curEp] = results[curEp] return foundResults
def searchProviders(show, season, episode=None, manualSearch=False): logger.log(u"Searching for stuff we need from " + show.name + " season " + str(season)) foundResults = {} didSearch = False seasonSearch = False # gather all episodes for season and then pick out the wanted episodes and compare to determin if we want whole season or just a few episodes if episode is None: seasonEps = show.getAllEpisodes(season) wantedEps = [x for x in seasonEps if show.getOverview(x.status) in (Overview.WANTED, Overview.QUAL)] if len(seasonEps) == len(wantedEps): seasonSearch = True else: ep_obj = show.getEpisode(season, episode) wantedEps = [ep_obj] for curProvider in providers.sortedProviderList(): if not curProvider.isActive(): continue try: curResults = curProvider.getSearchResults(show, season, wantedEps, seasonSearch, manualSearch) # make a list of all the results for this provider for curEp in curResults: # skip non-tv crap curResults[curEp] = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), curResults[curEp]) if curEp in foundResults: foundResults[curEp] += curResults[curEp] else: foundResults[curEp] = curResults[curEp] except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) continue except Exception, e: logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue
def findSeason(show, season): logger.log(u"Searching for stuff we need from " + show.name + " season " + str(season)) foundResults = {} didSearch = False for curProvider in providers.sortedProviderList(): if not curProvider.isActive(): continue try: curResults = curProvider.findSeasonResults(show, season) # make a list of all the results for this provider for curEp in curResults: # skip non-tv crap curResults[curEp] = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), curResults[curEp]) if curEp in foundResults: foundResults[curEp] += curResults[curEp] else: foundResults[curEp] = curResults[curEp] except exceptions.AuthException, e: logger.log(u"Authentication error: " + str(e).decode('utf-8'), logger.ERROR) continue except Exception, e: logger.log( u"Error while searching " + curProvider.name + ", skipping: " + str(e).decode('utf-8'), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue
def findSeason(show, season): logger.log(u"Searching for stuff we need from " + show.name + " season " + str(season)) foundResults = {} didSearch = False for curProvider in providers.sortedProviderList(): if not curProvider.isActive(): continue try: curResults = curProvider.findSeasonResults(show, season) # make a list of all the results for this provider for curEp in curResults: # skip non-tv crap curResults[curEp] = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.filterByRequiredWordsReleases(x.name, show.required_words) and show_name_helpers.isGoodResult(x.name, show), curResults[curEp], ) if curEp in foundResults: foundResults[curEp] += curResults[curEp] else: foundResults[curEp] = curResults[curEp] except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) continue except Exception, e: logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue
except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) continue except Exception, e: logger.log( u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue didSearch = True # skip non-tv crap curFoundResults = filter( lambda x: show_name_helpers.filterBadReleases( x.name, episode.show) and show_name_helpers.isGoodResult( x.name, episode.show), curFoundResults) # loop all results and see if any of them are good enough that we can stop searching done_searching = False for cur_result in curFoundResults: done_searching = isFinalResult(cur_result) logger.log( u"Should we stop searching after finding " + cur_result.name + ": " + str(done_searching), logger.DEBUG) if done_searching: break foundResults += curFoundResults # if we did find a result that's good enough to stop then don't continue if done_searching:
continue try: curFoundResults = curProvider.findEpisode(episode, manualSearch=manualSearch) except exceptions.AuthException, e: logger.log(u"Authentication error: "+ex(e), logger.ERROR) continue except Exception, e: logger.log(u"Error while searching "+curProvider.name+", skipping: "+ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue didSearch = True # skip non-tv crap curFoundResults = filter(lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.filterByRequiredWordsReleases(x.name, episode.show.required_words) and show_name_helpers.isGoodResult(x.name, episode.show), curFoundResults) # loop all results and see if any of them are good enough that we can stop searching done_searching = False for cur_result in curFoundResults: done_searching = isFinalResult(cur_result) logger.log(u"Should we stop searching after finding "+cur_result.name+": "+str(done_searching), logger.DEBUG) if done_searching: break foundResults += curFoundResults # if we did find a result that's good enough to stop then don't continue if done_searching: break
except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) continue except Exception, e: logger.log( u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue didSearch = True # skip non-tv crap curFoundResults = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, episode.show), curFoundResults) foundResults += curFoundResults if not didSearch: logger.log( u"No NZB/Torrent providers found or enabled in the sickbeard config. Please check your settings.", logger.ERROR) bestResult = pickBestResult(foundResults) return bestResult def findSeason(show, season):
try: curFoundResults = curProvider.findEpisode(episode, manualSearch=manualSearch) except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) continue except Exception, e: logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue didSearch = True # skip non-tv crap curFoundResults = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, episode.show), curFoundResults, ) # loop all results and see if any of them are good enough that we can stop searching done_searching = False for cur_result in curFoundResults: done_searching = isFinalResult(cur_result) logger.log( u"Should we stop searching after finding " + cur_result.name + ": " + str(done_searching), logger.DEBUG ) if done_searching: break foundResults += curFoundResults
epObjs.append(show.getEpisode(season, curEpNum)) bestSeasonNZB.episodes = epObjs return [bestSeasonNZB] elif not anyWanted: logger.log(u"No eps from this season are wanted at this quality, ignoring the result of "+bestSeasonNZB.name, logger.DEBUG) else: if bestSeasonNZB.provider.providerType == GenericProvider.NZB: logger.log(u"Breaking apart the NZB and adding the individual ones to our results", logger.DEBUG) # if not, break it apart and add them as the lowest priority results individualResults = nzbSplitter.splitResult(bestSeasonNZB) individualResults = filter(lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show, season=season), individualResults) for curResult in individualResults: if len(curResult.episodes) == 1: epNum = curResult.episodes[0].episode elif len(curResult.episodes) > 1: epNum = MULTI_EP_RESULT if epNum in foundResults: foundResults[epNum].append(curResult) else: foundResults[epNum] = [curResult] # If this is a torrent all we can do is leech the entire torrent, user will have to select which eps not do download in his torrent client else:
def findSeason(show, season): myDB = db.DBConnection() allEps = [int(x["episode"]) for x in myDB.select("SELECT episode FROM tv_episodes WHERE showid = ? AND season = ?", [show.tvdbid, season])] logger.log(u"Episode list: "+str(allEps), logger.DEBUG) reallywanted=[] notwanted=[] finalResults = [] for curEpNum in allEps: sqlResults = myDB.select("SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [show.tvdbid, season, curEpNum]) epStatus = int(sqlResults[0]["status"]) if epStatus ==3: reallywanted.append(curEpNum) else: notwanted.append(curEpNum) if notwanted != []: for EpNum in reallywanted: showObj = sickbeard.helpers.findCertainShow(sickbeard.showList, show.tvdbid) episode = showObj.getEpisode(season, EpNum) res=findEpisode(episode, manualSearch=True) snatchEpisode(res) return else: logger.log(u"Searching for stuff we need from "+show.name+" season "+str(season)) foundResults = {} didSearch = False for curProvider in providers.sortedProviderList(): if not curProvider.isActive(): continue try: curResults = curProvider.findSeasonResults(show, season) # make a list of all the results for this provider for curEp in curResults: # skip non-tv crap curResults[curEp] = filter(lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), curResults[curEp]) if curEp in foundResults: foundResults[curEp] += curResults[curEp] else: foundResults[curEp] = curResults[curEp] except exceptions.AuthException, e: logger.log(u"Authentication error: "+ex(e), logger.ERROR) continue except Exception, e: logger.log(u"Error while searching "+curProvider.name+", skipping: "+ex(e), logger.DEBUG) logger.log(traceback.format_exc(), logger.DEBUG) continue didSearch = True
logger.log( u"No eps from this season are wanted at this quality, ignoring the result of " + bestSeasonNZB.name, logger.DEBUG, ) else: if bestSeasonNZB.provider.providerType == GenericProvider.NZB: logger.log(u"Breaking apart the NZB and adding the individual ones to our results", logger.DEBUG) # if not, break it apart and add them as the lowest priority results individualResults = nzbSplitter.splitResult(bestSeasonNZB) individualResults = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show, season=season), individualResults, ) for curResult in individualResults: if len(curResult.episodes) == 1: epNum = curResult.episodes[0].episode elif len(curResult.episodes) > 1: epNum = MULTI_EP_RESULT if epNum in foundResults[provider.name]: foundResults[provider.name][epNum].append(curResult) else: foundResults[provider.name][epNum] = [curResult] # If this is a torrent all we can do is leech the entire torrent, user will have to select which eps not do download in his torrent client
def _addCacheEntry(self, name, url, season=None, episodes=None, tvdb_id=0, tvrage_id=0, quality=None, extraNames=[]): myDB = self._getDB() parse_result = None # if we don't have complete info then parse the filename to get it for curName in [name] + extraNames: try: myParser = NameParser() parse_result = myParser.parse(curName) except InvalidNameException: logger.log(u"Unable to parse the filename "+curName+" into a valid episode", logger.DEBUG) continue if not parse_result: logger.log(u"Giving up because I'm unable to parse this name: "+name, logger.DEBUG) return False if not parse_result.series_name: logger.log(u"No series name retrieved from "+name+", unable to cache it", logger.DEBUG) return False tvdb_lang = None # if we need tvdb_id or tvrage_id then search the DB for them if not tvdb_id or not tvrage_id: # if we have only the tvdb_id, use the database if tvdb_id: showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id) if showObj: tvrage_id = showObj.tvrid tvdb_lang = showObj.lang else: logger.log(u"We were given a TVDB id "+str(tvdb_id)+" but it doesn't match a show we have in our list, so leaving tvrage_id empty", logger.DEBUG) tvrage_id = 0 # if we have only a tvrage_id then use the database elif tvrage_id: showObj = helpers.findCertainTVRageShow(sickbeard.showList, tvrage_id) if showObj: tvdb_id = showObj.tvdbid tvdb_lang = showObj.lang else: logger.log(u"We were given a TVRage id "+str(tvrage_id)+" but it doesn't match a show we have in our list, so leaving tvdb_id empty", logger.DEBUG) tvdb_id = 0 # if they're both empty then fill out as much info as possible by searching the show name else: # check the name cache and see if we already know what show this is logger.log(u"Checking the cache to see if we already know the tvdb id of "+parse_result.series_name, logger.DEBUG) tvdb_id = name_cache.retrieveNameFromCache(parse_result.series_name) # remember if the cache lookup worked or not so we know whether we should bother updating it later if tvdb_id == None: logger.log(u"No cache results returned, continuing on with the search", logger.DEBUG) from_cache = False else: logger.log(u"Cache lookup found "+repr(tvdb_id)+", using that", logger.DEBUG) from_cache = True # if the cache failed, try looking up the show name in the database if tvdb_id == None: logger.log(u"Trying to look the show up in the show database", logger.DEBUG) showResult = helpers.searchDBForShow(parse_result.series_name) if showResult: logger.log(parse_result.series_name+" was found to be show "+showResult[1]+" ("+str(showResult[0])+") in our DB.", logger.DEBUG) tvdb_id = showResult[0] # if the DB lookup fails then do a comprehensive regex search if tvdb_id == None: logger.log(u"Couldn't figure out a show name straight from the DB, trying a regex search instead", logger.DEBUG) for curShow in sickbeard.showList: if show_name_helpers.isGoodResult(name, curShow, False): logger.log(u"Successfully matched "+name+" to "+curShow.name+" with regex", logger.DEBUG) tvdb_id = curShow.tvdbid tvdb_lang = curShow.lang break # if tvdb_id was anything but None (0 or a number) then if not from_cache: name_cache.addNameToCache(parse_result.series_name, tvdb_id) # if we came out with tvdb_id = None it means we couldn't figure it out at all, just use 0 for that if tvdb_id == None: tvdb_id = 0 # if we found the show then retrieve the show object if tvdb_id: showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id) if showObj: tvrage_id = showObj.tvrid tvdb_lang = showObj.lang # if we weren't provided with season/episode information then get it from the name that we parsed if not season: season = parse_result.season_number if parse_result.season_number != None else 1 if not episodes: episodes = parse_result.episode_numbers # if we have an air-by-date show then get the real season/episode numbers if parse_result.air_by_date and tvdb_id: try: # There's gotta be a better way of doing this but we don't wanna # change the language value elsewhere ltvdb_api_parms = sickbeard.TVDB_API_PARMS.copy() if not (tvdb_lang == "" or tvdb_lang == "en" or tvdb_lang == None): ltvdb_api_parms['language'] = tvdb_lang t = tvdb_api.Tvdb(**ltvdb_api_parms) epObj = t[tvdb_id].airedOn(parse_result.air_date)[0] season = int(epObj["seasonnumber"]) episodes = [int(epObj["episodenumber"])] except tvdb_exceptions.tvdb_episodenotfound: logger.log(u"Unable to find episode with date "+str(parse_result.air_date)+" for show "+parse_result.series_name+", skipping", logger.WARNING) return False except tvdb_exceptions.tvdb_error, e: logger.log(u"Unable to contact TVDB: "+ex(e), logger.WARNING) return False
elif not anyWanted: logger.log( u"No eps from this season are wanted at this quality, ignoring the result of " + bestSeasonNZB.name, logger.DEBUG) else: if bestSeasonNZB.provider.providerType == GenericProvider.NZB: logger.log(u"Breaking apart the NZB and adding the individual ones to our results", logger.DEBUG) # if not, break it apart and add them as the lowest priority results individualResults = nzbSplitter.splitResult(bestSeasonNZB) individualResults = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), individualResults) for curResult in individualResults: if len(curResult.episodes) == 1: epNum = curResult.episodes[0].episode elif len(curResult.episodes) > 1: epNum = MULTI_EP_RESULT if epNum in foundResults: foundResults[epNum].append(curResult) else: foundResults[epNum] = [curResult] # If this is a torrent all we can do is leech the entire torrent, user will have to select which eps not do download in his torrent client else:
def searchProviders(show, season, episodes, manualSearch=False): foundResults = {} finalResults = [] # check if we want to search for season packs instead of just season/episode seasonSearch = False if not manualSearch: seasonEps = show.getAllEpisodes(season) if len(seasonEps) == len(episodes): seasonSearch = True providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()] if not len(providers): logger.log(u"No NZB/Torrent providers found or enabled in the sickrage config. Please check your settings.", logger.ERROR) return origThreadName = threading.currentThread().name for providerNum, provider in enumerate(providers): if provider.anime_only and not show.is_anime: logger.log(u"" + str(show.name) + " is not an anime skiping ...") continue threading.currentThread().name = origThreadName + " :: [" + provider.name + "]" foundResults.setdefault(provider.name, {}) searchCount = 0 search_mode = 'eponly' if seasonSearch and provider.search_mode == 'sponly': search_mode = provider.search_mode while (True): searchCount += 1 if search_mode == 'sponly': logger.log(u"Searching for " + show.name + " Season " + str(season) + " pack") else: logger.log(u"Searching for episodes we need from " + show.name + " Season " + str(season)) try: searchResults = provider.findSearchResults(show, season, episodes, search_mode, manualSearch) except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) break except Exception, e: logger.log(u"Error while searching " + provider.name + ", skipping: " + ex(e), logger.ERROR) break if len(searchResults): # make a list of all the results for this provider for curEp in searchResults: # skip non-tv crap searchResults[curEp] = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show, season=season), searchResults[curEp]) if curEp in foundResults: foundResults[provider.name][curEp] += searchResults[curEp] else: foundResults[provider.name][curEp] = searchResults[curEp] break elif not provider.search_fallback or searchCount == 2: break if search_mode == 'sponly': logger.log(u"FALLBACK EPISODE SEARCH INITIATED ...") search_mode = 'eponly' else: logger.log(u"FALLBACK SEASON PACK SEARCH INITIATED ...") search_mode = 'sponly'
u"No eps from this season are wanted at this quality, ignoring the result of " + bestSeasonNZB.name, logger.DEBUG) else: if bestSeasonNZB.provider.providerType == GenericProvider.NZB: logger.log( u"Breaking apart the NZB and adding the individual ones to our results", logger.DEBUG) # if not, break it apart and add them as the lowest priority results individualResults = nzbSplitter.splitResult(bestSeasonNZB) individualResults = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), individualResults) for curResult in individualResults: if len(curResult.episodes) == 1: epNum = curResult.episodes[0].episode elif len(curResult.episodes) > 1: epNum = MULTI_EP_RESULT if epNum in foundResults: foundResults[epNum].append(curResult) else: foundResults[epNum] = [curResult] # If this is a torrent all we can do is leech the entire torrent, user will have to select which eps not do download in his torrent client else:
def _addCacheEntry(self, name, url, quality=None): indexerid = None in_cache = False # if we don't have complete info then parse the filename to get it try: myParser = NameParser() parse_result = myParser.parse(name).convert() except InvalidNameException: logger.log(u"Unable to parse the filename " + name + " into a valid episode", logger.DEBUG) return None if not parse_result: logger.log(u"Giving up because I'm unable to parse this name: " + name, logger.DEBUG) return None if not parse_result.series_name: logger.log(u"No series name retrieved from " + name + ", unable to cache it", logger.DEBUG) return None cacheResult = sickbeard.name_cache.retrieveNameFromCache(parse_result.series_name) if cacheResult: in_cache = True indexerid = int(cacheResult) elif cacheResult == 0: return None if not indexerid: showResult = helpers.searchDBForShow(parse_result.series_name) if showResult: indexerid = int(showResult[0]) if not indexerid: for curShow in sickbeard.showList: if show_name_helpers.isGoodResult(name, curShow, False): indexerid = curShow.indexerid break showObj = None if indexerid: showObj = helpers.findCertainShow(sickbeard.showList, indexerid) if not showObj: logger.log(u"No match for show: [" + parse_result.series_name + "], not caching ...", logger.DEBUG) sickbeard.name_cache.addNameToCache(parse_result.series_name, 0) return None season = episodes = None if parse_result.air_by_date or parse_result.sports: myDB = db.DBConnection() airdate = parse_result.air_date.toordinal() or parse_result.sports_event_date.toordinal() sql_results = myDB.select( "SELECT season, episode FROM tv_episodes WHERE showid = ? AND indexer = ? AND airdate = ?", [indexerid, showObj.indexer, airdate]) if sql_results > 0: season = int(sql_results[0]["season"]) episodes = [int(sql_results[0]["episode"])] else: season = parse_result.season_number if parse_result.season_number != None else 1 episodes = parse_result.episode_numbers if season and episodes: # store episodes as a seperated string episodeText = "|" + "|".join(map(str, episodes)) + "|" # get the current timestamp curTimestamp = int(time.mktime(datetime.datetime.today().timetuple())) # get quality of release if quality is None: quality = Quality.sceneQuality(name) if not isinstance(name, unicode): name = unicode(name, 'utf-8') logger.log(u"Added RSS item: [" + name + "] to cache: [" + self.providerID + "]", logger.DEBUG) if not in_cache: sickbeard.name_cache.addNameToCache(parse_result.series_name, indexerid) return [ "INSERT INTO [" + self.providerID + "] (name, season, episodes, indexerid, url, time, quality) VALUES (?,?,?,?,?,?,?)", [name, season, episodeText, indexerid, url, curTimestamp, quality]]
def findSeason(show, season): myDB = db.DBConnection() allEps = [int(x["episode"]) for x in myDB.select("SELECT episode FROM tv_episodes WHERE showid = ? AND season = ?", [show.tvdbid, season])] logger.log(u"Episode list: "+str(allEps), logger.DEBUG) reallywanted=[] notwanted=[] finalResults = [] for curEpNum in allEps: sqlResults = myDB.select("SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [show.tvdbid, season, curEpNum]) epStatus = int(sqlResults[0]["status"]) if epStatus ==3: reallywanted.append(curEpNum) else: notwanted.append(curEpNum) if notwanted != []: for EpNum in reallywanted: showObj = sickbeard.helpers.findCertainShow(sickbeard.showList, show.tvdbid) episode = showObj.getEpisode(season, EpNum) finalResults.append(findEpisode(episode, manualSearch=True)) return finalResults else: logger.log(u"Searching for stuff we need from "+show.name+" season "+str(season)) foundResults = {} didSearch = False for curProvider in providers.sortedProviderList(): if not curProvider.isActive(): continue try: curResults = curProvider.findSeasonResults(show, season) # make a list of all the results for this provider for curEp in curResults: # skip non-tv crap curResults[curEp] = filter(lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), curResults[curEp]) if curEp in foundResults: foundResults[curEp] += curResults[curEp] else: foundResults[curEp] = curResults[curEp] except exceptions.AuthException, e: logger.log(u"Authentication error: "+ex(e), logger.ERROR) continue except Exception, e: logger.log(u"Error while searching "+curProvider.name+", skipping: "+ex(e), logger.DEBUG) logger.log(traceback.format_exc(), logger.DEBUG) continue didSearch = True
def findEpisode(episode, manualSearch=False): logger.log(u"Searching for " + episode.prettyName(True)) foundResults = [] didSearch = False for curProvider in providers.sortedProviderList(): if not curProvider.isActive(): continue # we check our results after every search string # this is done because in the future we will have a ordered list of all show aliases and release_group aliases # ordered by success rate ... # lets get all search strings # we use the method from the curProvider to accommodate for the internal join functions # this way we do not break the special abilities of the providers e.g. nzbmatrix searchStrings = curProvider.get_episode_search_strings(episode) logger.log("All search string permutations (" + curProvider.name + "):" + str(searchStrings)) """ try: searchStrings = list(set(searchStrings)) except TypeError: pass """ done_searching = False for searchString in searchStrings: try: curFoundResults = curProvider.findEpisode(episode, manualSearch=manualSearch, searchString=searchString) except exceptions.AuthException, e: logger.log(u"Authentication error: "+ex(e), logger.ERROR) break # break the while loop except Exception, e: logger.log(u"Error while searching "+curProvider.name+", skipping: "+ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) break # break the while loop didSearch = True # skip non-tv crap curFoundResults = filter(lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, episode.show, season=episode.season), curFoundResults) # loop all results and see if any of them are good enough that we can stop searching for cur_result in curFoundResults: done_searching = isFinalResult(cur_result) logger.log(u"Should we stop searching after finding "+cur_result.name+": "+str(done_searching), logger.DEBUG) if done_searching: break # if we are searching an anime we are a little more loose # this means we check every turn for a possible result # in contrast the isFinalResultlooks function looks for a perfect result (best quality) # but this will accept any result that would have been picked in the end -> pickBestResult # and then stop and use that if episode.show.is_anime: logger.log(u"We are searching an anime. i am checking if we got a good result with search provider "+curProvider.name, logger.DEBUG) bestResult = pickBestResult(curFoundResults, show=episode.show) if bestResult: return bestResult foundResults += curFoundResults # if we did find a result that's good enough to stop then don't continue # this breaks the turn loop if done_searching: break
u"No eps from this season are wanted at this quality, ignoring the result of " + bestSeasonNZB.name, logger.DEBUG) else: if bestSeasonNZB.provider.providerType == GenericProvider.NZB: logger.log( u"Breaking apart the NZB and adding the individual ones to our results", logger.DEBUG) # if not, break it apart and add them as the lowest priority results individualResults = nzbSplitter.splitResult(bestSeasonNZB) individualResults = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show, season=season ), individualResults) for curResult in individualResults: if len(curResult.episodes) == 1: epNum = curResult.episodes[0].episode elif len(curResult.episodes) > 1: epNum = MULTI_EP_RESULT if epNum in foundResults: foundResults[epNum].append(curResult) else: foundResults[epNum] = [curResult] # If this is a torrent all we can do is leech the entire torrent, user will have to select which eps not do download in his torrent client else:
class ProperFinder(): def __init__(self): self.amActive = False self.updateInterval = datetime.timedelta(hours=1) check_propers_interval = {'15m': 15, '45m': 45, '90m': 90, '4h': 4*60, 'daily': 24*60} for curInterval in ('15m', '45m', '90m', '4h', 'daily'): if sickbeard.CHECK_PROPERS_INTERVAL == curInterval: self.updateInterval = datetime.timedelta(minutes = check_propers_interval[curInterval]) def run(self, force=False): if not sickbeard.DOWNLOAD_PROPERS: return # look for propers every night at 1 AM updateTime = datetime.time(hour=1) logger.log(u"Checking proper time", logger.DEBUG) hourDiff = datetime.datetime.today().time().hour - updateTime.hour dayDiff = (datetime.date.today() - self._get_lastProperSearch()).days if sickbeard.CHECK_PROPERS_INTERVAL == "daily" and not force: # if it's less than an interval after the update time then do an update if not (hourDiff >= 0 and hourDiff < self.updateInterval.seconds / 3600 or dayDiff >= 1): return logger.log(u"Beginning the search for new propers") self.amActive = True propers = self._getProperList() if propers: self._downloadPropers(propers) self._set_lastProperSearch(datetime.datetime.today().toordinal()) msg = u"Completed the search for new propers, next check " if sickbeard.CHECK_PROPERS_INTERVAL == "daily": logger.log(u"%sat 1am tomorrow" % msg) else: logger.log(u"%sin ~%s" % (msg, sickbeard.CHECK_PROPERS_INTERVAL)) self.amActive = False def _getProperList(self): propers = {} # for each provider get a list of the origThreadName = threading.currentThread().name providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()] for curProvider in providers: threading.currentThread().name = origThreadName + " :: [" + curProvider.name + "]" search_date = datetime.datetime.today() - datetime.timedelta(days=2) logger.log(u"Searching for any new PROPER releases from " + curProvider.name) try: curPropers = curProvider.findPropers(search_date) except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) continue # if they haven't been added by a different provider than add the proper to the list for x in curPropers: name = self._genericName(x.name) if not name in propers: logger.log(u"Found new proper: " + x.name, logger.DEBUG) x.provider = curProvider propers[name] = x # reset thread name back to original threading.currentThread().name = origThreadName # take the list of unique propers and get it sorted by sortedPropers = sorted(propers.values(), key=operator.attrgetter('date'), reverse=True) finalPropers = [] for curProper in sortedPropers: in_cache = False try: myParser = NameParser(False) parse_result = myParser.parse(curProper.name) except InvalidNameException: logger.log(u"Unable to parse the filename " + curProper.name + " into a valid episode", logger.DEBUG) continue if not parse_result.series_name: continue cacheResult = sickbeard.name_cache.retrieveNameFromCache(parse_result.series_name) if cacheResult: in_cache = True curProper.indexerid = int(cacheResult) elif cacheResult == 0: return None if not curProper.indexerid: showResult = helpers.searchDBForShow(parse_result.series_name) if showResult: curProper.indexerid = int(showResult[0]) if not curProper.indexerid: for curShow in sickbeard.showList: if show_name_helpers.isGoodResult(curProper.name, curShow, False): curProper.indexerid = curShow.indexerid break showObj = None if curProper.indexerid: showObj = helpers.findCertainShow(sickbeard.showList, curProper.indexerid) if not showObj: sickbeard.name_cache.addNameToCache(parse_result.series_name, 0) continue if not in_cache: sickbeard.name_cache.addNameToCache(parse_result.series_name, curProper.indexerid) # scene numbering -> indexer numbering parse_result = parse_result.convert(showObj) if not parse_result.episode_numbers: logger.log( u"Ignoring " + curProper.name + " because it's for a full season rather than specific episode", logger.DEBUG) continue # populate our Proper instance if parse_result.air_by_date or parse_result.sports: curProper.season = -1 curProper.episode = parse_result.air_date or parse_result.sports_event_date else: curProper.season = parse_result.season_number if parse_result.season_number != None else 1 curProper.episode = parse_result.episode_numbers[0] curProper.quality = Quality.nameQuality(curProper.name) # for each show in our list for curShow in sickbeard.showList: genericName = self._genericName(parse_result.series_name) # get the scene name masks sceneNames = set(show_name_helpers.makeSceneShowSearchStrings(curShow)) # for each scene name mask for curSceneName in sceneNames: # if it matches if genericName == self._genericName(curSceneName): logger.log( u"Successful match! Result " + parse_result.series_name + " matched to show " + curShow.name, logger.DEBUG) # set the indexerid in the db to the show's indexerid curProper.indexerid = curShow.indexerid # set the indexer in the db to the show's indexer curProper.indexer = curShow.indexer # since we found it, break out break # if we found something in the inner for loop break out of this one if curProper.indexerid != -1: break if not show_name_helpers.filterBadReleases(curProper.name): logger.log(u"Proper " + curProper.name + " isn't a valid scene release that we want, igoring it", logger.DEBUG) continue showObj = helpers.findCertainShow(sickbeard.showList, curProper.indexerid) if not showObj: logger.log(u"Unable to find the show with indexerID " + str(curProper.indexerid), logger.ERROR) continue if showObj.rls_ignore_words and search.filter_release_name(curProper.name, showObj.rls_ignore_words): logger.log(u"Ignoring " + curProper.name + " based on ignored words filter: " + showObj.rls_ignore_words, logger.MESSAGE) continue if showObj.rls_require_words and not search.filter_release_name(curProper.name, showObj.rls_require_words): logger.log(u"Ignoring " + curProper.name + " based on required words filter: " + showObj.rls_require_words, logger.MESSAGE) continue # if we have an air-by-date show then get the real season/episode numbers if (parse_result.air_by_date or parse_result.sports_event_date) and curProper.indexerid: logger.log( u"Looks like this is an air-by-date or sports show, attempting to convert the date to season/episode", logger.DEBUG) airdate = curProper.episode.toordinal() myDB = db.DBConnection() sql_result = myDB.select( "SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?", [curProper.indexerid, curProper.indexer, airdate]) if sql_result: curProper.season = int(sql_result[0][0]) curProper.episodes = [int(sql_result[0][1])] else: logger.log(u"Unable to find episode with date " + str( curProper.episode) + " for show " + parse_result.series_name + ", skipping", logger.WARNING) continue # check if we actually want this proper (if it's the right quality) sqlResults = db.DBConnection().select( "SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [curProper.indexerid, curProper.season, curProper.episode]) if not sqlResults: continue oldStatus, oldQuality = Quality.splitCompositeStatus(int(sqlResults[0]["status"])) # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones) if oldStatus not in (DOWNLOADED, SNATCHED) or oldQuality != curProper.quality: 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 curProper.indexerid != -1 and (curProper.indexerid, curProper.season, curProper.episode) not in map( operator.attrgetter('indexerid', 'season', 'episode'), finalPropers): logger.log(u"Found a proper that we need: " + str(curProper.name)) finalPropers.append(curProper) return finalPropers
def findEpisode(episode, manualSearch=False): logger.log(u"Searching for " + episode.prettyName(True)) foundResults = [] didSearch = False for curProvider in providers.sortedProviderList(): if not curProvider.isActive(): continue # we check our results after every search string # this is done because in the future we will have a ordered list of all show aliases and release_group aliases # ordered by success rate ... # lets get all search strings # we use the method from the curProvider to accommodate for the internal join functions # this way we do not break the special abilities of the providers e.g. nzbmatrix searchStrings = curProvider.get_episode_search_strings(episode) logger.log("All search string permutations (" + curProvider.name + "):" + str(searchStrings)) """ try: searchStrings = list(set(searchStrings)) except TypeError: pass """ done_searching = False for searchString in searchStrings: try: curFoundResults = curProvider.findEpisode( episode, manualSearch=manualSearch, searchString=searchString) except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) break # break the while loop except Exception, e: logger.log( u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) break # break the while loop didSearch = True # skip non-tv crap curFoundResults = filter( lambda x: show_name_helpers.filterBadReleases( x.name) and show_name_helpers.isGoodResult( x.name, episode.show, season=episode.season), curFoundResults) # loop all results and see if any of them are good enough that we can stop searching for cur_result in curFoundResults: done_searching = isFinalResult(cur_result) logger.log( u"Should we stop searching after finding " + cur_result.name + ": " + str(done_searching), logger.DEBUG) if done_searching: break # if we are searching an anime we are a little more loose # this means we check every turn for a possible result # in contrast the isFinalResultlooks function looks for a perfect result (best quality) # but this will accept any result that would have been picked in the end -> pickBestResult # and then stop and use that if episode.show.is_anime: logger.log( u"We are searching an anime. i am checking if we got a good result with search provider " + curProvider.name, logger.DEBUG) bestResult = pickBestResult(curFoundResults, show=episode.show) if bestResult: return bestResult foundResults += curFoundResults # if we did find a result that's good enough to stop then don't continue # this breaks the turn loop if done_searching: break
def _addCacheEntry(self, name, url, quality=None): indexerid = None in_cache = False # if we don't have complete info then parse the filename to get it try: myParser = NameParser() parse_result = myParser.parse(name) except InvalidNameException: logger.log( u"Unable to parse the filename " + name + " into a valid episode", logger.DEBUG) return None if not parse_result: logger.log( u"Giving up because I'm unable to parse this name: " + name, logger.DEBUG) return None if not parse_result.series_name: logger.log( u"No series name retrieved from " + name + ", unable to cache it", logger.DEBUG) return None cacheResult = sickbeard.name_cache.retrieveNameFromCache( parse_result.series_name) if cacheResult: in_cache = True indexerid = int(cacheResult) elif cacheResult == 0: return None if not indexerid: showResult = helpers.searchDBForShow(parse_result.series_name) if showResult: indexerid = int(showResult[0]) if not indexerid: for curShow in sickbeard.showList: if show_name_helpers.isGoodResult(name, curShow, False): indexerid = curShow.indexerid break showObj = None if indexerid: showObj = helpers.findCertainShow(sickbeard.showList, indexerid) if not showObj: logger.log( u"No match for show: [" + parse_result.series_name + "], not caching ...", logger.DEBUG) sickbeard.name_cache.addNameToCache(parse_result.series_name, 0) return None # scene -> indexer numbering parse_result = parse_result.convert(showObj) season = episodes = None if parse_result.air_by_date or parse_result.sports: myDB = db.DBConnection() airdate = parse_result.air_date.toordinal( ) or parse_result.sports_event_date.toordinal() sql_results = myDB.select( "SELECT season, episode FROM tv_episodes WHERE showid = ? AND indexer = ? AND airdate = ?", [indexerid, showObj.indexer, airdate]) if sql_results > 0: season = int(sql_results[0]["season"]) episodes = [int(sql_results[0]["episode"])] else: season = parse_result.season_number if parse_result.season_number != None else 1 episodes = parse_result.episode_numbers if season and episodes: # store episodes as a seperated string episodeText = "|" + "|".join(map(str, episodes)) + "|" # get the current timestamp curTimestamp = int( time.mktime(datetime.datetime.today().timetuple())) # get quality of release if quality is None: quality = Quality.sceneQuality(name) if not isinstance(name, unicode): name = unicode(name, 'utf-8') logger.log( u"Added RSS item: [" + name + "] to cache: [" + self.providerID + "]", logger.DEBUG) if not in_cache: sickbeard.name_cache.addNameToCache(parse_result.series_name, indexerid) return [ "INSERT INTO [" + self.providerID + "] (name, season, episodes, indexerid, url, time, quality) VALUES (?,?,?,?,?,?,?)", [ name, season, episodeText, indexerid, url, curTimestamp, quality ] ]
continue try: curFoundResults = curProvider.findEpisode(episode, manualSearch=manualSearch) except exceptions.AuthException, e: logger.log(u"Authentication error: "+str(e).decode('utf-8'), logger.ERROR) continue except Exception, e: logger.log(u"Error while searching "+curProvider.name+", skipping: "+str(e).decode('utf-8'), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue didSearch = True # skip non-tv crap curFoundResults = filter(lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, episode.show), curFoundResults) foundResults += curFoundResults if not didSearch: logger.log(u"No NZB/Torrent providers found or enabled in the sickbeard config. Please check your settings.", logger.ERROR) bestResult = pickBestResult(foundResults) return bestResult def findSeason(show, season): logger.log(u"Searching for stuff we need from "+show.name+" season "+str(season)) foundResults = {}
def _addCacheEntry(self, name, url, season=None, episodes=None, indexer_id=0, quality=None, extraNames=[]): myDB = self._getDB() parse_result = None # if we don't have complete info then parse the filename to get it for curName in [name] + extraNames: try: myParser = NameParser() parse_result = myParser.parse(curName, True) except InvalidNameException: logger.log( u"Unable to parse the filename " + curName + " into a valid episode", logger.DEBUG) continue if not parse_result: logger.log( u"Giving up because I'm unable to parse this name: " + name, logger.DEBUG) return None if not parse_result.series_name: logger.log( u"No series name retrieved from " + name + ", unable to cache it", logger.DEBUG) return None indexer_lang = None if indexer_id: # if we have only the indexer_id, use the database showObj = helpers.findCertainShow(sickbeard.showList, indexer_id) if showObj: self.indexer = int(showObj.indexer) indexer_lang = showObj.lang else: logger.log( u"We were given a Indexer ID " + str(indexer_id) + " but it doesn't match a show we have in our list, so leaving indexer_id empty", logger.DEBUG) indexer_id = 0 # if no indexerID then fill out as much info as possible by searching the show name if not indexer_id: # check the name cache and see if we already know what show this is logger.log( u"Checking the cache to see if we already know the Indexer ID of " + parse_result.series_name, logger.DEBUG) indexer_id = name_cache.retrieveNameFromCache( parse_result.series_name) # remember if the cache lookup worked or not so we know whether we should bother updating it later if indexer_id == None: logger.log( u"No cache results returned, continuing on with the search", logger.DEBUG) from_cache = False else: logger.log( u"Cache lookup found " + repr(indexer_id) + ", using that", logger.DEBUG) from_cache = True # if the cache failed, try looking up the show name in the database if indexer_id == None: logger.log(u"Trying to look the show up in the show database", logger.DEBUG) showResult = helpers.searchDBForShow(parse_result.series_name) if showResult: logger.log( u"" + parse_result.series_name + " was found to be show " + showResult[2] + " (" + str(showResult[1]) + ") in our DB.", logger.DEBUG) indexer_id = showResult[1] # if the DB lookup fails then do a comprehensive regex search if indexer_id == None: logger.log( u"Couldn't figure out a show name straight from the DB, trying a regex search instead", logger.DEBUG) for curShow in sickbeard.showList: if show_name_helpers.isGoodResult(name, curShow, False): logger.log( u"Successfully matched " + name + " to " + curShow.name + " with regex", logger.DEBUG) indexer_id = curShow.indexerid indexer_lang = curShow.lang break # if indexer_id was anything but None (0 or a number) then if not from_cache: name_cache.addNameToCache(parse_result.series_name, indexer_id) # if we came out with indexer_id = None it means we couldn't figure it out at all, just use 0 for that if indexer_id == None: indexer_id = 0 # if we found the show then retrieve the show object if indexer_id: try: showObj = helpers.findCertainShow(sickbeard.showList, indexer_id) except (MultipleShowObjectsException): showObj = None if showObj: self.indexer = int(showObj.indexer) indexer_lang = showObj.lang # if we weren't provided with season/episode information then get it from the name that we parsed if not season: season = parse_result.season_number if parse_result.season_number != None else 1 if not episodes: episodes = parse_result.episode_numbers # if we have an air-by-date show then get the real season/episode numbers if (parse_result.air_by_date or parse_result.sports) and indexer_id: try: lINDEXER_API_PARMS = sickbeard.indexerApi( self.indexer).api_params.copy() if not (indexer_lang == "" or indexer_lang == "en" or indexer_lang == None): lINDEXER_API_PARMS['language'] = indexer_lang t = sickbeard.indexerApi( self.indexer).indexer(**lINDEXER_API_PARMS) epObj = None if parse_result.air_by_date: epObj = t[indexer_id].airedOn(parse_result.air_date)[0] elif parse_result.sports: epObj = t[indexer_id].airedOn(parse_result.sports_date)[0] if epObj is None: return None season = int(epObj["seasonnumber"]) episodes = [int(epObj["episodenumber"])] except sickbeard.indexer_episodenotfound: logger.log( u"Unable to find episode with date " + str(parse_result.air_date) + " for show " + parse_result.series_name + ", skipping", logger.WARNING) return None except sickbeard.indexer_error, e: logger.log( u"Unable to contact " + sickbeard.indexerApi(self.indexer).name + ": " + ex(e), logger.WARNING) return None
def searchProviders(show, season, episodes, manualSearch=False): foundResults = {} finalResults = [] # check if we want to search for season packs instead of just season/episode seasonSearch = False if not manualSearch: seasonEps = show.getAllEpisodes(season) if len(seasonEps) == len(episodes): seasonSearch = True providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()] if not len(providers): logger.log( u"No NZB/Torrent providers found or enabled in the sickrage config. Please check your settings.", logger.ERROR, ) return origThreadName = threading.currentThread().name for providerNum, provider in enumerate(providers): if provider.anime_only and not show.is_anime: logger.log(u"" + str(show.name) + " is not an anime skiping ...") continue threading.currentThread().name = origThreadName + " :: [" + provider.name + "]" foundResults.setdefault(provider.name, {}) searchCount = 0 search_mode = "eponly" if seasonSearch and provider.search_mode == "sponly": search_mode = provider.search_mode while True: searchCount += 1 if search_mode == "sponly": logger.log(u"Searching for " + show.name + " Season " + str(season) + " pack") else: logger.log(u"Searching for episodes we need from " + show.name + " Season " + str(season)) try: searchResults = provider.findSearchResults(show, season, episodes, search_mode, manualSearch) except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) break except Exception, e: logger.log(u"Error while searching " + provider.name + ", skipping: " + ex(e), logger.ERROR) break if len(searchResults): # make a list of all the results for this provider for curEp in searchResults: # skip non-tv crap searchResults[curEp] = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show, season=season), searchResults[curEp], ) if curEp in foundResults: foundResults[provider.name][curEp] += searchResults[curEp] else: foundResults[provider.name][curEp] = searchResults[curEp] break elif not provider.search_fallback or searchCount == 2: break if search_mode == "sponly": logger.log(u"FALLBACK EPISODE SEARCH INITIATED ...") search_mode = "eponly" else: logger.log(u"FALLBACK SEASON PACK SEARCH INITIATED ...") search_mode = "sponly"
def _addCacheEntry(self, name, url, season=None, episodes=None, tvdb_id=0, tvrage_id=0, quality=None, extraNames=[]): myDB = self._getDB() parse_result = None # if we don't have complete info then parse the filename to get it for curName in [name] + extraNames: try: myParser = NameParser() parse_result = myParser.parse(curName) except InvalidNameException: logger.log( u"Unable to parse the filename " + curName + " into a valid episode", logger.DEBUG) continue if not parse_result: logger.log( u"Giving up because I'm unable to parse this name: " + name, logger.DEBUG) return False if not parse_result.series_name: logger.log( u"No series name retrieved from " + name + ", unable to cache it", logger.DEBUG) return False tvdb_lang = None # if we need tvdb_id or tvrage_id then search the DB for them if not tvdb_id or not tvrage_id: # if we have only the tvdb_id, use the database if tvdb_id: showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id) if showObj: tvrage_id = showObj.tvrid tvdb_lang = showObj.lang else: logger.log( u"We were given a TVDB id " + str(tvdb_id) + " but it doesn't match a show we have in our list, so leaving tvrage_id empty", logger.DEBUG) tvrage_id = 0 # if we have only a tvrage_id then use the database elif tvrage_id: showObj = helpers.findCertainTVRageShow( sickbeard.showList, tvrage_id) if showObj: tvdb_id = showObj.tvdbid tvdb_lang = showObj.lang else: logger.log( u"We were given a TVRage id " + str(tvrage_id) + " but it doesn't match a show we have in our list, so leaving tvdb_id empty", logger.DEBUG) tvdb_id = 0 # if they're both empty then fill out as much info as possible by searching the show name else: # check the name cache and see if we already know what show this is logger.log( u"Checking the cache to see if we already know the tvdb id of " + parse_result.series_name, logger.DEBUG) tvdb_id = name_cache.retrieveNameFromCache( parse_result.series_name) # remember if the cache lookup worked or not so we know whether we should bother updating it later if tvdb_id == None: logger.log( u"No cache results returned, continuing on with the search", logger.DEBUG) from_cache = False else: logger.log( u"Cache lookup found " + repr(tvdb_id) + ", using that", logger.DEBUG) from_cache = True # if the cache failed, try looking up the show name in the database if tvdb_id == None: logger.log( u"Trying to look the show up in the show database", logger.DEBUG) showResult = helpers.searchDBForShow( parse_result.series_name) if showResult: logger.log( parse_result.series_name + " was found to be show " + showResult[1] + " (" + str(showResult[0]) + ") in our DB.", logger.DEBUG) tvdb_id = showResult[0] # if the DB lookup fails then do a comprehensive regex search if tvdb_id == None: logger.log( u"Couldn't figure out a show name straight from the DB, trying a regex search instead", logger.DEBUG) for curShow in sickbeard.showList: if show_name_helpers.isGoodResult( name, curShow, False): logger.log( u"Successfully matched " + name + " to " + curShow.name + " with regex", logger.DEBUG) tvdb_id = curShow.tvdbid tvdb_lang = curShow.lang break # if tvdb_id was anything but None (0 or a number) then if not from_cache: name_cache.addNameToCache(parse_result.series_name, tvdb_id) # if we came out with tvdb_id = None it means we couldn't figure it out at all, just use 0 for that if tvdb_id == None: tvdb_id = 0 # if we found the show then retrieve the show object if tvdb_id: showObj = helpers.findCertainShow(sickbeard.showList, tvdb_id) if showObj: tvrage_id = showObj.tvrid tvdb_lang = showObj.lang # if we weren't provided with season/episode information then get it from the name that we parsed if not season: season = parse_result.season_number if parse_result.season_number != None else 1 if not episodes: episodes = parse_result.episode_numbers # if we have an air-by-date show then get the real season/episode numbers if parse_result.air_by_date and tvdb_id: try: # There's gotta be a better way of doing this but we don't wanna # change the language value elsewhere ltvdb_api_parms = sickbeard.TVDB_API_PARMS.copy() if not (tvdb_lang == "" or tvdb_lang == "en" or tvdb_lang == None): ltvdb_api_parms['language'] = tvdb_lang t = tvdb_api.Tvdb(**ltvdb_api_parms) epObj = t[tvdb_id].airedOn(parse_result.air_date)[0] season = int(epObj["seasonnumber"]) episodes = [int(epObj["episodenumber"])] except tvdb_exceptions.tvdb_episodenotfound: logger.log( u"Unable to find episode with date " + str(parse_result.air_date) + " for show " + parse_result.series_name + ", skipping", logger.WARNING) return False except tvdb_exceptions.tvdb_error, e: logger.log(u"Unable to contact TVDB: " + ex(e), logger.WARNING) return False
continue except Exception, e: logger.log( u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue didSearch = True # make a list of all the results for this provider for curEp in curResults: # skip non-tv crap curResults[curEp] = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), curResults[curEp]) if curEp in foundResults: foundResults[curEp] += curResults[curEp] else: foundResults[curEp] = curResults[curEp] if not didSearch: logger.log( u"No NZB/Torrent providers found or enabled in the sickbeard config. Please check your settings.", logger.ERROR) finalResults = [] anyQualities, bestQualities = Quality.splitQuality(show.quality)
def _addCacheEntry(self, name, url, season=None, episodes=None, indexer_id=0, quality=None, extraNames=[]): myDB = self._getDB() parse_result = None # if we don't have complete info then parse the filename to get it for curName in [name] + extraNames: try: myParser = NameParser() parse_result = myParser.parse(curName) except InvalidNameException: logger.log(u"Unable to parse the filename " + curName + " into a valid episode", logger.DEBUG) continue if not parse_result: logger.log(u"Giving up because I'm unable to parse this name: " + name, logger.DEBUG) return None if not parse_result.series_name: logger.log(u"No series name retrieved from " + name + ", unable to cache it", logger.DEBUG) return None indexer_lang = None if indexer_id: # if we have only the indexer_id, use the database showObj = helpers.findCertainShow(sickbeard.showList, indexer_id) if showObj: self.indexer = int(showObj.indexer) indexer_lang = showObj.lang else: logger.log(u"We were given a Indexer ID " + str(indexer_id) + " but it doesn't match a show we have in our list, so leaving indexer_id empty",logger.DEBUG) indexer_id = 0 # if no indexerID then fill out as much info as possible by searching the show name if not indexer_id: from_cache = False # check the name cache and see if we already know what show this is logger.log( u"Checking the cache for Indexer ID of " + parse_result.series_name, logger.DEBUG) # remember if the cache lookup worked or not so we know whether we should bother updating it later indexer_id = name_cache.retrieveNameFromCache(parse_result.series_name) if indexer_id: logger.log(u"Cache lookup found " + repr(indexer_id) + ", using that", logger.DEBUG) from_cache = True # if the cache failed, try looking up the show name in the database if not indexer_id: logger.log( u"Checking the database for Indexer ID of " + str(parse_result.series_name), logger.DEBUG) showResult = helpers.searchDBForShow(parse_result.series_name) if showResult: logger.log( u"" + parse_result.series_name + " was found to be show " + showResult[2] + " (" + str( showResult[1]) + ") in our DB.", logger.DEBUG) indexer_id = showResult[1] # if the database failed, try looking up the show name from scene exceptions list if not indexer_id: logger.log( u"Checking the scene exceptions list for Indexer ID of " + parse_result.series_name, logger.DEBUG) sceneResult = sickbeard.scene_exceptions.get_scene_exception_by_name(parse_result.series_name) if sceneResult: logger.log( u"" + str(parse_result.series_name) + " was found in scene exceptions list with Indexer ID: " + str(sceneResult), logger.DEBUG) indexer_id = sceneResult # if the DB lookup fails then do a comprehensive regex search if not indexer_id: logger.log( u"Checking the shows list for Indexer ID of " + str(parse_result.series_name), logger.DEBUG) for curShow in sickbeard.showList: if show_name_helpers.isGoodResult(name, curShow, False): logger.log(u"Successfully matched " + name + " to " + curShow.name + " from shows list", logger.DEBUG) indexer_id = curShow.indexerid indexer_lang = curShow.lang break # if the database failed, try looking up the show name from scene exceptions list if not indexer_id: logger.log( u"Checking Indexers for Indexer ID of " + parse_result.series_name, logger.DEBUG) # check indexers try:indexerResult = helpers.searchIndexerForShowID(parse_result.series_name) except:indexerResult = None if indexerResult: logger.log( u"" + str(parse_result.series_name) + " was found on " + str(sickbeard.indexerApi(indexerResult[0]).name) + " with Indexer ID: " + str(indexerResult[1]), logger.DEBUG) indexer_id = indexerResult[1] # if indexer_id was anything but None (0 or a number) then if not from_cache: name_cache.addNameToCache(parse_result.series_name, indexer_id) # if we came out with indexer_id = None it means we couldn't figure it out at all, just use 0 for that if indexer_id == None: indexer_id = 0 # if we found the show then retrieve the show object if indexer_id: try: showObj = helpers.findCertainShow(sickbeard.showList, indexer_id) except (MultipleShowObjectsException): showObj = None if showObj: self.indexer = int(showObj.indexer) indexer_lang = showObj.lang # if we weren't provided with season/episode information then get it from the name that we parsed if not season: season = parse_result.season_number if parse_result.season_number != None else 1 if not episodes: episodes = parse_result.episode_numbers # if we have an air-by-date show then get the real season/episode numbers if (parse_result.air_by_date or parse_result.sports) and indexer_id: try: lINDEXER_API_PARMS = sickbeard.indexerApi(self.indexer).api_params.copy() if not (indexer_lang == "" or indexer_lang == "en" or indexer_lang == None): lINDEXER_API_PARMS['language'] = indexer_lang t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS) epObj = None if parse_result.air_by_date: epObj = t[indexer_id].airedOn(parse_result.air_date)[0] elif parse_result.sports: epObj = t[indexer_id].airedOn(parse_result.sports_date)[0] if epObj is None: return None season = int(epObj["seasonnumber"]) episodes = [int(epObj["episodenumber"])] except sickbeard.indexer_episodenotfound: logger.log(u"Unable to find episode with date " + str( parse_result.air_date) + " for show " + parse_result.series_name + ", skipping", logger.WARNING) return None except sickbeard.indexer_error, e: logger.log(u"Unable to contact " + sickbeard.indexerApi(self.indexer).name + ": " + ex(e), logger.WARNING) return None
def _test_isGoodName(self, name, show): self.assertTrue(show_name_helpers.isGoodResult(name, show))
elif not anyWanted: logger.log( u"No eps from this season are wanted at this quality, ignoring the result of " + bestSeasonNZB.name, logger.DEBUG) else: if bestSeasonNZB.provider.providerType == GenericProvider.NZB: logger.log(u"Breaking apart the NZB and adding the individual ones to our results", logger.DEBUG) # if not, break it apart and add them as the lowest priority results individualResults = nzbSplitter.splitResult(bestSeasonNZB) individualResults = filter( lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, show), individualResults) for curResult in individualResults: if len(curResult.episodes) == 1: epNum = curResult.episodes[0].episode elif len(curResult.episodes) > 1: epNum = MULTI_EP_RESULT if epNum in foundResults[provider.name]: foundResults[provider.name][epNum].append(curResult) else: foundResults[provider.name][epNum] = [curResult] # If this is a torrent all we can do is leech the entire torrent, user will have to select which eps not do download in his torrent client else:
continue try: curFoundResults = curProvider.findEpisode(episode, manualSearch=manualSearch) except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) continue except Exception, e: logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) continue didSearch = True # skip non-tv crap curFoundResults = filter(lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name, episode.show), curFoundResults) # loop all results and see if any of them are good enough that we can stop searching done_searching = False for cur_result in curFoundResults: done_searching = isFinalResult(cur_result) logger.log(u"Should we stop searching after finding " + cur_result.name + ": " + str(done_searching), logger.DEBUG) if done_searching: break foundResults += curFoundResults # if we did find a result that's good enough to stop then don't continue if done_searching: break
logger.log( u"No eps from this season are wanted at this quality, ignoring the result of " + bestSeasonNZB.name, logger.DEBUG) else: logger.log( u"Breaking apart the NZB and adding the individual ones to our results", logger.DEBUG) # if not, break it apart and add them as the lowest priority results individualResults = nzbSplitter.splitResult(bestSeasonNZB) individualResults = filter( lambda x: show_name_helpers.filterBadReleases( x.name, show.show_lang) and show_name_helpers.isGoodResult( x.name, show), individualResults) for curResult in individualResults: if len(curResult.episodes) == 1: epNum = curResult.episodes[0].episode elif len(curResult.episodes) > 1: epNum = MULTI_EP_RESULT if epNum in foundResults: foundResults[epNum].append(curResult) else: foundResults[epNum] = [curResult] # go through multi-ep results and see if we really want them or not, get rid of the rest multiResults = {} if MULTI_EP_RESULT in foundResults: