From 0aa08edd84c770310f28a7d38853f6ac65b262cb Mon Sep 17 00:00:00 2001
From: Sarakha63 <sarakha_ludovic@yahoo.fr>
Date: Sat, 18 May 2013 13:04:51 +0200
Subject: [PATCH] first version :

History download gestion
a second search will automatically skip the first downloaded episode
unless ou clean this episode download history


also : changed the way backlog is done when only some episodes were
wanted in a season (avoiding having a full season search if only some
eps were wanted)
---
 data/images/corbeille.png                | Bin 0 -> 16531 bytes
 data/interfaces/default/displayShow.tmpl |   8 +-
 data/js/ajaxHisttrunc.js                 |  45 ++
 data/js/displayShow.js                   |   1 +
 sickbeard/databases/mainDB.py            |  13 +-
 sickbeard/nzbSplitter.py                 |   2 +-
 sickbeard/providers/binnewz/nzbindex.py  |   2 +-
 sickbeard/providers/cpasbien.py          |   2 +-
 sickbeard/providers/gks.py               |   2 +-
 sickbeard/providers/t411.py              |   2 +-
 sickbeard/search.py                      | 546 +++++++++++++----------
 sickbeard/webserve.py                    |  10 +
 12 files changed, 381 insertions(+), 252 deletions(-)
 create mode 100644 data/images/corbeille.png
 create mode 100644 data/js/ajaxHisttrunc.js

diff --git a/data/images/corbeille.png b/data/images/corbeille.png
new file mode 100644
index 0000000000000000000000000000000000000000..d057ce92d6a136700cbc91f37e9e76660fba1b30
GIT binary patch
literal 16531
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

literal 0
HcmV?d00001

diff --git a/data/interfaces/default/displayShow.tmpl b/data/interfaces/default/displayShow.tmpl
index edfb26c58..608f63fb5 100644
--- a/data/interfaces/default/displayShow.tmpl
+++ b/data/interfaces/default/displayShow.tmpl
@@ -89,6 +89,7 @@
 <script type="text/javascript" src="$sbRoot/js/plotTooltip.js?$sbPID"></script>
 <script type="text/javascript" src="$sbRoot/js/ajaxEpSearch.js?$sbPID"></script>
 <script type="text/javascript" src="$sbRoot/js/ajaxEpSubtitles.js?$sbPID"></script>
+<script type="text/javascript" src="$sbRoot/js/ajaxhisttrunc.js?$sbPID"></script>
 
 <div class="align-left"><b>Change Show:</b>
 <div class="navShow"><img id="prevShow" width="16" height="18" src="$sbRoot/images/prev.gif" alt="&lt;&lt;" title="Prev Show" /></div>
@@ -209,13 +210,13 @@ Change Audio of selected episodes to
 #for $epResult in $sqlResults:
 
     #if int($epResult["season"]) != $curSeason:
-  <tr><td colspan="10"><a name="season-$epResult["season"]"></a></td></tr>
+  <tr><td colspan="11"><a name="season-$epResult["season"]"></a></td></tr>
   <tr class="seasonheader" id="season-$epResult["season"]">
     <td colspan="9">
         <h2>#if int($epResult["season"]) == 0 then "Specials" else "Season "+str($epResult["season"])#</h2>
     </td>
   </tr>
-  <tr id="season-$epResult["season"]-cols"><th width="1%"><input type="checkbox" class="seasonCheck" id="$epResult["season"]" /></th><th>NFO</th><th>TBN</th><th>Episode</th><th>Name</th><th class="nowrap">Airdate</th><th>Filename</th><th>Audio</th>#if $sickbeard.USE_SUBTITLES and $show.subtitles then "<th>Subs</th>" else ""#<th>Status</th><th>Search</th></tr>
+  <tr id="season-$epResult["season"]-cols"><th width="1%"><input type="checkbox" class="seasonCheck" id="$epResult["season"]" /></th><th>NFO</th><th>TBN</th><th>Episode</th><th>Name</th><th class="nowrap">Airdate</th><th>Filename</th><th>Audio</th>#if $sickbeard.USE_SUBTITLES and $show.subtitles then "<th>Subs</th>" else ""#<th>Status</th><th>Search</th><th>Hist</th></tr>
         #set $curSeason = int($epResult["season"])
     #end if    
 
