diff --git a/sickbeard/dailysearcher.py b/sickbeard/dailysearcher.py index 70338cd2..b4d24e56 100644 --- a/sickbeard/dailysearcher.py +++ b/sickbeard/dailysearcher.py @@ -20,6 +20,7 @@ from __future__ import with_statement import datetime import threading +import traceback import sickbeard from sickbeard import logger @@ -42,19 +43,17 @@ class DailySearcher(): providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and not x.backlog_only] for curProviderCount, curProvider in enumerate(providers): + logger.log(u"Updating [" + curProvider.name + "] RSS cache ...") + try: - logger.log(u"Updating [" + curProvider.name + "] RSS cache ...") curProvider.cache.updateCache() except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) - if curProviderCount != len(providers): - continue - break + continue except Exception, e: logger.log(u"Error while updating cache for " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) - if curProviderCount != len(providers): - continue - break + logger.log(traceback.format_exc(), logger.DEBUG) + continue logger.log(u"Searching for coming episodes and 1 weeks worth of previously WANTED episodes ...") @@ -66,21 +65,14 @@ class DailySearcher(): [common.UNAIRED, common.WANTED, fromDate.toordinal(), curDate.toordinal()]) sql_l = [] - todaysEps = {} for sqlEp in sqlResults: - try: show = helpers.findCertainShow(sickbeard.showList, int(sqlEp["showid"])) except exceptions.MultipleShowObjectsException: logger.log(u"ERROR: expected to find a single show matching " + sqlEp["showid"]) - break + continue - if not show: - logger.log(u"Unable to find the show with ID " + str( - sqlEp["showid"]) + " in your show list! DB value was " + str(sqlEp), logger.ERROR) - break - - ep = show.getEpisode(sqlEp["season"], sqlEp["episode"]) + ep = show.getEpisode(int(sqlEp["season"]), int(sqlEp["episode"])) with ep.lock: if ep.show.paused: ep.status = common.SKIPPED @@ -89,26 +81,16 @@ class DailySearcher(): logger.log(u"New episode " + ep.prettyName() + " airs today, setting status to WANTED") ep.status = common.WANTED - if ep.status == common.WANTED: - if show not in todaysEps: - todaysEps[show] = [ep] - else: - todaysEps[show].append(ep) - sql_l.append(ep.get_sql()) + if ep.status == common.WANTED: + dailysearch_queue_item = sickbeard.search_queue.DailySearchQueueItem(show, [ep]) + sickbeard.searchQueueScheduler.action.add_item(dailysearch_queue_item) + else: + logger.log(u"Could not find any wanted episodes for the last 7 days to search for") + if len(sql_l) > 0: myDB = db.DBConnection() myDB.mass_action(sql_l) - - if len(todaysEps): - for show in todaysEps: - segment = todaysEps[show] - - dailysearch_queue_item = sickbeard.search_queue.DailySearchQueueItem(show, segment) - sickbeard.searchQueueScheduler.action.add_item(dailysearch_queue_item) - else: - logger.log(u"Could not find any needed episodes to search for ...") - self.amActive = False \ No newline at end of file diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py index a8450ea8..96e4aa5e 100644 --- a/sickbeard/databases/mainDB.py +++ b/sickbeard/databases/mainDB.py @@ -168,7 +168,7 @@ class InitialSchema(db.SchemaUpgrade): "CREATE TABLE info (last_backlog NUMERIC, last_indexer NUMERIC, last_proper_search NUMERIC)", "CREATE TABLE scene_numbering(indexer TEXT, indexer_id INTEGER, season INTEGER, episode INTEGER,scene_season INTEGER, scene_episode INTEGER, PRIMARY KEY(indexer_id, season, episode))", "CREATE TABLE tv_shows (show_id INTEGER PRIMARY KEY, indexer_id NUMERIC, indexer TEXT, show_name TEXT, location TEXT, network TEXT, genre TEXT, classification TEXT, runtime NUMERIC, quality NUMERIC, airs TEXT, status TEXT, flatten_folders NUMERIC, paused NUMERIC, startyear NUMERIC, air_by_date NUMERIC, lang TEXT, subtitles NUMERIC, notify_list TEXT, imdb_id TEXT, last_update_indexer NUMERIC, dvdorder NUMERIC, archive_firstmatch NUMERIC, rls_require_words TEXT, rls_ignore_words TEXT, sports NUMERIC);", - "CREATE TABLE tv_episodes (episode_id INTEGER PRIMARY KEY, showid/ NUMERIC, indexerid NUMERIC, indexer TEXT, name TEXT, season NUMERIC, episode NUMERIC, description TEXT, airdate NUMERIC, hasnfo NUMERIC, hastbn NUMERIC, status NUMERIC, location TEXT, file_size NUMERIC, release_name TEXT, subtitles TEXT, subtitles_searchcount NUMERIC, subtitles_lastsearch TIMESTAMP, is_proper NUMERIC, scene_season NUMERIC, scene_episode NUMERIC);", + "CREATE TABLE tv_episodes (episode_id INTEGER PRIMARY KEY, showid NUMERIC, indexerid NUMERIC, indexer TEXT, name TEXT, season NUMERIC, episode NUMERIC, description TEXT, airdate NUMERIC, hasnfo NUMERIC, hastbn NUMERIC, status NUMERIC, location TEXT, file_size NUMERIC, release_name TEXT, subtitles TEXT, subtitles_searchcount NUMERIC, subtitles_lastsearch TIMESTAMP, is_proper NUMERIC, scene_season NUMERIC, scene_episode NUMERIC);", "CREATE UNIQUE INDEX idx_indexer_id ON tv_shows (indexer_id)", "CREATE INDEX idx_showid ON tv_episodes (showid);", "CREATE INDEX idx_sta_epi_air ON tv_episodes (status,episode, airdate);", diff --git a/sickbeard/properFinder.py b/sickbeard/properFinder.py index 9adadcc9..f4fa06b2 100644 --- a/sickbeard/properFinder.py +++ b/sickbeard/properFinder.py @@ -19,6 +19,7 @@ import datetime import operator import threading +import traceback import sickbeard @@ -68,20 +69,27 @@ class ProperFinder(): def _getProperList(self): propers = {} + search_date = datetime.datetime.today() - datetime.timedelta(days=2) + # 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 + except Exception, e: + logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) + logger.log(traceback.format_exc(), logger.DEBUG) + continue + finally: + threading.currentThread().name = origThreadName # if they haven't been added by a different provider than add the proper to the list for x in curPropers: @@ -91,12 +99,10 @@ class ProperFinder(): 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: try: @@ -162,7 +168,9 @@ class ProperFinder(): 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 = ?", diff --git a/sickbeard/providers/speedcd.py b/sickbeard/providers/speedcd.py index 92670127..76c86fa0 100644 --- a/sickbeard/providers/speedcd.py +++ b/sickbeard/providers/speedcd.py @@ -164,6 +164,8 @@ class SpeedCDProvider(generic.TorrentProvider): **self.categories[mode]) data = self.session.post(self.urls['search'], data=post_data).json() + if not data: + continue try: torrents = data.get('Fs', [])[0].get('Cn', {}).get('torrents', []) diff --git a/sickbeard/search.py b/sickbeard/search.py index 976555cd..96fc8a11 100644 --- a/sickbeard/search.py +++ b/sickbeard/search.py @@ -22,10 +22,11 @@ import os import re import threading import datetime +import traceback import sickbeard -from common import SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, Quality, SEASON_RESULT, MULTI_EP_RESULT, Overview +from common import SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, Quality, SEASON_RESULT, MULTI_EP_RESULT from sickbeard import logger, db, show_name_helpers, exceptions, helpers from sickbeard import sab @@ -36,10 +37,9 @@ from sickbeard import notifiers from sickbeard import nzbSplitter from sickbeard import ui from sickbeard import encodingKludge as ek -from sickbeard import providers from sickbeard import failed_history from sickbeard.exceptions import ex -from sickbeard.providers.generic import GenericProvider, tvcache +from sickbeard.providers.generic import GenericProvider from sickbeard.blackandwhitelist import BlackAndWhiteList def _downloadResult(result): @@ -52,9 +52,6 @@ def _downloadResult(result): """ resProvider = result.provider - - newResult = False - if resProvider == None: logger.log(u"Invalid provider name - this is a coding error, report it please", logger.ERROR) return False @@ -109,7 +106,8 @@ def snatchEpisode(result, endStatus=SNATCHED): endStatus: the episode status that should be used for the episode object once it's snatched. """ - if result is None: return False + if result is None: + return False result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickbeard.ALLOW_HIGH_PRIORITY: @@ -176,7 +174,6 @@ def snatchEpisode(result, endStatus=SNATCHED): myDB = db.DBConnection() myDB.mass_action(sql_l) - return True @@ -345,32 +342,27 @@ def searchForNeededEpisodes(show, episodes): foundResults = {} didSearch = False - providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and not x.backlog_only] - 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 + + providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and not x.backlog_only] for curProviderCount, curProvider in enumerate(providers): if curProvider.anime_only and not show.is_anime: - logger.log(u"" + str(show.name) + " is not an anime skiping ...") + logger.log(u"" + str(show.name) + " is not an anime, skiping", logger.DEBUG) continue + threading.currentThread().name = origThreadName + " :: [" + curProvider.name + "]" + try: - threading.currentThread().name = origThreadName + " :: [" + curProvider.name + "]" curFoundResults = curProvider.searchRSS(episodes) - threading.currentThread().name = origThreadName except exceptions.AuthException, e: logger.log(u"Authentication error: " + ex(e), logger.ERROR) - if curProviderCount != len(providers): - continue - break + continue except Exception, e: logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) - if curProviderCount != len(providers): - continue - break + logger.log(traceback.format_exc(), logger.DEBUG) + continue + finally: + threading.currentThread().name = origThreadName didSearch = True @@ -408,12 +400,6 @@ def searchProviders(show, season, episodes, manualSearch=False): foundResults = {} finalResults = [] - 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 - # check if we want to search for season packs instead of just season/episode seasonSearch = False if not manualSearch: @@ -422,17 +408,21 @@ def searchProviders(show, season, episodes, manualSearch=False): seasonSearch = True 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 ...") + + providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()] + for providerNum, curProvider in enumerate(providers): + if curProvider.anime_only and not show.is_anime: + logger.log(u"" + str(show.name) + " is not an anime, skiping", logger.DEBUG) continue - foundResults[provider.name] = {} + threading.currentThread().name = origThreadName + " :: [" + curProvider.name + "]" + + foundResults[curProvider.name] = {} searchCount = 0 search_mode = 'eponly' - if seasonSearch and provider.search_mode == 'sponly': - search_mode = provider.search_mode + if seasonSearch and curProvider.search_mode == 'sponly': + search_mode = curProvider.search_mode while(True): searchCount += 1 @@ -443,15 +433,16 @@ def searchProviders(show, season, episodes, manualSearch=False): logger.log(u"Searching for episodes we need from " + show.name + " Season " + str(season)) try: - threading.currentThread().name = origThreadName + " :: [" + provider.name + "]" - searchResults = provider.findSearchResults(show, season, episodes, search_mode, manualSearch) - threading.currentThread().name = origThreadName + searchResults = curProvider.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) + logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) + logger.log(traceback.format_exc(), logger.DEBUG) break + finally: + threading.currentThread().name = origThreadName if len(searchResults): # make a list of all the results for this provider @@ -461,12 +452,12 @@ def searchProviders(show, season, episodes, manualSearch=False): lambda x: show_name_helpers.filterBadReleases(x.name) and x.show == show, searchResults[curEp]) if curEp in foundResults: - foundResults[provider.name][curEp] += searchResults[curEp] + foundResults[curProvider.name][curEp] += searchResults[curEp] else: - foundResults[provider.name][curEp] = searchResults[curEp] + foundResults[curProvider.name][curEp] = searchResults[curEp] break - elif not provider.search_fallback or searchCount == 2: + elif not curProvider.search_fallback or searchCount == 2: break if search_mode == 'sponly': @@ -477,22 +468,20 @@ def searchProviders(show, season, episodes, manualSearch=False): search_mode = 'sponly' # skip to next provider if we have no results to process - if not len(foundResults[provider.name]): - if providerNum != len(providers): - continue - break + if not len(foundResults[curProvider.name]): + continue anyQualities, bestQualities = Quality.splitQuality(show.quality) # pick the best season NZB bestSeasonNZB = None - if SEASON_RESULT in foundResults[provider.name]: - bestSeasonNZB = pickBestResult(foundResults[provider.name][SEASON_RESULT], show, + if SEASON_RESULT in foundResults[curProvider.name]: + bestSeasonNZB = pickBestResult(foundResults[curProvider.name][SEASON_RESULT], show, anyQualities + bestQualities) highest_quality_overall = 0 - for cur_episode in foundResults[provider.name]: - for cur_result in foundResults[provider.name][cur_episode]: + for cur_episode in foundResults[curProvider.name]: + for cur_result in foundResults[curProvider.name][cur_episode]: if cur_result.quality != Quality.UNKNOWN and cur_result.quality > highest_quality_overall: highest_quality_overall = cur_result.quality logger.log(u"The highest quality of any match is " + Quality.qualityStrings[highest_quality_overall], @@ -502,7 +491,6 @@ def searchProviders(show, season, episodes, manualSearch=False): if bestSeasonNZB: # get the quality of the season nzb - seasonQual = Quality.sceneQuality(bestSeasonNZB.name) seasonQual = bestSeasonNZB.quality logger.log( u"The quality of the season " + bestSeasonNZB.provider.providerType + " is " + Quality.qualityStrings[ @@ -555,10 +543,10 @@ def searchProviders(show, season, episodes, manualSearch=False): elif len(curResult.episodes) > 1: epNum = MULTI_EP_RESULT - if epNum in foundResults[provider.name]: - foundResults[provider.name][epNum].append(curResult) + if epNum in foundResults[curProvider.name]: + foundResults[curProvider.name][epNum].append(curResult) else: - foundResults[provider.name][epNum] = [curResult] + foundResults[curProvider.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: @@ -572,15 +560,15 @@ def searchProviders(show, season, episodes, manualSearch=False): bestSeasonNZB.episodes = epObjs epNum = MULTI_EP_RESULT - if epNum in foundResults[provider.name]: - foundResults[provider.name][epNum].append(bestSeasonNZB) + if epNum in foundResults[curProvider.name]: + foundResults[curProvider.name][epNum].append(bestSeasonNZB) else: - foundResults[provider.name][epNum] = [bestSeasonNZB] + foundResults[curProvider.name][epNum] = [bestSeasonNZB] # 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[provider.name]: - for multiResult in foundResults[provider.name][MULTI_EP_RESULT]: + if MULTI_EP_RESULT in foundResults[curProvider.name]: + for multiResult in foundResults[curProvider.name][MULTI_EP_RESULT]: logger.log(u"Seeing if we want to bother with multi-episode result " + multiResult.name, logger.DEBUG) @@ -595,15 +583,10 @@ def searchProviders(show, season, episodes, manualSearch=False): for epObj in multiResult.episodes: epNum = epObj.episode # if we have results for the episode - if epNum in foundResults[provider.name] and len(foundResults[provider.name][epNum]) > 0: - # but the multi-ep is worse quality, we don't want it - # TODO: wtf is this False for - # if False and multiResult.quality <= pickBestResult(foundResults[epNum]): - # notNeededEps.append(epNum) - #else: + if epNum in foundResults[curProvider.name] and len(foundResults[curProvider.name][epNum]) > 0: neededEps.append(epNum) else: - neededEps.append(epNum) + notNeededEps.append(epNum) logger.log( u"Single-ep check result is neededEps: " + str(neededEps) + ", notNeededEps: " + str(notNeededEps), @@ -641,22 +624,22 @@ def searchProviders(show, season, episodes, manualSearch=False): # don't bother with the single result if we're going to get it with a multi result for epObj in multiResult.episodes: epNum = epObj.episode - if epNum in foundResults[provider.name]: + if epNum in foundResults[curProvider.name]: logger.log( u"A needed multi-episode result overlaps with a single-episode result for ep #" + str( epNum) + ", removing the single-episode results from the list", logger.DEBUG) - del foundResults[provider.name][epNum] + del foundResults[curProvider.name][epNum] # of all the single ep results narrow it down to the best one for each episode finalResults += set(multiResults.values()) - for curEp in foundResults[provider.name]: + for curEp in foundResults[curProvider.name]: if curEp in (MULTI_EP_RESULT, SEASON_RESULT): continue - if len(foundResults[provider.name][curEp]) == 0: + if len(foundResults[curProvider.name][curEp]) == 0: continue - bestResult = pickBestResult(foundResults[provider.name][curEp], show) + bestResult = pickBestResult(foundResults[curProvider.name][curEp], show) # if all results were rejected move on to the next episode if not bestResult: @@ -682,7 +665,11 @@ def searchProviders(show, season, episodes, manualSearch=False): wantedEpCount += 1 # make sure we search every provider for results unless we found everything we wanted - if providerNum == len(providers) or wantedEpCount == len(episodes): + if wantedEpCount == len(episodes): break + else: + logger.log(u"No NZB/Torrent providers found or enabled in the sickrage config. Please check your settings.", + logger.ERROR) + return finalResults diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index ee91d516..ad1ecdbe 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -2693,18 +2693,17 @@ class NewHomeAddShows(MainHandler): indexer_id = show_name = indexer = None for cur_provider in sickbeard.metadata_provider_dict.values(): (indexer_id, show_name, indexer) = cur_provider.retrieveShowMetadata(cur_path) - if show_name: break - # default to TVDB if indexer was not detected - if show_name and not (indexer and indexer_id): - (sn, idx, id) = helpers.searchIndexerForShowID(show_name, indexer, indexer_id) + # default to TVDB if indexer was not detected + if show_name and not (indexer or indexer_id): + (sn, idx, id) = helpers.searchIndexerForShowID(show_name, indexer, indexer_id) - # set indexer and indexer_id from found info - if indexer is None and idx: - indexer = idx + # set indexer and indexer_id from found info + if not indexer and idx: + indexer = idx - if indexer_id is None and id: - indexer_id = id + if not indexer_id and id: + indexer_id = id cur_dir['existing_info'] = (indexer_id, show_name, indexer)