diff --git a/data/interfaces/default/config_search.tmpl b/data/interfaces/default/config_search.tmpl index b4c1d816abddde69492dff3fa9582684765341f7..1b63b585d52b6c776aba476f4d018193b1e18070 100644 --- a/data/interfaces/default/config_search.tmpl +++ b/data/interfaces/default/config_search.tmpl @@ -42,10 +42,18 @@ <input type="checkbox" name="download_propers" id="download_propers" #if $sickbeard.DOWNLOAD_PROPERS == True then "checked=\"checked\"" else ""# /> <label class="clearfix" for="download_propers"> <span class="component-title">Download Propers</span> - <span class="component-desc">Replace original download with "Proper/Repack" if nuked?</span> + <span class="component-desc">Replace original download with "Proper/Repack" if nuked? Needs restart</span> </label> </div> - + + <div class="field-pair"> + <input type="checkbox" name="download_french" id="download_french" #if $sickbeard.DOWNLOAD_FRENCH == True then "checked=\"checked\"" else ""# /> + <label class="clearfix" for="download_french"> + <span class="component-title">Auto download French</span> + <span class="component-desc">Replace non french downloads with French ones if they exist even if audio is English (for the show where option is activated, will check every weeks). Needs restart</span> + </label> + </div> + <div class="field-pair"> <label class="nocheck clearfix"> <span class="component-title">Search Frequency</span> diff --git a/data/interfaces/default/displayShow.tmpl b/data/interfaces/default/displayShow.tmpl index c139eaee4d7f7883af87b5d0abedafb8747f544a..5a83780ba04109956ee289701404f7829814fdeb 100644 --- a/data/interfaces/default/displayShow.tmpl +++ b/data/interfaces/default/displayShow.tmpl @@ -195,8 +195,12 @@ #end if <tr><td class="showLegend">Info Language:</td><td><img src="$sbRoot/images/flags/${show.lang}.png" width="16" height="11" alt="$show.lang" title="$show.lang" /></td></tr> + #if int($show.frenchsearch) == 1 + <tr><td class="showLegend">Audio Language:</td><td><img src="$sbRoot/images/flags/${show.audio_lang}.png" width="16" height="11" alt="$show.audio_lang" title="$show.lang" /> <img src="$sbRoot/images/flags/fr.png" width="16" height="11" alt="fr" title="fr" /></td></tr> + #else <tr><td class="showLegend">Audio Language:</td><td><img src="$sbRoot/images/flags/${show.audio_lang}.png" width="16" height="11" alt="$show.audio_lang" title="$show.lang" /></td></tr> - <tr><td class="showLegend">Custom Names :</td><td>#if $show.exceptions then $exceptions_string else $show.name#</td></tr> + #end if + <tr><td class="showLegend">Custom Names :</td><td>#if $show.exceptions then $exceptions_string else $show.name#</td></tr> #if $show.imdbid: #if $show.imdb_info['rating'] !='': <tr><td class="showLegend">Rating :</td><td>$show.imdb_info['rating']</td></tr> @@ -206,7 +210,7 @@ #else: <tr><td class="showLegend">No Rating</td><td></td></tr> #end if - </td></tr> + </td></tr> </table> <td width="25%"> <table> diff --git a/data/interfaces/default/editShow.tmpl b/data/interfaces/default/editShow.tmpl index bf721d5ab58a9a1dc92162440ae310728e15bf17..9990ccfe06d528ef11217a298c6d11e323d72fdf 100644 --- a/data/interfaces/default/editShow.tmpl +++ b/data/interfaces/default/editShow.tmpl @@ -125,6 +125,7 @@ selected <table> <b>Flatten files (no folders):</b> <input type="checkbox" name="flatten_folders" #if $show.flatten_folders == 1 and not $sickbeard.NAMING_FORCE_FOLDERS then "checked=\"checked\"" else ""# #if $sickbeard.NAMING_FORCE_FOLDERS then "disabled=\"disabled\"" else ""#/><br /><br /> <b>Paused:</b> <input type="checkbox" name="paused" #if $show.paused == 1 then "checked=\"checked\"" else ""# /><br /><br /> +<b>French Search (auto) :</b> <input type="checkbox" name="frenchsearch" #if $show.frenchsearch == 1 and $sickbeard.DOWNLOAD_FRENCH then "checked=\"checked\"" else ""##if not $sickbeard.DOWNLOAD_FRENCH then " disabled=\"disabled\"" else ""# /><br /><br /> <b>Subtitles:</b> <input type="checkbox" name="subtitles"#if $show.subtitles == 1 and $sickbeard.USE_SUBTITLES then " checked=\"checked\"" else ""##if not $sickbeard.USE_SUBTITLES then " disabled=\"disabled\"" else ""#/><br /><br /> <b>Air by date: </b> diff --git a/data/interfaces/default/history.tmpl b/data/interfaces/default/history.tmpl index 759101f2c91baa6b37ee903592a092b163c971c4..aa7ca1cb14a860ad2141ee460da30078a8646ceb 100644 --- a/data/interfaces/default/history.tmpl +++ b/data/interfaces/default/history.tmpl @@ -53,7 +53,11 @@ #set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($hItem["action"])) <tr> <td class="nowrap">$datetime.datetime.strptime(str($hItem["date"]), $history.dateFormat)</td> + #if "snatchedfr" in $hItem["resource"].lower + <td width="35%"><a style="color: #000000; text-align: center;" href="$sbRoot/home/displayShow?show=$hItem["showid"]#season-$hItem["season"]">$hItem["show_name"] - <%=str(hItem["season"]) +"x"+ "%02i" % int(hItem["episode"]) %> <span class="quality Proper">French</span></a></td> + #else <td width="35%"><a style="color: #000000; text-align: center;" href="$sbRoot/home/displayShow?show=$hItem["showid"]#season-$hItem["season"]">$hItem["show_name"] - <%=str(hItem["season"]) +"x"+ "%02i" % int(hItem["episode"]) %>#if "proper" in $hItem["resource"].lower or "repack" in $hItem["resource"].lower then ' <span class="quality Proper">Proper</span>' else ""#</a></td> + #end if <td align="center" #if $curStatus == SUBTITLED then 'class="subtitles_column"' else ''#><span style="cursor: help;" title="$os.path.basename($hItem["resource"])">$statusStrings[$curStatus]</span> #if $curStatus == SUBTITLED: <img width="16" height="11" src="/images/flags/<%= hItem["resource"][len(hItem["resource"])-6:len(hItem["resource"])-4]+'.png'%>"> diff --git a/data/interfaces/default/home.tmpl b/data/interfaces/default/home.tmpl index 97e911181f11a24a2b82821a188b57094f8deae7..89acd89411541e68e4a4a16fc9019ba067ed71c8 100644 --- a/data/interfaces/default/home.tmpl +++ b/data/interfaces/default/home.tmpl @@ -14,10 +14,10 @@ #set $myDB = $db.DBConnection() #set $today = str($datetime.date.today().toordinal()) -#set $downloadedEps = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE (status IN ("+",".join([str(x) for x in $Quality.DOWNLOADED + [$ARCHIVED]])+") OR (status IN ("+",".join([str(x) for x in $Quality.SNATCHED + $Quality.SNATCHED_PROPER])+") AND location != '')) AND season != 0 and episode != 0 AND airdate <= "+$today+" GROUP BY showid") -#set $snatchedEps = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE (status IN ("+",".join([str(x) for x in $Quality.SNATCHED + [$ARCHIVED]])+") OR (status IN ("+",".join([str(x) for x in $Quality.SNATCHED + $Quality.SNATCHED_PROPER])+") AND location != '')) AND season != 0 and episode != 0 AND airdate <= "+$today+" GROUP BY showid") -#set $wantedEps = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE (status IN ("+",".join([str(x) for x in $Quality.WANTED + [$ARCHIVED]])+") OR (status IN ("+",".join([str(x) for x in $Quality.SNATCHED + $Quality.SNATCHED_PROPER])+") AND location != '')) AND season != 0 and episode != 0 AND airdate <= "+$today+" GROUP BY showid") -#set $allEps = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE season != 0 and episode != 0 AND (airdate != 1 OR status IN ("+",".join([str(x) for x in ($Quality.DOWNLOADED + $Quality.SNATCHED + $Quality.SNATCHED_PROPER) + [$ARCHIVED]])+")) AND airdate <= "+$today+" AND status != "+str($IGNORED)+" GROUP BY showid") +#set $downloadedEps = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE (status IN ("+",".join([str(x) for x in $Quality.DOWNLOADED + [$ARCHIVED]])+") OR (status IN ("+",".join([str(x) for x in $Quality.SNATCHED + $Quality.SNATCHED_PROPER + $Quality.SNATCHED_FRENCH])+") AND location != '')) AND season != 0 and episode != 0 AND airdate <= "+$today+" GROUP BY showid") +#set $snatchedEps = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE (status IN ("+",".join([str(x) for x in $Quality.SNATCHED + [$ARCHIVED]])+") OR (status IN ("+",".join([str(x) for x in $Quality.SNATCHED + $Quality.SNATCHED_PROPER + $Quality.SNATCHED_FRENCH])+") AND location != '')) AND season != 0 and episode != 0 AND airdate <= "+$today+" GROUP BY showid") +#set $wantedEps = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE (status IN ("+",".join([str(x) for x in $Quality.WANTED + [$ARCHIVED]])+") OR (status IN ("+",".join([str(x) for x in $Quality.SNATCHED + $Quality.SNATCHED_PROPER + $Quality.SNATCHED_FRENCH])+") AND location != '')) AND season != 0 and episode != 0 AND airdate <= "+$today+" GROUP BY showid") +#set $allEps = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE season != 0 and episode != 0 AND (airdate != 1 OR status IN ("+",".join([str(x) for x in ($Quality.DOWNLOADED + $Quality.SNATCHED + $Quality.SNATCHED_PROPER + $Quality.SNATCHED_FRENCH) + [$ARCHIVED]])+")) AND airdate <= "+$today+" AND status != "+str($IGNORED)+" GROUP BY showid") #set $fr = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE audio_langs = 'fr' AND location != '' AND season != 0 and episode != 0 AND airdate <= "+$today+" GROUP BY showid") #set $subfr = $myDB.select("SELECT showid, COUNT(*) FROM tv_episodes WHERE audio_langs <> 'fr' AND subtitles like '%fr%' AND location != '' AND season != 0 and episode != 0 AND airdate <= "+$today+" GROUP BY showid") #set $layout = $sickbeard.HOME_LAYOUT @@ -345,8 +345,12 @@ function setLayout(imdb,name){ subfr : "$nomSub", downloads : setPbDl($nom,$nomSna,$den), frenchep : setPbFr($nomfr,$nomSub,$denfr), - active : "$active", - audio : "<img src=\"$sbRoot/images/flags/${curShow.audio_lang}.png\" alt=\"$curShow.audio_lang\" width=\"16\" />", + active : "$active", + #if int($curShow.frenchsearch) == 1 + audio : "<img src=\"$sbRoot/images/flags/${curShow.audio_lang}.png\" alt=\"$curShow.audio_lang\" width=\"16\" /> <img src=\"$sbRoot/images/flags/fr.png\" alt=\"fr\" width=\"16\" />", + #else + audio : "<img src=\"$sbRoot/images/flags/${curShow.audio_lang}.png\" alt=\"$curShow.audio_lang\" width=\"16\" />", + #end if status : "$curShow.status" }, #end for diff --git a/data/interfaces/default/inc_top.tmpl b/data/interfaces/default/inc_top.tmpl index cdbdeb6af3fbbe098490961876dca8fdcce5d889..0b9b1cf47d5e5d2fe7cb47f92a7ed3f81aa064b6 100644 --- a/data/interfaces/default/inc_top.tmpl +++ b/data/interfaces/default/inc_top.tmpl @@ -102,6 +102,7 @@ \$("#SubMenu a[href='/home/updatePLEX/']").addClass('btn').html('<span class="ui-icon ui-icon-refresh pull-left"></span> Update PLEX </a>'); \$("#SubMenu a:contains('Force')").addClass('btn').html('<span class="ui-icon ui-icon-transfer-e-w pull-left"></span> Force Full Update </a>'); \$("#SubMenu a:contains('Rename')").addClass('btn').html('<span class="ui-icon ui-icon-tag pull-left"></span> Preview Rename </a>'); + \$("#SubMenu a:contains('French')").addClass('btn').html('<span class="ui-icon ui-icon-refresh pull-left"></span> French Search </a>'); \$("#SubMenu a[href='/config/subtitles/']").addClass('btn').html('<span class="ui-icon ui-icon-comment pull-left"></span> Search Subtitles </a>'); \$("#SubMenu a[href^='/home/subtitleShow']").addClass('btn').html('<span class="ui-icon ui-icon-comment pull-left"></span> Download Subtitles </a>'); \$("#SubMenu a[href^='/home/subtitleShowClean']").addClass('btn').html('<span class="ui-icon ui-icon-comment pull-left"></span> Clean Subtitles </a>'); diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 26991d04dab90dd4f4e422b129d689989f93096f..b35026db2bc0524874e694ad0072d0faa84b4c73 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -33,7 +33,7 @@ from sickbeard import providers, metadata from providers import ezrss, tvtorrents, torrentleech, btn, nzbsrus, newznab, womble, nzbx, omgwtfnzbs, binnewz, t411, cpasbien, piratebay, gks, kat from sickbeard.config import CheckSection, check_setting_int, check_setting_str, ConfigMigrator -from sickbeard import searchCurrent, searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser, subtitles, traktWatchListChecker, SentFTPChecker +from sickbeard import searchCurrent, searchBacklog, showUpdater, versionChecker, properFinder, frenchFinder, autoPostProcesser, subtitles, traktWatchListChecker, SentFTPChecker from sickbeard import helpers, db, exceptions, show_queue, search_queue, scheduler from sickbeard import logger from sickbeard import naming @@ -74,6 +74,7 @@ showUpdateScheduler = None versionCheckScheduler = None showQueueScheduler = None searchQueueScheduler = None +frenchFinderScheduler = None properFinderScheduler = None autoPostProcesserScheduler = None autoTorrentPostProcesserScheduler = None @@ -156,6 +157,7 @@ USENET_RETENTION = None TORRENT_METHOD = None TORRENT_DIR = None DOWNLOAD_PROPERS = None +DOWNLOAD_FRENCH = None PREFERED_METHOD = None SEARCH_FREQUENCY = None BACKLOG_SEARCH_FREQUENCY = 1 @@ -427,7 +429,7 @@ def initialize(consoleLogging=True): with INIT_LOCK: global LOG_DIR, WEB_PORT, WEB_LOG, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, USE_API, API_KEY, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \ - USE_NZBS, USE_TORRENTS, NZB_METHOD, NZB_DIR, DOWNLOAD_PROPERS, TORRENT_METHOD, PREFERED_METHOD, \ + USE_NZBS, USE_TORRENTS, NZB_METHOD, NZB_DIR, DOWNLOAD_PROPERS, DOWNLOAD_FRENCH, TORRENT_METHOD, PREFERED_METHOD, \ SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_HOST, \ NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_HOST, currentSearchScheduler, backlogSearchScheduler, \ TORRENT_USERNAME, TORRENT_PASSWORD, TORRENT_HOST, TORRENT_PATH, TORRENT_RATIO, TORRENT_PAUSED, TORRENT_LABEL, \ @@ -456,7 +458,7 @@ def initialize(consoleLogging=True): KEEP_PROCESSED_DIR, PROCESS_METHOD, TV_DOWNLOAD_DIR, TORRENT_DOWNLOAD_DIR, TVDB_BASE_URL, MIN_SEARCH_FREQUENCY, \ showQueueScheduler, searchQueueScheduler, ROOT_DIRS, CACHE_DIR, ACTUAL_CACHE_DIR, TVDB_API_PARMS, \ NAMING_PATTERN, NAMING_MULTI_EP, NAMING_FORCE_FOLDERS, NAMING_ABD_PATTERN, NAMING_CUSTOM_ABD, \ - RENAME_EPISODES, properFinderScheduler, PROVIDER_ORDER, autoPostProcesserScheduler, autoTorrentPostProcesserScheduler, \ + RENAME_EPISODES, frenchFinderScheduler, properFinderScheduler, PROVIDER_ORDER, autoPostProcesserScheduler, autoTorrentPostProcesserScheduler, \ NZBSRUS, NZBSRUS_UID, NZBSRUS_HASH, WOMBLE, NZBX, NZBX_COMPLETION, OMGWTFNZBS, OMGWTFNZBS_UID, OMGWTFNZBS_KEY, providerList, newznabProviderList, \ EXTRA_SCRIPTS, USE_TWITTER, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, \ USE_NOTIFO, NOTIFO_USERNAME, NOTIFO_APISECRET, NOTIFO_NOTIFY_ONDOWNLOAD, NOTIFO_NOTIFY_ONSUBTITLEDOWNLOAD, NOTIFO_NOTIFY_ONSNATCH, \ @@ -575,6 +577,7 @@ def initialize(consoleLogging=True): PREFERED_METHOD = 'nzb' DOWNLOAD_PROPERS = bool(check_setting_int(CFG, 'General', 'download_propers', 1)) + DOWNLOAD_FRENCH = bool(check_setting_int(CFG, 'General', 'download_french', 0)) USENET_RETENTION = check_setting_int(CFG, 'General', 'usenet_retention', 500) SEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'search_frequency', DEFAULT_SEARCH_FREQUENCY) if SEARCH_FREQUENCY < MIN_SEARCH_FREQUENCY: @@ -999,6 +1002,11 @@ def initialize(consoleLogging=True): cycleTime=properFinderInstance.updateInterval, threadName="FINDPROPERS", runImmediately=False) + + frenchFinderScheduler = scheduler.Scheduler(frenchFinder.FrenchFinder(), + cycleTime=datetime.timedelta(minutes=10080), + threadName="FINDFRENCH", + runImmediately=True) if PROCESS_AUTOMATICALLY: autoPostProcesserScheduler = scheduler.Scheduler(autoPostProcesser.PostProcesser( TV_DOWNLOAD_DIR ), @@ -1046,7 +1054,7 @@ def start(): global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, \ showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ - properFinderScheduler, autoPostProcesserScheduler, autoTorrentPostProcesserScheduler, searchQueueScheduler, \ + frenchFinderScheduler, properFinderScheduler, autoPostProcesserScheduler, autoTorrentPostProcesserScheduler, searchQueueScheduler, \ subtitlesFinderScheduler, started, USE_SUBTITLES, \ traktWatchListCheckerSchedular, started, \ sentFTPSchedular, started @@ -1072,7 +1080,9 @@ def start(): # start the search queue checker searchQueueScheduler.thread.start() - + + if DOWNLOAD_FRENCH: + frenchFinderScheduler.thread.start() # start the queue checker if DOWNLOAD_PROPERS: properFinderScheduler.thread.start() @@ -1101,7 +1111,7 @@ def start(): def halt(): global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, showUpdateScheduler, \ - showQueueScheduler, properFinderScheduler, autoPostProcesserScheduler, autoTorrentPostProcesserScheduler, searchQueueScheduler, \ + showQueueScheduler, frenchFinderScheduler, properFinderScheduler, autoPostProcesserScheduler, autoTorrentPostProcesserScheduler, searchQueueScheduler, \ subtitlesFinderScheduler, started, \ traktWatchListCheckerSchedular @@ -1193,7 +1203,16 @@ def halt(): properFinderScheduler.thread.join(10) except: pass - + + if frenchFinderScheduler: + frenchFinderScheduler.abort = True + logger.log(u"Waiting for the FRENCHFINDER thread to exit") + try: + frenchFinderScheduler.thread.join(10) + except: + pass + + if subtitlesFinderScheduler: subtitlesFinderScheduler.abort = True logger.log(u"Waiting for the SUBTITLESFINDER thread to exit") try: @@ -1321,6 +1340,7 @@ def save_config(): new_config['General']['usenet_retention'] = int(USENET_RETENTION) new_config['General']['search_frequency'] = int(SEARCH_FREQUENCY) new_config['General']['download_propers'] = int(DOWNLOAD_PROPERS) + new_config['General']['download_french'] = int(DOWNLOAD_FRENCH) new_config['General']['quality_default'] = int(QUALITY_DEFAULT) new_config['General']['status_default'] = int(STATUS_DEFAULT) new_config['General']['audio_show_default'] = AUDIO_SHOW_DEFAULT diff --git a/sickbeard/common.py b/sickbeard/common.py index f2f8d840ba020ba66c9ff6ba690d51eb10eeba59..83facaddd5264b7c69b65a8b30369659b950bc2b 100644 --- a/sickbeard/common.py +++ b/sickbeard/common.py @@ -58,6 +58,7 @@ ARCHIVED = 6 # episodes that you don't have locally (counts toward download comp IGNORED = 7 # episodes that you don't want included in your download stats SNATCHED_PROPER = 9 # qualified with quality SUBTITLED = 10 # qualified with quality +SNATCHED_FRENCH = 11 # episodes downloaded in english then autodownloaded in french NAMING_REPEAT = 1 NAMING_EXTEND = 2 @@ -220,11 +221,13 @@ class Quality: DOWNLOADED = None SNATCHED = None SNATCHED_PROPER = None + SNATCHED_FRENCH = None WANTED = None Quality.DOWNLOADED = [Quality.compositeStatus(DOWNLOADED, x) for x in Quality.qualityStrings.keys()] Quality.SNATCHED = [Quality.compositeStatus(SNATCHED, x) for x in Quality.qualityStrings.keys()] Quality.SNATCHED_PROPER = [Quality.compositeStatus(SNATCHED_PROPER, x) for x in Quality.qualityStrings.keys()] +Quality.SNATCHED_FRENCH = [Quality.compositeStatus(SNATCHED_FRENCH, x) for x in Quality.qualityStrings.keys()] Quality.WANTED = [Quality.compositeStatus(WANTED, x) for x in Quality.qualityStrings.keys()] SD = Quality.combineQualities([Quality.SDTV, Quality.SDDVD], []) @@ -252,13 +255,14 @@ class StatusStrings: DOWNLOADED: "Downloaded", SKIPPED: "Skipped", SNATCHED_PROPER: "Snatched (Proper)", + SNATCHED_FRENCH: "Snatched (French)", WANTED: "Wanted", ARCHIVED: "Archived", IGNORED: "Ignored", SUBTITLED: "Subtitled"} def __getitem__(self, name): - if name in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER: + if name in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH: status, quality = Quality.splitCompositeStatus(name) if quality == Quality.NONE: return self.statusStrings[status] @@ -268,7 +272,7 @@ class StatusStrings: return self.statusStrings[name] def has_key(self, name): - return name in self.statusStrings or name in Quality.DOWNLOADED or name in Quality.SNATCHED or name in Quality.SNATCHED_PROPER + return name in self.statusStrings or name in Quality.DOWNLOADED or name in Quality.SNATCHED or name in Quality.SNATCHED_PROPER or name in Quality.SNATCHED_FRENCH statusStrings = StatusStrings() @@ -280,7 +284,7 @@ class Overview: SKIPPED = SKIPPED # 5 # For both snatched statuses. Note: SNATCHED/QUAL have same value and break dict. - SNATCHED = SNATCHED_PROPER # 9 + SNATCHED = SNATCHED_PROPER = SNATCHED_FRENCH # 9 overviewStrings = {SKIPPED: "skipped", WANTED: "wanted", diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py index 6295a80502cc79a64271fc67600b3701b5e14b99..7f4c747de4dec3f633e8c3a91d15ad9daa4ce3f0 100644 --- a/sickbeard/databases/mainDB.py +++ b/sickbeard/databases/mainDB.py @@ -97,7 +97,7 @@ class InitialSchema (db.SchemaUpgrade): def execute(self): queries = [ - "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_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, frenchsearch 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);", @@ -357,8 +357,15 @@ class AddLang (FixSabHostURL): def execute(self): self.addColumn("tv_shows", "lang", "TEXT", "fr") + +class AddFrenchSearch (AddLang): + def test(self): + return self.hasColumn("tv_shows", "frenchsearch") + + def execute(self): + self.addColumn("tv_shows", "frenchsearch", "NUMERIC", 0) -class AddCustomSearchNames (AddLang): +class AddCustomSearchNames (AddFrenchSearch): def test(self): return self.hasColumn("tv_shows", "custom_search_names") diff --git a/sickbeard/frenchFinder.py b/sickbeard/frenchFinder.py new file mode 100644 index 0000000000000000000000000000000000000000..3b1ba86c146f0f5092c400cc2cfb7273e9d0f4b7 --- /dev/null +++ b/sickbeard/frenchFinder.py @@ -0,0 +1,79 @@ +# Author: Nic Wolfe <nic@wolfeden.ca> +# URL: http://code.google.com/p/sickbeard/ +# +# This file is part of Sick Beard. +# +# Sick Beard is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Sick Beard is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>. + +import datetime +import operator + +import sickbeard + +from sickbeard import db +from sickbeard import helpers, logger, show_name_helpers +from sickbeard import providers +from sickbeard import search +from sickbeard import history + +from sickbeard.common import DOWNLOADED, SNATCHED, SNATCHED_FRENCH, Quality + +from lib.tvdb_api import tvdb_api, tvdb_exceptions + +from name_parser.parser import NameParser, InvalidNameException + + +class FrenchFinder(): + + def __init__(self, force=None, show=None): + + #TODOif not sickbeard.DOWNLOAD_FRENCH: + # return + if sickbeard.showList==None: + return + logger.log(u"Beginning the search for french episodes") + + frenchlist=[] + #get list of english episodes that we want to search in french + myDB = db.DBConnection() + if show: + frenchsql=myDB.select("SELECT showid, season, episode from tv_episodes where audio_langs='en' and tv_episodes.showid =?",[show]) + else: + frenchsql=myDB.select("SELECT showid, season, episode from tv_episodes, tv_shows where audio_langs='en' and tv_episodes.showid = tv_shows.tvdb_id and tv_shows.frenchsearch = 1") + #make the episodes objects + for episode in frenchsql: + showObj = helpers.findCertainShow(sickbeard.showList, episode[0]) + epObj = showObj.getEpisode(episode[1], episode[2]) + frenchlist.append(epObj) + + #for each episode in frenchlist fire a search in french + for frepisode in frenchlist: + result=[] + for curProvider in providers.sortedProviderList(): + + if not curProvider.isActive(): + continue + + logger.log(u"Searching for french episodes on "+curProvider.name +" for " +frepisode.show.name +" season "+str(frepisode.season)+" episode "+str(frepisode.episode)) + curfrench = curProvider.findFrench(frepisode, manualSearch=True) + for x in curfrench: + result.append(x) + best = search.pickBestResult(result, episode = epObj.episode, season = epObj.season) + if best: + best.name=best.name + ' snatchedfr' + logger.log(u"Found french episode for " +frepisode.show.name +" season "+str(frepisode.season)+" episode "+str(frepisode.episode)) + search.snatchEpisode(best, SNATCHED_FRENCH) + else: + logger.log(u"No french episodes found for " +frepisode.show.name +" season "+str(frepisode.season)+" episode "+str(frepisode.episode)) + \ No newline at end of file diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py index 544070e8f511b05945cb17f6f2807239cbd7f1cf..74921457bf45b89aee27e2fcadc3a077076292d4 100755 --- a/sickbeard/postProcessor.py +++ b/sickbeard/postProcessor.py @@ -723,7 +723,7 @@ class PostProcessor(object): ep_quality = common.Quality.UNKNOWN # if there is a quality available in the status then we don't need to bother guessing from the filename - if ep_obj.status in common.Quality.SNATCHED + common.Quality.SNATCHED_PROPER: + if ep_obj.status in common.Quality.SNATCHED + common.Quality.SNATCHED_PROPER + common.Quality.SNATCHED_FRENCH: oldStatus, ep_quality = common.Quality.splitCompositeStatus(ep_obj.status) #@UnusedVariable if ep_quality != common.Quality.UNKNOWN: self._log(u"The old status had a quality in it, using that: "+common.Quality.qualityStrings[ep_quality], logger.DEBUG) @@ -789,7 +789,7 @@ class PostProcessor(object): """ # if SB downloaded this on purpose then this is a priority download - if self.in_history or ep_obj.status in common.Quality.SNATCHED + common.Quality.SNATCHED_PROPER: + if self.in_history or ep_obj.status in common.Quality.SNATCHED + common.Quality.SNATCHED_PROPER + common.Quality.SNATCHED_FRENCH: self._log(u"SB snatched this episode so I'm marking it as priority", logger.DEBUG) return True diff --git a/sickbeard/providers/binnewz/__init__.py b/sickbeard/providers/binnewz/__init__.py index 2e9f22988cfddcde123b3128b71b61e28ae8cd22..86ee5d0af987c2831e34a7a5a5a210cd3b0c4fd7 100644 --- a/sickbeard/providers/binnewz/__init__.py +++ b/sickbeard/providers/binnewz/__init__.py @@ -92,7 +92,7 @@ class BinNewzProvider(generic.NZBProvider): result.append(showName + ".saison %2d" % season) return result - def _get_episode_search_strings(self, ep_obj): + def _get_episode_search_strings(self, ep_obj, french=None): strings = [] showNames = show_name_helpers.allPossibleShowNames(ep_obj.show) global globepid @@ -134,7 +134,7 @@ class BinNewzProvider(generic.NZBProvider): return data #wtf with the signature change... - def _doSearch(self, searchString=None, show=None, season=None): + def _doSearch(self, searchString=None, show=None, season=None, french=None): if searchString is None: return [] logger.log("BinNewz : Searching for " + searchString) @@ -161,7 +161,7 @@ class BinNewzProvider(generic.NZBProvider): language = cells[3].find("img").get("src") if show: - if show.audio_lang == "fr": + if show.audio_lang == "fr" or french: if not "_fr" in language: continue elif show.audio_lang == "en": @@ -220,7 +220,10 @@ class BinNewzProvider(generic.NZBProvider): binsearch_result = downloader.search(searchItem, minSize, newsgroup) if binsearch_result: links = [] - binsearch_result.audio_langs = show.audio_lang + if french: + binsearch_result.audio_langs = 'fr' + else: + binsearch_result.audio_langs = show.audio_lang binsearch_result.title = name binsearch_result.quality = quality myDB = db.DBConnection() diff --git a/sickbeard/providers/cpasbien.py b/sickbeard/providers/cpasbien.py index bbb3b228c678f03d4fb8fa5a44f5b5a273538c98..5952a9e09c4af8af6d3b9994dbad91e01bacfd61 100644 --- a/sickbeard/providers/cpasbien.py +++ b/sickbeard/providers/cpasbien.py @@ -53,7 +53,7 @@ class CpasbienProvider(generic.TorrentProvider): result.append( showName + " S%02d" % season ) return result - def _get_episode_search_strings(self, ep_obj): + def _get_episode_search_strings(self, ep_obj, french=None): strings = [] @@ -70,7 +70,7 @@ class CpasbienProvider(generic.TorrentProvider): def getQuality(self, item): return item.getQuality() - def _doSearch(self, searchString, show=None, season=None): + def _doSearch(self, searchString, show=None, season=None, french=None): results = [] searchUrl = self.url + '/recherche/' @@ -91,7 +91,7 @@ class CpasbienProvider(generic.TorrentProvider): title = str(link.text).lower().strip() pageURL = link['href'] - if "vostfr" in title and ((not show.subtitles) or show.audio_lang == "fr"): + if "vostfr" in title and ((not show.subtitles) or show.audio_lang == "fr" or french): continue torrentPage = self.opener.open( pageURL ) @@ -123,8 +123,10 @@ class CpasbienProvider(generic.TorrentProvider): else: quality = Quality.SDTV - if show: + if show and french==None: results.append( CpasbienSearchResult( self.opener, title, downloadURL, quality, str(show.audio_lang) ) ) + elif show and french: + results.append( CpasbienSearchResult( self.opener, title, downloadURL, quality, 'fr' ) ) else: results.append( CpasbienSearchResult( self.opener, title, downloadURL, quality ) ) diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py index 4848c976a7dae844e045107a59cc633b4eca7457..84d7dd19bd64486c924e1fffd2897befb86864eb 100644 --- a/sickbeard/providers/generic.py +++ b/sickbeard/providers/generic.py @@ -190,13 +190,13 @@ class GenericProvider: quality = Quality.nameQuality(title) return quality - def _doSearch(self, show=None, season=None): + def _doSearch(self, show=None, season=None, french=None): return [] def _get_season_search_strings(self, show, season, episode=None): return [] - def _get_episode_search_strings(self, ep_obj): + def _get_episode_search_strings(self, ep_obj, french=None): return [] def _get_title_and_url(self, item): @@ -411,7 +411,69 @@ class GenericProvider: return [classes.Proper(x['name'], x['url'], datetime.datetime.fromtimestamp(x['time'])) for x in results] + def findFrench(self, episode=None, manualSearch=False): + results = [] + self._checkAuth() + + logger.log(u"Searching "+self.name+" for " + episode.prettyName()) + + itemList = [] + + for cur_search_string in self._get_episode_search_strings(episode,'french'): + itemList += self._doSearch(cur_search_string, show=episode.show, french='french') + + for item in itemList: + + (title, url) = self._get_title_and_url(item) + + # parse the file name + try: + myParser = NameParser() + parse_result = myParser.parse(title) + except InvalidNameException: + logger.log(u"Unable to parse the filename "+title+" into a valid episode", logger.WARNING) + continue + + language = self._get_language(title,item) + + if episode.show.air_by_date: + if parse_result.air_date != episode.airdate: + logger.log("Episode "+title+" didn't air on "+str(episode.airdate)+", skipping it", logger.DEBUG) + continue + elif parse_result.season_number != episode.season or episode.episode not in parse_result.episode_numbers: + logger.log("Episode "+title+" isn't "+str(episode.season)+"x"+str(episode.episode)+", skipping it", logger.DEBUG) + continue + quality = self.getQuality(item) + + if not episode.show.wantEpisode(episode.season, episode.episode, quality, manualSearch): + logger.log(u"Ignoring result "+title+" because we don't want an episode that is "+Quality.qualityStrings[quality], logger.DEBUG) + continue + + if not language == 'fr': + logger.log(u"Ignoring result "+title+" because the language: " + showLanguages[language] + " does not match the desired language: French") + continue + + logger.log(u"Found result " + title + " at " + url, logger.DEBUG) + + result = self.getResult([episode]) + result.item = item + if hasattr(item , 'getNZB'): + result.extraInfo = [item.getNZB() ] + elif hasattr(item , 'extraInfo'): + result.extraInfo = item.extraInfo + result.url = url + result.name = title + result.quality = quality + if hasattr(item , 'audio_langs'): + result.audio_lang=''.join(item.audio_langs) + + else: + result.audio_lang=language + results.append(result) + + return results + class NZBProvider(GenericProvider): def __init__(self, name): diff --git a/sickbeard/providers/gks.py b/sickbeard/providers/gks.py index 5578c4229f481aad218650e0fa033f5e1a18f236..c6dff7f4c9e8699b81d8f0ee8565ebbec7b61955 100644 --- a/sickbeard/providers/gks.py +++ b/sickbeard/providers/gks.py @@ -73,16 +73,20 @@ class GksProvider(generic.TorrentProvider): results.append(result) return results - def _get_episode_search_strings(self, ep_obj): + def _get_episode_search_strings(self, ep_obj, french=None): showNames = show_name_helpers.allPossibleShowNames(ep_obj.show) results = [] for showName in showNames: - for result in self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang) : + if french: + lang='fr' + else: + lang=ep_obj.show.audio_lang + for result in self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), lang) : results.append(result) return results - def _doSearch(self, searchString, show=None, season=None): + def _doSearch(self, searchString, show=None, season=None, french=None): results = [] searchUrl = self.url+'rdirect.php?type=search&'+searchString logger.log(u"Search URL: " + searchUrl, logger.DEBUG) @@ -130,8 +134,10 @@ class GksProvider(generic.TorrentProvider): if quality==Quality.UNKNOWN and title: if '720p' not in title.lower() and '1080p' not in title.lower(): quality=Quality.SDTV - if show: + if show and french==None: results.append( GksSearchResult( self.opener, title, downloadURL, quality, str(show.audio_lang) ) ) + elif show and french: + results.append( GksSearchResult( self.opener, title, downloadURL, quality, 'fr' ) ) else: results.append( GksSearchResult( self.opener, title, downloadURL, quality ) ) return results diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py index 84d8d60f795db68a5bd45b09af4066b6eb162d24..f57d6f53890e6c80a90b90302febfa5b7cae1b20 100644 --- a/sickbeard/providers/kat.py +++ b/sickbeard/providers/kat.py @@ -91,7 +91,7 @@ class KATProvider(generic.TorrentProvider): return [params] - def _get_episode_search_strings(self, ep_obj): + def _get_episode_search_strings(self, ep_obj,french=None): params = {} @@ -121,7 +121,10 @@ class KATProvider(generic.TorrentProvider): to_return.append(cur_return) logger.log(u"KAT _get_episode_search_strings for %s is returning %s" % (repr(ep_obj), repr(params)), logger.DEBUG) - lang = ep_obj.show.audio_lang + if french: + lang='fr' + else: + lang = ep_obj.show.audio_lang return to_return def getURL(self, url, headers=None): @@ -180,7 +183,7 @@ class KATProvider(generic.TorrentProvider): logger.log(u"Unknown exception while loading URL " + url + ": " + traceback.format_exc(), logger.ERROR) return None - def _doSearch(self, search_params, show=None, season=None): + def _doSearch(self, search_params, show=None, season=None, french=None): # First run a search using the advanced format -- results are probably more reliable, but often not available for several weeks # http://kat.ph/usearch/%22james%20may%22%20season:1%20episode:1%20verified:1/?rss=1 def advancedEpisodeParamBuilder(params): @@ -191,7 +194,7 @@ class KATProvider(generic.TorrentProvider): episodeParam = episodeParam + 'season:' + str(params.pop('season')) +"%20" if 'episode' in params: episodeParam = episodeParam + 'episode:' + str(params.pop('episode')) +"%20" - if str(lang)=="fr": + if str(lang)=="fr" or french: episodeParam = episodeParam + ' french' return episodeParam searchURL = self._buildSearchURL(advancedEpisodeParamBuilder, search_params); @@ -209,7 +212,7 @@ class KATProvider(generic.TorrentProvider): episodeParam = episodeParam + 'S' + str(params.pop('season')).zfill(2) if 'episode' in params: episodeParam += 'E' + str(params.pop('episode')).zfill(2) - if str(lang)=="fr": + if str(lang)=="fr" or french: episodeParam = episodeParam + ' french' return episodeParam searchURL = self._buildSearchURL(fuzzyEpisodeParamBuilder, search_params); diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py index e085c774ca7f5001afa847f7dc104a23de25b015..378266a1f1c0a3f8d105d8ac88a5c662857a61a8 100644 --- a/sickbeard/providers/newznab.py +++ b/sickbeard/providers/newznab.py @@ -110,7 +110,7 @@ class NewznabProvider(generic.NZBProvider): return to_return - def _get_episode_search_strings(self, ep_obj): + def _get_episode_search_strings(self, ep_obj, french=None): showNames = show_name_helpers.allPossibleShowNames(ep_obj.show) for show_name in showNames: ep_obj.show.sname=show_name @@ -122,9 +122,13 @@ class NewznabProvider(generic.NZBProvider): # search directly by tvrage id if ep_obj.show.tvrid: params['rid'] = ep_obj.show.tvrid + if ep_obj.show.audio_lang=="fr" or french: + params['q'] = "french" + else: + params['q'] = helpers.sanitizeSceneName(ep_obj.show.sname) # if we can't then fall back on a very basic name search else: - if ep_obj.show.audio_lang=="fr": + if ep_obj.show.audio_lang=="fr" or french: params['q'] = helpers.sanitizeSceneName(ep_obj.show.sname) + " french" else: params['q'] = helpers.sanitizeSceneName(ep_obj.show.sname) @@ -195,10 +199,10 @@ class NewznabProvider(generic.NZBProvider): return True - def _doSearch(self, search_params, show=None, max_age=0, season=None): + def _doSearch(self, search_params, show=None, max_age=0, season=None, french=None): cat = '5030,5040' - if show and show.audio_lang != u"en": + if (show and show.audio_lang != u"en") or french: cat = '5020' params = {"t": "tvsearch", diff --git a/sickbeard/providers/piratebay/__init__.py b/sickbeard/providers/piratebay/__init__.py index f1fd78e6eabad07a7386fede71816a461bdd69ad..35ffe0d9d1d5ad4b287ab1a578b6d2bb7eeb62da 100644 --- a/sickbeard/providers/piratebay/__init__.py +++ b/sickbeard/providers/piratebay/__init__.py @@ -176,7 +176,7 @@ class ThePirateBayProvider(generic.TorrentProvider): return [search_string] - def _get_episode_search_strings(self, ep_obj): + def _get_episode_search_strings(self, ep_obj,french=None): search_string = {'Episode': []} @@ -198,7 +198,7 @@ class ThePirateBayProvider(generic.TorrentProvider): return [search_string] - def _doSearch(self, search_params, show=None, season=None): + def _doSearch(self, search_params, show=None, season=None, french=None): results = [] items = {'Season': [], 'Episode': []} diff --git a/sickbeard/providers/t411.py b/sickbeard/providers/t411.py index dc332ab98d07fdb7c352384a75a2253bc29c2d54..0074b2b767b3c719be41f133543df3544bc121f9 100644 --- a/sickbeard/providers/t411.py +++ b/sickbeard/providers/t411.py @@ -45,10 +45,10 @@ class T411Provider(generic.TorrentProvider): def isEnabled(self): return sickbeard.T411 - def getSearchParams(self, searchString, audio_lang, subcat): - if audio_lang == "en": + def getSearchParams(self, searchString, audio_lang, subcat, french): + if audio_lang == "en" and french==None: return urllib.urlencode( {'search': searchString, 'cat' : 210, 'submit' : 'Recherche', 'subcat': subcat } ) + "&term%5B17%5D%5B%5D=540&term%5B17%5D%5B%5D=721" - elif audio_lang == "fr": + elif audio_lang == "fr" or french: return urllib.urlencode( {'search': searchString, 'cat' : 210, 'submit' : 'Recherche', 'subcat': subcat } ) + "&term%5B17%5D%5B%5D=541&term%5B17%5D%5B%5D=542" else: return urllib.urlencode( {'search': searchString, 'cat' : 210, 'submit' : 'Recherche', 'subcat': subcat } ) @@ -77,24 +77,24 @@ class T411Provider(generic.TorrentProvider): results.append( self.getSearchParams(showName + " saison %02d" % season, show.audio_lang, 634 )) return results - def _get_episode_search_strings(self, ep_obj): + def _get_episode_search_strings(self, ep_obj, french=None): showNames = show_name_helpers.allPossibleShowNames(ep_obj.show) results = [] for showName in showNames: - results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 433 )) + results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 433, french )) if (int(ep_obj.season) < 31 and int(ep_obj.episode) < 61): - results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 433)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.episode), 'term[45][]': self.seasonValue(ep_obj.season)})) + results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 433, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.episode), 'term[45][]': self.seasonValue(ep_obj.season)})) #results.append( self.getSearchParams( "%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang , 433 )) MAY RETURN 1x12 WHEN SEARCHING 1x1 - results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 433 )) - results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 637 )) + results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 433, french )) + results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 637, french )) if (int(ep_obj.season) < 31 and int(ep_obj.episode) < 61): - results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 637)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.episode), 'term[45][]': self.seasonValue(ep_obj.season)})) + results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 637, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.episode), 'term[45][]': self.seasonValue(ep_obj.season)})) #results.append( self.getSearchParams( "%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 637 )) - results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 637 )) - results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 634)) + results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 637, french )) + results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 634, french)) #results.append( self.getSearchParams( "%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 634 )) - results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 634 )) + results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 634, french )) return results def _get_title_and_url(self, item): @@ -108,7 +108,7 @@ class T411Provider(generic.TorrentProvider): data = urllib.urlencode({'login': login, 'password' : password, 'submit' : 'Connexion', 'remember': 1, 'url' : '/'}) self.opener.open(self.url + '/users/login', data) - def _doSearch(self, searchString, show=None, season=None): + def _doSearch(self, searchString, show=None, season=None, french=None): if not self.login_done: self._doLogin( sickbeard.T411_USERNAME, sickbeard.T411_PASSWORD ) @@ -133,8 +133,10 @@ class T411Provider(generic.TorrentProvider): if quality==Quality.UNKNOWN and title: if '720p' not in title.lower() and '1080p' not in title.lower(): quality=Quality.SDTV - if show: + if show and french==None: results.append( T411SearchResult( self.opener, link['title'], downloadURL, quality, str(show.audio_lang) ) ) + elif show and french: + results.append( T411SearchResult( self.opener, link['title'], downloadURL, quality, 'fr' ) ) else: results.append( T411SearchResult( self.opener, link['title'], downloadURL, quality ) ) diff --git a/sickbeard/scheduler.py b/sickbeard/scheduler.py index 92a59c85d6af333d2da8d7e074f4386427b6a453..d175facedb2e73bec443231daa54c2bd728454f0 100644 --- a/sickbeard/scheduler.py +++ b/sickbeard/scheduler.py @@ -70,7 +70,10 @@ class Scheduler: try: if not self.silent: logger.log(u"Starting new thread: "+self.threadName, logger.DEBUG) - self.action.run() + if self.threadName == 'FINDFRENCH': + self.action.__init__() + else: + self.action.run() except Exception, e: logger.log(u"Exception generated in thread "+self.threadName+": " + ex(e), logger.ERROR) logger.log(repr(traceback.format_exc()), logger.DEBUG) diff --git a/sickbeard/search_queue.py b/sickbeard/search_queue.py index 9549d7b01c9732a77946d3f40b92f65eb594c203..41654d6a23d31132b9614fd80845644a3a986579 100644 --- a/sickbeard/search_queue.py +++ b/sickbeard/search_queue.py @@ -227,7 +227,7 @@ class BacklogQueueItem(generic_queue.QueueItem): highestBestQuality = 0 # if we need a better one then say yes - if (curStatus in (common.DOWNLOADED, common.SNATCHED, common.SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == common.WANTED: + if (curStatus in (common.DOWNLOADED, common.SNATCHED, common.SNATCHED_PROPER, common.SNATCHED_FRENCH) and curQuality < highestBestQuality) or curStatus == common.WANTED: wantSeason = True break diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py index 56c29062236c8b0f59e6f0c689c395ee369fd148..eb2056d1c280189b33b5842d4f1c3462e10b357c 100644 --- a/sickbeard/show_queue.py +++ b/sickbeard/show_queue.py @@ -140,6 +140,14 @@ class ShowQueue(generic_queue.GenericQueue): self.add_item(queueItemObj) return queueItemObj + + def searchFrench(self, show, force=False): + + queueItemObj = QueueItemsearchFrench(show) + + self.add_item(queueItemObj) + + return queueItemObj def addShow(self, tvdb_id, showDir, default_status=None, quality=None, flatten_folders=None, lang="fr", subtitles=None, audio_lang=None): queueItemObj = QueueItemAdd(tvdb_id, showDir, default_status, quality, flatten_folders, lang, subtitles, audio_lang) @@ -157,6 +165,7 @@ class ShowQueueActions: RENAME = 5 SUBTITLE=6 SUBTITLE_CLEAN=7 + FRENCH_SEARCH=8 names = {REFRESH: 'Refresh', ADD: 'Add', @@ -165,6 +174,7 @@ class ShowQueueActions: RENAME: 'Rename', SUBTITLE: 'Subtitle', SUBTITLE_CLEAN: 'Subtitle Cleaning', + FRENCH_SEARCH: 'French Search', } class ShowQueueItem(generic_queue.QueueItem): @@ -285,6 +295,7 @@ class QueueItemAdd(ShowQueueItem): self.show.quality = self.quality if self.quality else sickbeard.QUALITY_DEFAULT self.show.flatten_folders = self.flatten_folders if self.flatten_folders != None else sickbeard.FLATTEN_FOLDERS_DEFAULT self.show.paused = 0 + self.show.frenchsearch = 0 # be smartish about this if self.show.genre and "talk show" in self.show.genre.lower(): @@ -465,6 +476,19 @@ class QueueItemCleanSubtitle(ShowQueueItem): self.inProgress = False +class QueueItemsearchFrench(ShowQueueItem): + def __init__(self, show=None): + ShowQueueItem.__init__(self, ShowQueueActions.FRENCH_SEARCH, show) + + def execute(self): + + ShowQueueItem.execute(self) + + logger.log(u"Searching french episodes for "+self.show.name) + + self.show.searchFrench(self.show.tvdbid) + + self.inProgress = False class QueueItemUpdate(ShowQueueItem): def __init__(self, show=None): ShowQueueItem.__init__(self, ShowQueueActions.UPDATE, show) diff --git a/sickbeard/subtitles.py b/sickbeard/subtitles.py index a2957162adb163fe6f32ab153e13a5a5d721012e..0ec658c9c8fd3b39aba7aef8c4f0567887ed18cc 100644 --- a/sickbeard/subtitles.py +++ b/sickbeard/subtitles.py @@ -106,7 +106,7 @@ class SubtitlesFinder(): myDB = db.DBConnection() today = datetime.date.today().toordinal() # you have 5 minutes to understand that one. Good luck - sqlResults = myDB.select('SELECT s.show_name, e.showid, e.season, e.episode, e.status, e.subtitles, e.subtitles_searchcount AS searchcount, e.subtitles_lastsearch AS lastsearch, e.location, (? - e.airdate) AS airdate_daydiff FROM tv_episodes AS e INNER JOIN tv_shows AS s ON (e.showid = s.tvdb_id) WHERE s.subtitles = 1 AND e.subtitles NOT LIKE (?) AND ((e.subtitles_searchcount <= 2 AND (? - e.airdate) > 7) OR (e.subtitles_searchcount <= 9 AND (? - e.airdate) <= 7)) AND (e.status IN ('+','.join([str(x) for x in Quality.DOWNLOADED])+') OR (e.status IN ('+','.join([str(x) for x in Quality.SNATCHED + Quality.SNATCHED_PROPER])+') AND e.location != ""))', [today, wantedLanguages(True), today, today]) + sqlResults = myDB.select('SELECT s.show_name, e.showid, e.season, e.episode, e.status, e.subtitles, e.subtitles_searchcount AS searchcount, e.subtitles_lastsearch AS lastsearch, e.location, (? - e.airdate) AS airdate_daydiff FROM tv_episodes AS e INNER JOIN tv_shows AS s ON (e.showid = s.tvdb_id) WHERE s.subtitles = 1 AND e.subtitles NOT LIKE (?) AND ((e.subtitles_searchcount <= 2 AND (? - e.airdate) > 7) OR (e.subtitles_searchcount <= 9 AND (? - e.airdate) <= 7)) AND (e.status IN ('+','.join([str(x) for x in Quality.DOWNLOADED])+') OR (e.status IN ('+','.join([str(x) for x in Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH ])+') AND e.location != ""))', [today, wantedLanguages(True), today, today]) if len(sqlResults) == 0: logger.log('No subtitles to download', logger.MESSAGE) return diff --git a/sickbeard/traktWatchListChecker.py b/sickbeard/traktWatchListChecker.py index ead7fefbafb2d3af6cc299d1edeac7a9093871bc..fb884499a5e8afcd2ef1f75bc345aa60dc9fea6d 100644 --- a/sickbeard/traktWatchListChecker.py +++ b/sickbeard/traktWatchListChecker.py @@ -23,7 +23,7 @@ from sickbeard import encodingKludge as ek from sickbeard import logger,db from sickbeard import helpers from sickbeard import search_queue -from sickbeard.common import SNATCHED, SNATCHED_PROPER, DOWNLOADED, SKIPPED, UNAIRED, IGNORED, ARCHIVED, WANTED, UNKNOWN +from sickbeard.common import SNATCHED, SNATCHED_PROPER, SNATCHED_FRENCH, DOWNLOADED, SKIPPED, UNAIRED, IGNORED, ARCHIVED, WANTED, UNKNOWN from lib.trakt import * class TraktChecker(): diff --git a/sickbeard/tv.py b/sickbeard/tv.py index e2dad314f5390e3d352f7c474a68785469dbd871..bc605c48c8d5ac0f694131775de2d3bd36f67417 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -33,6 +33,8 @@ import xml.etree.cElementTree as etree from name_parser.parser import NameParser, InvalidNameException +from frenchFinder import FrenchFinder + from lib import subliminal from lib.tidysub import cleaner @@ -54,7 +56,7 @@ from sickbeard import history from sickbeard import encodingKludge as ek from common import Quality, Overview -from common import DOWNLOADED, SNATCHED, SNATCHED_PROPER, ARCHIVED, IGNORED, UNAIRED, WANTED, SKIPPED, UNKNOWN +from common import DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_FRENCH, ARCHIVED, IGNORED, UNAIRED, WANTED, SKIPPED, UNKNOWN from common import NAMING_DUPLICATE, NAMING_EXTEND, NAMING_LIMITED_EXTEND, NAMING_SEPARATED_REPEAT, NAMING_LIMITED_EXTEND_E_PREFIXED @@ -80,6 +82,7 @@ class TVShow(object): self.airs = "" self.startyear = 0 self.paused = 0 + self.frenchsearch = 0 self.air_by_date = 0 self.subtitles = int(sickbeard.SUBTITLES_DEFAULT if sickbeard.SUBTITLES_DEFAULT else 0) self.lang = lang @@ -564,11 +567,11 @@ class TVShow(object): newStatus = DOWNLOADED # if it was snatched proper and we found a higher quality one then allow the status change - elif oldStatus == SNATCHED_PROPER and oldQuality < newQuality: + elif (oldStatus == SNATCHED_PROPER or oldStatus == SNATCHED_FRENCH) and oldQuality < newQuality: logger.log(u"STATUS: this ep used to be snatched proper with quality "+Quality.qualityStrings[oldQuality]+" but a file exists with quality "+Quality.qualityStrings[newQuality]+" so I'm setting the status to DOWNLOADED", logger.DEBUG) newStatus = DOWNLOADED - elif oldStatus not in (SNATCHED, SNATCHED_PROPER): + elif oldStatus not in (SNATCHED, SNATCHED_PROPER, SNATCHED_FRENCH): newStatus = DOWNLOADED if newStatus != None: @@ -634,7 +637,7 @@ class TVShow(object): self.quality = int(sqlResults[0]["quality"]) self.flatten_folders = int(sqlResults[0]["flatten_folders"]) self.paused = int(sqlResults[0]["paused"]) - + self.frenchsearch = int(sqlResults[0]["frenchsearch"]) self._location = sqlResults[0]["location"] if self.tvrid == 0: @@ -952,6 +955,11 @@ class TVShow(object): except Exception as e: logger.log("Error occurred when cleaning subtitles: " + str(e), logger.DEBUG) return + + def searchFrench(self, show): + logger.log("Sending french episodes search") + FrenchFinder('force',show) + return def saveToDB(self): logger.log(str(self.tvdbid) + ": Saving show info to database", logger.DEBUG) @@ -969,6 +977,7 @@ class TVShow(object): "airs": self.airs, "status": self.status, "flatten_folders": self.flatten_folders, + "frenchsearch":self.frenchsearch, "paused": self.paused, "air_by_date": self.air_by_date, "subtitles": self.subtitles, @@ -1048,7 +1057,7 @@ class TVShow(object): curStatus, curQuality = Quality.splitCompositeStatus(epStatus) # if we are re-downloading then we only want it if it's in our bestQualities list and better than what we have - if curStatus in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER and quality in bestQualities and quality > curQuality: + if curStatus in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH and quality in bestQualities and quality > curQuality: logger.log(u"We already have this ep but the new one is better quality, saying yes", logger.DEBUG) return True @@ -1066,7 +1075,7 @@ class TVShow(object): return Overview.SKIPPED elif epStatus == ARCHIVED: return Overview.GOOD - elif epStatus in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER: + elif epStatus in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH: anyQualities, bestQualities = Quality.splitQuality(self.quality) #@UnusedVariable if bestQualities: @@ -1076,7 +1085,7 @@ class TVShow(object): epStatus, curQuality = Quality.splitCompositeStatus(epStatus) - if epStatus in (SNATCHED, SNATCHED_PROPER): + if epStatus in (SNATCHED, SNATCHED_PROPER, SNATCHED_FRENCH): return Overview.SNATCHED # if they don't want re-downloads then we call it good if they have anything elif maxBestQuality == None: @@ -1488,7 +1497,7 @@ class TVEpisode(object): if not ek.ek(os.path.isfile, self.location): # if we don't have the file - if self.airdate >= datetime.date.today() and self.status not in Quality.SNATCHED + Quality.SNATCHED_PROPER: + if self.airdate >= datetime.date.today() and self.status not in Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH: # and it hasn't aired yet set the status to UNAIRED logger.log(u"Episode airs in the future, changing status from " + str(self.status) + " to " + str(UNAIRED), logger.DEBUG) self.status = UNAIRED @@ -1514,7 +1523,7 @@ class TVEpisode(object): # if we have a media file then it's downloaded elif sickbeard.helpers.isMediaFile(self.location): # leave propers alone, you have to either post-process them or manually change them back - if self.status not in Quality.SNATCHED_PROPER + Quality.DOWNLOADED + Quality.SNATCHED + [ARCHIVED]: + if self.status not in Quality.SNATCHED_FRENCH + Quality.SNATCHED_PROPER + Quality.DOWNLOADED + Quality.SNATCHED + [ARCHIVED]: logger.log(u"5 Status changes from " + str(self.status) + " to " + str(Quality.statusFromName(self.location)), logger.DEBUG) self.status = Quality.statusFromName(self.location) diff --git a/sickbeard/webapi.py b/sickbeard/webapi.py index 5ff4e2d1e19f1b304970ac453c47dfa67831a5c0..08be5696c0559065dce0f1d207afb9e6fedd8b6e 100644 --- a/sickbeard/webapi.py +++ b/sickbeard/webapi.py @@ -34,7 +34,7 @@ from sickbeard import db, logger, exceptions, history, ui, helpers from sickbeard.exceptions import ex from sickbeard import encodingKludge as ek from sickbeard import search_queue -from sickbeard.common import SNATCHED, SNATCHED_PROPER, DOWNLOADED, SKIPPED, UNAIRED, IGNORED, ARCHIVED, WANTED, UNKNOWN +from sickbeard.common import SNATCHED, SNATCHED_PROPER, SNATCHED_FRENCH, DOWNLOADED, SKIPPED, UNAIRED, IGNORED, ARCHIVED, WANTED, UNKNOWN from common import Quality, qualityPresetStrings, statusStrings from sickbeard import image_cache from lib.tvdb_api import tvdb_api, tvdb_exceptions @@ -2222,7 +2222,7 @@ class CMD_ShowStats(ApiCall): episode_status_counts_total = {} episode_status_counts_total["total"] = 0 for status in statusStrings.statusStrings.keys(): - if status in [UNKNOWN, DOWNLOADED, SNATCHED, SNATCHED_PROPER]: + if status in [UNKNOWN, DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_FRENCH]: continue episode_status_counts_total[status] = 0 @@ -2238,7 +2238,7 @@ class CMD_ShowStats(ApiCall): # add all snatched qualities episode_qualities_counts_snatch = {} episode_qualities_counts_snatch["total"] = 0 - for statusCode in Quality.SNATCHED + Quality.SNATCHED_PROPER: + for statusCode in Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH: status, quality = Quality.splitCompositeStatus(statusCode) if quality in [Quality.NONE]: continue @@ -2255,7 +2255,7 @@ class CMD_ShowStats(ApiCall): if status in Quality.DOWNLOADED: episode_qualities_counts_download["total"] += 1 episode_qualities_counts_download[int(row["status"])] += 1 - elif status in Quality.SNATCHED + Quality.SNATCHED_PROPER: + elif status in Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH: episode_qualities_counts_snatch["total"] += 1 episode_qualities_counts_snatch[int(row["status"])] += 1 elif status == 0: # we dont count NONE = 0 = N/A @@ -2396,7 +2396,7 @@ class CMD_ShowsStats(ApiCall): stats["shows_total"] = len(sickbeard.showList) stats["shows_active"] = len([show for show in sickbeard.showList if show.paused == 0 and show.status != "Ended"]) stats["ep_downloaded"] = myDB.select("SELECT COUNT(*) FROM tv_episodes WHERE status IN (" + ",".join([str(show) for show in Quality.DOWNLOADED + [ARCHIVED]]) + ") AND season != 0 and episode != 0 AND airdate <= " + today + "")[0][0] - stats["ep_total"] = myDB.select("SELECT COUNT(*) FROM tv_episodes WHERE season != 0 and episode != 0 AND (airdate != 1 OR status IN (" + ",".join([str(show) for show in (Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER) + [ARCHIVED]]) + ")) AND airdate <= " + today + " AND status != " + str(IGNORED) + "")[0][0] + stats["ep_total"] = myDB.select("SELECT COUNT(*) FROM tv_episodes WHERE season != 0 and episode != 0 AND (airdate != 1 OR status IN (" + ",".join([str(show) for show in (Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH) + [ARCHIVED]]) + ")) AND airdate <= " + today + " AND status != " + str(IGNORED) + "")[0][0] myDB.connection.close() return _responds(RESULT_SUCCESS, stats) diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index d941c248d095eb6f95a9f8c922678850b9d55828..536adf6ef51f6f12a49e1669761af90f6d1b5f87 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -226,7 +226,7 @@ class Manage: status_list = [int(whichStatus)] if status_list[0] == SNATCHED: - status_list = Quality.SNATCHED + Quality.SNATCHED_PROPER + status_list = Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH cur_show_results = myDB.select("SELECT season, episode, name FROM tv_episodes WHERE showid = ? AND season != 0 AND status IN ("+','.join(['?']*len(status_list))+")", [int(tvdb_id)] + status_list) @@ -249,7 +249,7 @@ class Manage: whichStatus = int(whichStatus) status_list = [whichStatus] if status_list[0] == SNATCHED: - status_list = Quality.SNATCHED + Quality.SNATCHED_PROPER + status_list = Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH else: status_list = [] @@ -288,7 +288,7 @@ class Manage: status_list = [int(oldStatus)] if status_list[0] == SNATCHED: - status_list = Quality.SNATCHED + Quality.SNATCHED_PROPER + status_list = Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH to_change = {} @@ -996,7 +996,7 @@ class ConfigSearch: @cherrypy.expose def saveSearch(self, use_nzbs=None, use_torrents=None, nzb_dir=None, sab_username=None, sab_password=None, sab_apikey=None, sab_category=None, sab_host=None, nzbget_password=None, nzbget_category=None, nzbget_host=None, - torrent_dir=None,torrent_method=None, nzb_method=None, usenet_retention=None, search_frequency=None, download_propers=None, torrent_username=None, torrent_password=None, torrent_host=None, torrent_label=None, torrent_path=None, + torrent_dir=None,torrent_method=None, nzb_method=None, usenet_retention=None, search_frequency=None, download_propers=None, download_french=None, torrent_username=None, torrent_password=None, torrent_host=None, torrent_label=None, torrent_path=None, torrent_ratio=None, torrent_paused=None, ignore_words=None, prefered_method=None, torrent_use_ftp = None, ftp_host=None, ftp_port=None, ftp_timeout=None, ftp_passive = None, ftp_login=None, ftp_password=None, ftp_remotedir=None): results = [] @@ -1013,7 +1013,11 @@ class ConfigSearch: download_propers = 1 else: download_propers = 0 - + + if download_french == "on": + download_french = 1 + else: + download_french = 0 if use_nzbs == "on": use_nzbs = 1 else: @@ -1047,6 +1051,7 @@ class ConfigSearch: sickbeard.IGNORE_WORDS = ignore_words sickbeard.DOWNLOAD_PROPERS = download_propers + sickbeard.DOWNLOAD_FRENCH = download_french sickbeard.SAB_USERNAME = sab_username sickbeard.SAB_PASSWORD = sab_password @@ -2905,6 +2910,7 @@ class Home: t.submenu.append({ 'title': 'Force Full Update', 'path': 'home/updateShow?show=%d&force=1'%showObj.tvdbid }) t.submenu.append({ 'title': 'Update show in XBMC', 'path': 'home/updateXBMC?showName=%s'%urllib.quote_plus(showObj.name.encode('utf-8')), 'requires': haveXBMC }) t.submenu.append({ 'title': 'Preview Rename', 'path': 'home/testRename?show=%d'%showObj.tvdbid }) + t.submenu.append({ 'title': 'French Search', 'path': 'home/frenchSearch?show=%d'%showObj.tvdbid }) if sickbeard.USE_SUBTITLES and not sickbeard.showQueueScheduler.action.isBeingSubtitled(showObj) and not sickbeard.showQueueScheduler.action.isBeingCleanedSubtitle(showObj) and showObj.subtitles: t.submenu.append({ 'title': 'Download Subtitles', 'path': 'home/subtitleShow?show=%d'%showObj.tvdbid }) t.submenu.append({ 'title': 'Clean Subtitles', 'path': 'home/subtitleShowClean?show=%d'%showObj.tvdbid }) @@ -2950,7 +2956,7 @@ class Home: return result['description'] if result else 'Episode not found.' @cherrypy.expose - def editShow(self, show=None, location=None, anyQualities=[], bestQualities=[], exceptions_list=[], flatten_folders=None, paused=None, directCall=False, air_by_date=None, tvdbLang=None, audio_lang=None, subtitles=None): + def editShow(self, show=None, location=None, anyQualities=[], bestQualities=[], exceptions_list=[], flatten_folders=None, paused=None, frenchsearch=None, directCall=False, air_by_date=None, tvdbLang=None, audio_lang=None, subtitles=None): if show == None: errString = "Invalid show ID: "+str(show) @@ -2990,6 +2996,11 @@ class Home: paused = 1 else: paused = 0 + + if frenchsearch == "on": + frenchsearch = 1 + else: + frenchsearch = 0 if air_by_date == "on": air_by_date = 1 @@ -3047,6 +3058,7 @@ class Home: showObj.paused = paused showObj.air_by_date = air_by_date showObj.subtitles = subtitles + showObj.frenchsearch = frenchsearch showObj.lang = tvdb_lang showObj.audio_lang = audio_lang @@ -3198,6 +3210,25 @@ class Home: redirect("/home/displayShow?show="+str(showObj.tvdbid)) + @cherrypy.expose + + def frenchSearch(self, show=None, force=0): + + if show == None: + return _genericMessage("Error", "Invalid show ID") + + showObj = sickbeard.helpers.findCertainShow(sickbeard.showList, int(show)) + + if showObj == None: + return _genericMessage("Error", "Unable to find the specified show") + + # search and download subtitles + sickbeard.showQueueScheduler.action.searchFrench(showObj, bool(force)) #@UndefinedVariable + + time.sleep(3) + + redirect("/home/displayShow?show="+str(showObj.tvdbid)) + @cherrypy.expose def updateXBMC(self, showName=None): if sickbeard.XBMC_UPDATE_ONLYFIRST: @@ -3280,7 +3311,7 @@ class Home: logger.log(u"Refusing to change status of "+curEp+" because it is UNAIRED", logger.ERROR) continue - if int(status) in Quality.DOWNLOADED and epObj.status not in Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.DOWNLOADED + [IGNORED] and not ek.ek(os.path.isfile, epObj.location): + if int(status) in Quality.DOWNLOADED and epObj.status not in Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_FRENCH + Quality.DOWNLOADED + [IGNORED] and not ek.ek(os.path.isfile, epObj.location): logger.log(u"Refusing to change status of "+curEp+" to DOWNLOADED because it's not SNATCHED/DOWNLOADED", logger.ERROR) continue