@@ -280,6 +281,9 @@ $epLoc
       <a class="epSubtitlesSearch" href="searchEpisodeSubtitles?show=$show.tvdbid&amp;season=$epResult["season"]&amp;episode=$epResult["episode"]"><img src="$sbRoot/images/closed_captioning.png" height="16" alt="search subtitles" title="Search Subtitles" /></a>
     #end if
     </td>
+    <td align="center">
+     <a class="histtrunc" href="trunchistory?epid=$epResult["episode_id"]"><img src="$sbRoot/images/corbeille.png" height="16" alt="trunc" title="Trunc Downloaded links History" /></a>
+     </td>
    </tr>
 
 #end for
diff --git a/data/js/ajaxHisttrunc.js b/data/js/ajaxHisttrunc.js
new file mode 100644
index 000000000..82db735ed
--- /dev/null
+++ b/data/js/ajaxHisttrunc.js
@@ -0,0 +1,45 @@
+(function () {
+
+    $.ajaxHisttrunc = {
+        defaults: {
+            size:               16,
+            colorRow:           false,
+            loadingImage:       'loading16_dddddd.gif',
+            noImage:            'no16.png',
+            yesImage:           'yes16.png'
+        }
+    };
+
+    $.fn.ajaxHisttrunc = function (options) {
+        options = $.extend({}, $.ajaxHisttrunc.defaults, options);
+
+        $('.histtrunc').click(function () {
+            var parent = $(this).parent();
+
+            // put the ajax spinner (for non white bg) placeholder while we wait
+            parent.empty();
+            parent.append($("<img/>").attr({"src": sbRoot + "/images/" + options.loadingImage, "height": options.size, "alt": "", "title": "loading"}));
+
+            $.getJSON($(this).attr('href'), function (data) {
+                // if they failed then just put the red X
+                if (data.result == 'failure') {
+                    img_name = options.noImage;
+                    img_result = 'failed';
+
+                // if the snatch was successful then apply the corresponding class and fill in the row appropriately
+                } else {
+                    img_name = options.yesImage;
+                    img_result = 'success';
+                    
+                }
+
+                // put the corresponding image as the result for the the row
+                parent.empty();
+                parent.append($("<img/>").attr({"src": sbRoot + "/images/" + img_name, "height": options.size, "alt": img_result, "title": img_result}));
+            });
+
+            // fon't follow the link
+            return false;
+        });
+    };
+})();
diff --git a/data/js/displayShow.js b/data/js/displayShow.js
index 7dc7a9375..30869610e 100644
--- a/data/js/displayShow.js
+++ b/data/js/displayShow.js
@@ -2,6 +2,7 @@ $(document).ready(function(){
 
     $('#sbRoot').ajaxEpSearch({'colorRow': true});
     $('#sbRoot').ajaxEpSubtitlesSearch({'colorRow': true});
+    $('#sbRoot').ajaxHisttrunc({'colorRow': true});
 
     $('#seasonJump').change(function() {
         var id = $(this).val();
diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py
index 3dc8d4b4c..22a250bcb 100644
--- a/sickbeard/databases/mainDB.py
+++ b/sickbeard/databases/mainDB.py
@@ -25,7 +25,7 @@ from sickbeard.providers.generic import GenericProvider
 from sickbeard import encodingKludge as ek
 from sickbeard.name_parser.parser import NameParser, InvalidNameException
 
-MAX_DB_VERSION = 13
+MAX_DB_VERSION = 14
 
 
 class MainSanityCheck(db.DBSanityCheck):
@@ -100,7 +100,8 @@ class InitialSchema (db.SchemaUpgrade):
             "CREATE TABLE tv_shows (show_id INTEGER PRIMARY KEY, location TEXT, show_name TEXT, tvdb_id NUMERIC, network TEXT, genre TEXT, runtime NUMERIC, quality NUMERIC, airs TEXT, status TEXT, seasonfolders NUMERIC, paused NUMERIC, startyear NUMERIC);",
             "CREATE TABLE tv_episodes (episode_id INTEGER PRIMARY KEY, showid NUMERIC, tvdbid NUMERIC, name TEXT, season NUMERIC, episode NUMERIC, description TEXT, airdate NUMERIC, hasnfo NUMERIC, hastbn NUMERIC, status NUMERIC, location TEXT);",
             "CREATE TABLE info (last_backlog NUMERIC, last_tvdb NUMERIC);",
-            "CREATE TABLE history (action NUMERIC, date NUMERIC, showid NUMERIC, season NUMERIC, episode NUMERIC, quality NUMERIC, resource TEXT, provider NUMERIC);"
+            "CREATE TABLE history (action NUMERIC, date NUMERIC, showid NUMERIC, season NUMERIC, episode NUMERIC, quality NUMERIC, resource TEXT, provider NUMERIC);",
+            "CREATE TABLE episode_links (episode_id INTEGER, link TEXT);"
         ]
         for query in queries:
             self.connection.action(query)
@@ -697,3 +698,11 @@ class AddSubtitlesSupport(Add1080pAndRawHDQualities):
         self.addColumn("tv_episodes", "subtitles_searchcount")
         self.addColumn("tv_episodes", "subtitles_lastsearch", "TIMESTAMP", str(datetime.datetime.min))
         self.incDBVersion()
+        
+class AddSubtitlesSupport(AddSubtitlesSupport):    
+    def test(self):
+        return self.checkDBVersion() >= 14
+
+    def execute(self):
+        self.connection.action("CREATE TABLE episode_links (episode_id INTEGER, link TEXT)")
+        self.incDBVersion()
diff --git a/sickbeard/nzbSplitter.py b/sickbeard/nzbSplitter.py
index 048c8a59e..ab7eeba12 100644
--- a/sickbeard/nzbSplitter.py
+++ b/sickbeard/nzbSplitter.py
@@ -32,7 +32,7 @@ def getSeasonNZBs(name, urlData, season):
     try:
         showXML = etree.ElementTree(etree.XML(urlData))
     except SyntaxError:
-        logger.log(u"Unable to parse the XML of "+name+", not splitting it", logger.ERROR)
+        logger.log(u"Unable to parse the XML of "+name+", not splitting it", logger.DEBUG)
         return ({},'')
 
     filename = name.replace(".nzb", "")
diff --git a/sickbeard/providers/binnewz/nzbindex.py b/sickbeard/providers/binnewz/nzbindex.py
index b340c99a9..d2a0547b1 100644
--- a/sickbeard/providers/binnewz/nzbindex.py
+++ b/sickbeard/providers/binnewz/nzbindex.py
@@ -44,4 +44,4 @@ class NZBIndex(NZBDownloader):
                              
         for tr in results:
             nzblink = tr.find("a", text="Download")
-            return NZBGetURLSearchResult(self, nzblink.get("href"), None, refererURL)
+            return NZBGetURLSearchResult(self, nzblink.get("href"), None, nzblink.get("href"))
diff --git a/sickbeard/providers/cpasbien.py b/sickbeard/providers/cpasbien.py
index 9bfc47c36..0794f087e 100644
--- a/sickbeard/providers/cpasbien.py
+++ b/sickbeard/providers/cpasbien.py
@@ -143,7 +143,7 @@ class CpasbienSearchResult:
         self.title = title
         self.url = url
         self.quality = quality
-        self.audio_langs=[audio_langs]
+        self.audio_langs=audio_langs
         
     def getNZB(self):
         return self.opener.open( self.url , 'wb').read()
diff --git a/sickbeard/providers/gks.py b/sickbeard/providers/gks.py
index 32ac1a7b7..345a161a8 100644
--- a/sickbeard/providers/gks.py
+++ b/sickbeard/providers/gks.py
@@ -134,7 +134,7 @@ class GksSearchResult:
         self.title = title
         self.url = url
         self.quality = quality
-        self.audio_langs=[audio_langs]
+        self.audio_langs=audio_langs
 
     def getNZB(self):
         return self.opener.open( self.url , 'wb').read()
diff --git a/sickbeard/providers/t411.py b/sickbeard/providers/t411.py
index 5113e9a31..3faa8533c 100644
--- a/sickbeard/providers/t411.py
+++ b/sickbeard/providers/t411.py
@@ -139,7 +139,7 @@ class T411SearchResult:
         self.title = title
         self.url = url
         self.quality = quality
-        self.audio_langs=[audio_langs]
+        self.audio_langs=audio_langs
         
     def getNZB(self):
         return self.opener.open( self.url , 'wb').read()
diff --git a/sickbeard/search.py b/sickbeard/search.py
index cfc541c34..f6d87388b 100644
--- a/sickbeard/search.py
+++ b/sickbeard/search.py
@@ -23,8 +23,7 @@ import traceback
 
 import sickbeard
 
-from common import SNATCHED, Quality, SEASON_RESULT, MULTI_EP_RESULT
-
+from common import SNATCHED, Quality, SEASON_RESULT, MULTI_EP_RESULT,ARCHIVED, IGNORED, UNAIRED, WANTED, SKIPPED
 from sickbeard import logger, db, show_name_helpers, exceptions, helpers
 from sickbeard import sab
 from sickbeard import nzbget
@@ -124,48 +123,51 @@ def snatchEpisode(result, endStatus=SNATCHED):
     """
 
     # NZBs can be sent straight to SAB or saved to disk
-    if result.resultType in ("nzb", "nzbdata"):
-        if sickbeard.NZB_METHOD == "blackhole":
-            dlResult = _downloadResult(result)
-        elif sickbeard.NZB_METHOD == "sabnzbd":
-            dlResult = sab.sendNZB(result)
-        elif sickbeard.NZB_METHOD == "nzbget":
-            dlResult = nzbget.sendNZB(result)
+    if hasattr(result,'resultType'):
+        if result.resultType in ("nzb", "nzbdata"):
+            if sickbeard.NZB_METHOD == "blackhole":
+                dlResult = _downloadResult(result)
+            elif sickbeard.NZB_METHOD == "sabnzbd":
+                dlResult = sab.sendNZB(result)
+            elif sickbeard.NZB_METHOD == "nzbget":
+                dlResult = nzbget.sendNZB(result)
+            else:
+                logger.log(u"Unknown NZB action specified in config: " + sickbeard.NZB_METHOD, logger.ERROR)
+                dlResult = False
+    
+        # TORRENTs can be sent to clients or saved to disk
+        elif result.resultType in ("torrent", "torrentdata"):
+            # torrents are saved to disk when blackhole mode
+            if sickbeard.TORRENT_METHOD == "blackhole": 
+                dlResult = _downloadResult(result)
+            else:
+                client = clients.getClientIstance(sickbeard.TORRENT_METHOD)()
+                if hasattr(result,'extraInfo') and result.resultType=="torrentdata":
+                    result.content=result.extraInfo[0]
+                dlResult = client.sendTORRENT(result)
         else:
-            logger.log(u"Unknown NZB action specified in config: " + sickbeard.NZB_METHOD, logger.ERROR)
+            logger.log(u"Unknown result type, unable to download it", logger.ERROR)
             dlResult = False
-
-    # TORRENTs can be sent to clients or saved to disk
-    elif result.resultType in ("torrent", "torrentdata"):
-        # torrents are saved to disk when blackhole mode
-        if sickbeard.TORRENT_METHOD == "blackhole": 
-            dlResult = _downloadResult(result)
-        else:
-            client = clients.getClientIstance(sickbeard.TORRENT_METHOD)()
-            if hasattr(result,'extraInfo') and result.resultType=="torrentdata":
-                result.content=result.extraInfo[0]
-            dlResult = client.sendTORRENT(result)
+    
+        if dlResult == False:
+            return False
+    
+        history.logSnatch(result)
+    
+        # don't notify when we re-download an episode
+        for curEpObj in result.episodes:
+            with curEpObj.lock:
+                curEpObj.status = Quality.compositeStatus(endStatus, result.quality)
+                curEpObj.audio_langs = result.audio_lang
+                curEpObj.saveToDB()
+    
+            if curEpObj.status not in Quality.DOWNLOADED:
+                notifiers.notify_snatch(curEpObj.prettyName())
+    
+        return True
     else:
-        logger.log(u"Unknown result type, unable to download it", logger.ERROR)
-        dlResult = False
-
-    if dlResult == False:
         return False
 
-    history.logSnatch(result)
-
-    # don't notify when we re-download an episode
-    for curEpObj in result.episodes:
-        with curEpObj.lock:
-            curEpObj.status = Quality.compositeStatus(endStatus, result.quality)
-            curEpObj.audio_langs = result.audio_lang
-            curEpObj.saveToDB()
-
-        if curEpObj.status not in Quality.DOWNLOADED:
-            notifiers.notify_snatch(curEpObj.prettyName())
-
-    return True
-
 def searchForNeededEpisodes():
 
     logger.log(u"Searching all providers for any needed episodes")
@@ -221,32 +223,68 @@ def searchForNeededEpisodes():
     return foundResults.values()
 
 
-def pickBestResult(results, quality_list=None):
+def pickBestResult(results, quality_list=None, episode=None):
 
     logger.log(u"Picking the best result out of "+str([x.name for x in results]), logger.DEBUG)
-
+    links=[]
+    myDB = db.DBConnection()
+    for eps in episode.values():
+        if hasattr(eps,'tvdbid'):
+            epidr=myDB.select("SELECT episode_id from tv_episodes where tvdbid=?",[eps.tvdbid])
+            listlink=myDB.select("SELECT link from episode_links where episode_id=?",[epidr[0][0]])
+            for dlink in listlink:
+                links.append(dlink[0])
     # find the best result for the current episode
-    bestResult = None
-    for cur_result in results:
-        logger.log("Quality of "+cur_result.name+" is "+Quality.qualityStrings[cur_result.quality])
+        bestResult = None
+        for cur_result in results:
+            if hasattr(cur_result,'item'):
+                if hasattr(cur_result.item,'nzburl'):
+                    eplink=cur_result.item.nzburl
+                else:
+                    eplink=cur_result.item.url
+            else:
+                if hasattr(cur_result,'nzburl'):
+                    eplink=cur_result.nzburl
+                else:
+                    eplink=cur_result.url
+            logger.log("Quality of "+cur_result.name+" is "+Quality.qualityStrings[cur_result.quality])
         
-        if quality_list and cur_result.quality not in quality_list:
-            logger.log(cur_result.name+" is a quality we know we don't want, rejecting it", logger.DEBUG)
-            continue
+            if quality_list and cur_result.quality not in quality_list:
+                logger.log(cur_result.name+" is a quality we know we don't want, rejecting it", logger.DEBUG)
+                continue
         
-        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
-            bestResult = cur_result
-        elif bestResult.quality == cur_result.quality:
-            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
-                bestResult = cur_result
-            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
+            if eplink in links:
+                logger.log(eplink +" was already downloaded so let's skip it assuming the download failed, you can erase the downloaded links for that episode if you want", logger.DEBUG)
+                continue
+        
+            if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
                 bestResult = cur_result
-
-    if bestResult:
-        logger.log(u"Picked "+bestResult.name+" as the best", logger.DEBUG)
-    else:
-        logger.log(u"No result picked.", logger.DEBUG)
-
+            
+            elif bestResult.quality == cur_result.quality:
+                if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
+                    bestResult = cur_result
+                elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
+                    bestResult = cur_result
+       
+        if bestResult:
+            logger.log(u"Picked "+bestResult.name+" as the best", logger.DEBUG)
+        
+            if hasattr(bestResult,'item'):
+                if hasattr(bestResult.item,'nzburl'):
+                    eplink=bestResult.item.nzburl
+                else:
+                    eplink=bestResult.item.url
+            else:
+                if hasattr(bestResult,'nzburl'):
+                    eplink=bestResult.nzburl
+                else:
+                    eplink=bestResult.url
+            count=myDB.select("SELECT count(*) from episode_links where episode_id=? and link=?",[epidr[0][0],eplink])
+            if count[0][0]==0:
+                myDB.action("INSERT INTO episode_links (episode_id, link) VALUES (?,?)",[epidr[0][0],eplink])
+        else:
+            logger.log(u"No result picked.", logger.DEBUG)
+    
     return bestResult
 
 def isFinalResult(result):
@@ -331,202 +369,224 @@ def findEpisode(episode, manualSearch=False):
 
     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)
-
+    epi={}
+    epi[1]=episode
+    bestResult = pickBestResult(foundResults,episode=epi)
     return bestResult
 
 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: "+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
-
-    if not didSearch:
-        logger.log(u"No NZB/Torrent providers found or enabled in the sickbeard config. Please check your settings.", logger.ERROR)
+    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 = []
-
-    anyQualities, bestQualities = Quality.splitQuality(show.quality)
-
-    # pick the best season NZB
-    bestSeasonNZB = None
-    if SEASON_RESULT in foundResults:
-        bestSeasonNZB = pickBestResult(foundResults[SEASON_RESULT], anyQualities+bestQualities)
-
-    highest_quality_overall = 0
-    for cur_season in foundResults:
-        for cur_result in foundResults[cur_season]:
-            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], logger.DEBUG)
-
-    # see if every episode is wanted
-    if bestSeasonNZB:
-
-        # get the quality of the season nzb
-        seasonQual = Quality.nameQuality(bestSeasonNZB.name)
-        seasonQual = bestSeasonNZB.quality
-        logger.log(u"The quality of the season NZB is "+Quality.qualityStrings[seasonQual], logger.DEBUG)
-
-        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)
-
-        allWanted = True
-        anyWanted = False
-        for curEpNum in allEps:
-            if not show.wantEpisode(season, curEpNum, seasonQual):
-                allWanted = False
-            else:
-                anyWanted = True
-
-        # if we need every ep in the season and there's nothing better then just download this and be done with it
-        if allWanted and bestSeasonNZB.quality == highest_quality_overall:
-            logger.log(u"Every ep in this season is needed, downloading the whole NZB "+bestSeasonNZB.name)
-            epObjs = []
-            for curEpNum in allEps:
-                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)
-
+    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:
-            
-            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)
+            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[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:
-                
-                # Season result from BTN must be a full-season torrent, creating multi-ep result for it.
-                logger.log(u"Adding multi-ep result for full-season torrent. Set the episodes you don't want to 'don't download' in your torrent client if desired!")
+                        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
+    
+        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)
+    
+        # pick the best season NZB
+        bestSeasonNZB = None
+        if SEASON_RESULT in foundResults:
+            bestSeasonNZB = pickBestResult(foundResults[SEASON_RESULT], anyQualities+bestQualities,episode=show.episodes[1])
+    
+        highest_quality_overall = 0
+        for cur_season in foundResults:
+            for cur_result in foundResults[cur_season]:
+                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], logger.DEBUG)
+    
+        # see if every episode is wanted
+        if bestSeasonNZB:
+    
+            # get the quality of the season nzb
+            seasonQual = Quality.nameQuality(bestSeasonNZB.name)
+            seasonQual = bestSeasonNZB.quality
+            logger.log(u"The quality of the season NZB is "+Quality.qualityStrings[seasonQual], logger.DEBUG)
+    
+            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)
+    
+            allWanted = True
+            anyWanted = False
+            for curEpNum in allEps:
+                if not show.wantEpisode(season, curEpNum, seasonQual):
+                    allWanted = False
+                else:
+                    anyWanted = True
+    
+            # if we need every ep in the season and there's nothing better then just download this and be done with it
+            if allWanted and bestSeasonNZB.quality == highest_quality_overall:
+                logger.log(u"Every ep in this season is needed, downloading the whole NZB "+bestSeasonNZB.name)
                 epObjs = []
                 for curEpNum in allEps:
                     epObjs.append(show.getEpisode(season, curEpNum))
                 bestSeasonNZB.episodes = epObjs
-
-                epNum = MULTI_EP_RESULT
-                if epNum in foundResults:
-                    foundResults[epNum].append(bestSeasonNZB)
-                else:
-                    foundResults[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:
-        for multiResult in foundResults[MULTI_EP_RESULT]:
-
-            logger.log(u"Seeing if we want to bother with multi-episode result "+multiResult.name, logger.DEBUG)
-
-            # see how many of the eps that this result covers aren't covered by single results
-            neededEps = []
-            notNeededEps = []
-            for epObj in multiResult.episodes:
-                epNum = epObj.episode
-                # if we have results for the episode
-                if epNum in foundResults and len(foundResults[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:
-                    neededEps.append(epNum)
+                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), 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:
-                    neededEps.append(epNum)
-
-            logger.log(u"Single-ep check result is neededEps: "+str(neededEps)+", notNeededEps: "+str(notNeededEps), logger.DEBUG)
-
-            if not neededEps:
-                logger.log(u"All of these episodes were covered by single nzbs, ignoring this multi-ep result", logger.DEBUG)
+                    
+                    # Season result from BTN must be a full-season torrent, creating multi-ep result for it.
+                    logger.log(u"Adding multi-ep result for full-season torrent. Set the episodes you don't want to 'don't download' in your torrent client if desired!")
+                    epObjs = []
+                    for curEpNum in allEps:
+                        epObjs.append(show.getEpisode(season, curEpNum))
+                    bestSeasonNZB.episodes = epObjs
+    
+                    epNum = MULTI_EP_RESULT
+                    if epNum in foundResults:
+                        foundResults[epNum].append(bestSeasonNZB)
+                    else:
+                        foundResults[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:
+            for multiResult in foundResults[MULTI_EP_RESULT]:
+    
+                logger.log(u"Seeing if we want to bother with multi-episode result "+multiResult.name, logger.DEBUG)
+    
+                # see how many of the eps that this result covers aren't covered by single results
+                neededEps = []
+                notNeededEps = []
+                for epObj in multiResult.episodes:
+                    epNum = epObj.episode
+                    # if we have results for the episode
+                    if epNum in foundResults and len(foundResults[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:
+                        neededEps.append(epNum)
+                    else:
+                        neededEps.append(epNum)
+    
+                logger.log(u"Single-ep check result is neededEps: "+str(neededEps)+", notNeededEps: "+str(notNeededEps), logger.DEBUG)
+    
+                if not neededEps:
+                    logger.log(u"All of these episodes were covered by single nzbs, ignoring this multi-ep result", logger.DEBUG)
+                    continue
+    
+                # check if these eps are already covered by another multi-result
+                multiNeededEps = []
+                multiNotNeededEps = []
+                for epObj in multiResult.episodes:
+                    epNum = epObj.episode
+                    if epNum in multiResults:
+                        multiNotNeededEps.append(epNum)
+                    else:
+                        multiNeededEps.append(epNum)
+    
+                logger.log(u"Multi-ep check result is multiNeededEps: "+str(multiNeededEps)+", multiNotNeededEps: "+str(multiNotNeededEps), logger.DEBUG)
+    
+                if not multiNeededEps:
+                    logger.log(u"All of these episodes were covered by another multi-episode nzbs, ignoring this multi-ep result", logger.DEBUG)
+                    continue
+    
+                # if we're keeping this multi-result then remember it
+                for epObj in multiResult.episodes:
+                    multiResults[epObj.episode] = multiResult
+    
+                # 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:
+                        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[epNum]
+    
+        finalResults += set(multiResults.values())
+    
+        # of all the single ep results narrow it down to the best one for each episode
+        for curEp in foundResults:
+            if curEp in (MULTI_EP_RESULT, SEASON_RESULT):
                 continue
-
-            # check if these eps are already covered by another multi-result
-            multiNeededEps = []
-            multiNotNeededEps = []
-            for epObj in multiResult.episodes:
-                epNum = epObj.episode
-                if epNum in multiResults:
-                    multiNotNeededEps.append(epNum)
-                else:
-                    multiNeededEps.append(epNum)
-
-            logger.log(u"Multi-ep check result is multiNeededEps: "+str(multiNeededEps)+", multiNotNeededEps: "+str(multiNotNeededEps), logger.DEBUG)
-
-            if not multiNeededEps:
-                logger.log(u"All of these episodes were covered by another multi-episode nzbs, ignoring this multi-ep result", logger.DEBUG)
+    
+            if len(foundResults[curEp]) == 0:
                 continue
-
-            # if we're keeping this multi-result then remember it
-            for epObj in multiResult.episodes:
-                multiResults[epObj.episode] = multiResult
-
-            # 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:
-                    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[epNum]
-
-    finalResults += set(multiResults.values())
-
-    # of all the single ep results narrow it down to the best one for each episode
-    for curEp in foundResults:
-        if curEp in (MULTI_EP_RESULT, SEASON_RESULT):
-            continue
-
-        if len(foundResults[curEp]) == 0:
-            continue
-
-        finalResults.append(pickBestResult(foundResults[curEp]))
-
-    return finalResults
+            print curEp
+            finalResults.append(pickBestResult(foundResults[curEp],None,episode=show.episodes[1]))
+    
+        return finalResults
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index deaa2cc2d..65a92316f 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -3162,6 +3162,16 @@ class Home:
 
         redirect("/home/displayShow?show=" + show)
 
+    @cherrypy.expose
+    def trunchistory(self, epid):
+        
+        myDB = db.DBConnection()
+        nbep = myDB.select("Select count(*) from episode_links where episode_id=?",[epid])
+        myDB.action("DELETE from episode_links where episode_id=?",[epid])
+        messnum = str(nbep[0][0]) + ' history links deleted'
+        ui.notifications.message('Episode History Truncated' , messnum)
+        return json.dumps({'result': 'ok'})
+    
     @cherrypy.expose
     def searchEpisode(self, show=None, season=None, episode=None):
 
-- 
GitLab