diff --git a/SickBeard.py b/SickBeard.py index aa01b655..b6cc16b3 100755 --- a/SickBeard.py +++ b/SickBeard.py @@ -2,20 +2,20 @@ # Author: Nic Wolfe # URL: http://code.google.com/p/sickbeard/ # -# This file is part of Sick Beard. +# This file is part of SickRage. # -# Sick Beard is free software: you can redistribute it and/or modify +# SickRage 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, +# SickRage 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 . +# along with SickRage. If not, see . # Check needed software dependencies to nudge users to fix their setup import sys @@ -96,9 +96,10 @@ def daemonize(): try: pid = os.fork() # @UndefinedVariable - only available in UNIX if pid != 0: - sys.exit(0) + os._exit(0) except OSError, e: - raise RuntimeError("1st fork failed: %s [%d]" % (e.strerror, e.errno)) + sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) + sys.exit(1) os.setsid() # @UndefinedVariable - only available in UNIX @@ -110,18 +111,33 @@ def daemonize(): try: pid = os.fork() # @UndefinedVariable - only available in UNIX if pid != 0: - sys.exit(0) + os._exit(0) except OSError, e: - raise RuntimeError("2nd fork failed: %s [%d]" % (e.strerror, e.errno)) - - dev_null = file('/dev/null', 'r') - os.dup2(dev_null.fileno(), sys.stdin.fileno()) + sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) + sys.exit(1) + # Write pid if sickbeard.CREATEPID: pid = str(os.getpid()) - logger.log(u"Writing PID " + pid + " to " + str(sickbeard.PIDFILE)) - file(sickbeard.PIDFILE, 'w').write("%s\n" % pid) + logger.log(u"Writing PID: " + pid + " to " + str(sickbeard.PIDFILE)) + try: + file(sickbeard.PIDFILE, 'w').write("%s\n" % pid) + except IOError, e: + logger.log_error_and_exit( + u"Unable to write PID file: " + sickbeard.PIDFILE + " Error: " + str(e.strerror) + " [" + str( + e.errno) + "]") + # Redirect all output + sys.stdout.flush() + sys.stderr.flush() + + devnull = getattr(os, 'devnull', '/dev/null') + stdin = file(devnull, 'r') + stdout = file(devnull, 'a+') + stderr = file(devnull, 'a+') + os.dup2(stdin.fileno(), sys.stdin.fileno()) + os.dup2(stdout.fileno(), sys.stdout.fileno()) + os.dup2(stderr.fileno(), sys.stderr.fileno()) def main(): """ @@ -134,8 +150,8 @@ def main(): sickbeard.PROG_DIR = os.path.dirname(sickbeard.MY_FULLNAME) sickbeard.DATA_DIR = sickbeard.PROG_DIR sickbeard.MY_ARGS = sys.argv[1:] - sickbeard.CREATEPID = False sickbeard.DAEMON = False + sickbeard.CREATEPID = False sickbeard.SYS_ENCODING = None @@ -157,7 +173,7 @@ def main(): # On non-unicode builds this will raise an AttributeError, if encoding type is not valid it throws a LookupError sys.setdefaultencoding(sickbeard.SYS_ENCODING) except: - print 'Sorry, you MUST add the Sick Beard folder to the PYTHONPATH environment variable' + print 'Sorry, you MUST add the SickRage folder to the PYTHONPATH environment variable' print 'or find another way to force Python to use ' + sickbeard.SYS_ENCODING + ' for string encoding.' sys.exit(1) @@ -196,13 +212,15 @@ def main(): if o in ('-p', '--port'): forcedPort = int(a) - # Run as a daemon + # Run as a double forked daemon if o in ('-d', '--daemon'): + sickbeard.DAEMON = True + # When running as daemon disable consoleLogging and don't start browser + consoleLogging = False + noLaunch = True + if sys.platform == 'win32': - print "Daemonize not supported under Windows, starting normally" - else: - consoleLogging = False - sickbeard.DAEMON = True + sickbeard.DAEMON = False # Specify folder to load the config file from if o in ('--config',): @@ -214,21 +232,27 @@ def main(): # Write a pidfile if requested if o in ('--pidfile',): + sickbeard.CREATEPID = True sickbeard.PIDFILE = str(a) # If the pidfile already exists, sickbeard may still be running, so exit if os.path.exists(sickbeard.PIDFILE): - sys.exit("PID file '" + sickbeard.PIDFILE + "' already exists. Exiting.") + sys.exit("PID file: " + sickbeard.PIDFILE + " already exists. Exiting.") - # The pidfile is only useful in daemon mode, make sure we can write the file properly - if sickbeard.DAEMON: - sickbeard.CREATEPID = True - try: - file(sickbeard.PIDFILE, 'w').write("pid\n") - except IOError, e: - raise SystemExit("Unable to write PID file: %s [%d]" % (e.strerror, e.errno)) - else: - logger.log(u"Not running in daemon mode. PID file creation disabled.") + # The pidfile is only useful in daemon mode, make sure we can write the file properly + if sickbeard.CREATEPID: + if sickbeard.DAEMON: + pid_dir = os.path.dirname(sickbeard.PIDFILE) + if not os.access(pid_dir, os.F_OK): + sys.exit("PID dir: " + pid_dir + " doesn't exist. Exiting.") + if not os.access(pid_dir, os.W_OK): + sys.exit("PID dir: " + pid_dir + " must be writable (write permissions). Exiting.") + + else: + if consoleLogging: + sys.stdout.write("Not running in daemon mode. PID file creation disabled.\n") + + sickbeard.CREATEPID = False # If they don't specify a config file then put it in the data dir if not sickbeard.CONFIG_FILE: @@ -255,7 +279,7 @@ def main(): os.chdir(sickbeard.DATA_DIR) if consoleLogging: - print "Starting up Sick Beard " + SICKBEARD_VERSION + " from " + sickbeard.CONFIG_FILE + print "Starting up SickRage " + SICKBEARD_VERSION + " from " + sickbeard.CONFIG_FILE # Load the config and publish it to the sickbeard package if not os.path.isfile(sickbeard.CONFIG_FILE): @@ -266,13 +290,13 @@ def main(): CUR_DB_VERSION = db.DBConnection().checkDBVersion() if CUR_DB_VERSION > 0: if CUR_DB_VERSION < MIN_DB_VERSION: - raise SystemExit("Your database version (" + str(db.DBConnection().checkDBVersion()) + ") is too old to migrate from with this version of Sick Beard (" + str(MIN_DB_VERSION) + ").\n" + \ + raise SystemExit("Your database version (" + str(db.DBConnection().checkDBVersion()) + ") is too old to migrate from with this version of SickRage (" + str(MIN_DB_VERSION) + ").\n" + \ "Upgrade using a previous version of SB first, or start with no database file to begin fresh.") if CUR_DB_VERSION > MAX_DB_VERSION: - raise SystemExit("Your database version (" + str(db.DBConnection().checkDBVersion()) + ") has been incremented past what this version of Sick Beard supports (" + str(MAX_DB_VERSION) + ").\n" + \ + raise SystemExit("Your database version (" + str(db.DBConnection().checkDBVersion()) + ") has been incremented past what this version of SickRage supports (" + str(MAX_DB_VERSION) + ").\n" + \ "If you have used other forks of SB, your database may be unusable due to their modifications.") - # Initialize the config and our threads + # Initialize the config and our threads sickbeard.initialize(consoleLogging=consoleLogging) sickbeard.showList = [] @@ -306,18 +330,18 @@ def main(): try: initWebServer({ - 'port': startPort, - 'host': webhost, - 'data_root': os.path.join(sickbeard.PROG_DIR, 'gui/'+sickbeard.GUI_NAME), - 'web_root': sickbeard.WEB_ROOT, - 'log_dir': log_dir, - 'username': sickbeard.WEB_USERNAME, - 'password': sickbeard.WEB_PASSWORD, - 'enable_https': sickbeard.ENABLE_HTTPS, - 'handle_reverse_proxy': sickbeard.HANDLE_REVERSE_PROXY, - 'https_cert': sickbeard.HTTPS_CERT, - 'https_key': sickbeard.HTTPS_KEY, - }) + 'port': startPort, + 'host': webhost, + 'data_root': os.path.join(sickbeard.PROG_DIR, 'gui/'+sickbeard.GUI_NAME), + 'web_root': sickbeard.WEB_ROOT, + 'log_dir': log_dir, + 'username': sickbeard.WEB_USERNAME, + 'password': sickbeard.WEB_PASSWORD, + 'enable_https': sickbeard.ENABLE_HTTPS, + 'handle_reverse_proxy': sickbeard.HANDLE_REVERSE_PROXY, + 'https_cert': sickbeard.HTTPS_CERT, + 'https_key': sickbeard.HTTPS_KEY, + }) except IOError: logger.log(u"Unable to start web server, is something else running on port %d?" % startPort, logger.ERROR) if sickbeard.LAUNCH_BROWSER and not sickbeard.DAEMON: @@ -342,12 +366,13 @@ def main(): # Stay alive while my threads do the work while (True): - time.sleep(1) if sickbeard.invoked_command: sickbeard.invoked_command() sickbeard.invoked_command = None + time.sleep(1) + return if __name__ == "__main__": diff --git a/gui/slick/interfaces/default/config.tmpl b/gui/slick/interfaces/default/config.tmpl index 15491d8a..cf2ca7d9 100644 --- a/gui/slick/interfaces/default/config.tmpl +++ b/gui/slick/interfaces/default/config.tmpl @@ -17,7 +17,12 @@
- diff --git a/gui/slick/interfaces/default/displayShow.tmpl b/gui/slick/interfaces/default/displayShow.tmpl index a510a67d..a7ad448f 100644 --- a/gui/slick/interfaces/default/displayShow.tmpl +++ b/gui/slick/interfaces/default/displayShow.tmpl @@ -248,8 +248,10 @@ #if int($show.air_by_date) != 1 and int($show.sports) != 1 #if (epResult["season"], epResult["episode"]) in $xem_numbering: #set ($dfltSeas, $dfltEpis) = $xem_numbering[(epResult["season"], epResult["episode"])] - #else + #elif $xem_numbering and (epResult["season"], epResult["episode"]) not in $xem_numbering: #set ($dfltSeas, $dfltEpis) = (0,0) + #else: + #set ($dfltSeas, $dfltEpis) = (epResult["season"], epResult["episode"]) #end if #if (epResult["season"], epResult["episode"]) in $scene_numbering: #set ($scSeas, $scEpis) = $scene_numbering[(epResult["season"], epResult["episode"])] diff --git a/readme.md b/readme.md index 94431a68..c2a423f1 100644 --- a/readme.md +++ b/readme.md @@ -39,6 +39,10 @@ FEATURES: To run SickRage from source you will need Python 2.6+ and Cheetah 2.1.0+. -## Bugs +## Forums -If you find a bug please report [here][githubissues] on Github or at our forums http://www.sickrage.tv. Verify that it hasn't already been submitted and then [log a new bug][githubnewissue]. Be sure to provide a sickrage log in debug mode where is the error evidence or it'll never get fixed. +Any questions or setup info your looking for can be found at out forums http://www.sickrage.tv +
+If you find a bug please report at our forums http://sickrage.tv/forums/forum/help-support/bug-issue-reports +
+Be sure to provide a sickrage log in debug mode where is the error evidence or it'll never get fixed. diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 44d6bcf3..46a96592 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -32,7 +32,7 @@ from threading import Lock from sickbeard import providers, metadata, config from providers import ezrss, tvtorrents, btn, newznab, womble, thepiratebay, torrentleech, kat, publichd, iptorrents, \ omgwtfnzbs, scc, hdtorrents, torrentday, hdbits, nextgen, speedcd -from sickbeard.config import CheckSection, check_setting_int, check_setting_str, ConfigMigrator, naming_ep_type +from sickbeard.config import CheckSection, check_setting_int, check_setting_str, check_setting_float, ConfigMigrator, naming_ep_type from sickbeard import searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser, \ subtitles, traktWatchListChecker from sickbeard import helpers, db, exceptions, show_queue, search_queue, scheduler, show_name_helpers @@ -50,6 +50,8 @@ from sickbeard.databases import mainDB, cache_db, failed_db from lib.configobj import ConfigObj +import xml.etree.ElementTree as ElementTree + invoked_command = None PID = None @@ -135,6 +137,7 @@ ROOT_DIRS = None UPDATE_SHOWS_ON_START = None SORT_ARTICLE = None DEBUG = False +CLEAR_CACHE = None USE_LISTVIEW = None METADATA_XBMC = None @@ -521,7 +524,7 @@ def initialize(consoleLogging=True): USE_SYNOLOGYNOTIFIER, SYNOLOGYNOTIFIER_NOTIFY_ONSNATCH, SYNOLOGYNOTIFIER_NOTIFY_ONDOWNLOAD, SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD, \ USE_EMAIL, EMAIL_HOST, EMAIL_PORT, EMAIL_TLS, EMAIL_USER, EMAIL_PASSWORD, EMAIL_FROM, EMAIL_NOTIFY_ONSNATCH, EMAIL_NOTIFY_ONDOWNLOAD, EMAIL_NOTIFY_ONSUBTITLEDOWNLOAD, EMAIL_LIST, \ USE_LISTVIEW, METADATA_XBMC, METADATA_XBMC_12PLUS, METADATA_MEDIABROWSER, METADATA_PS3, metadata_provider_dict, \ - NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, GIT_PATH, MOVE_ASSOCIATED_FILES, \ + NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, GIT_PATH, MOVE_ASSOCIATED_FILES, CLEAR_CACHE, \ GUI_NAME, HOME_LAYOUT, HISTORY_LAYOUT, DISPLAY_SHOW_SPECIALS, COMING_EPS_LAYOUT, COMING_EPS_SORT, COMING_EPS_DISPLAY_PAUSED, COMING_EPS_MISSED_RANGE, DATE_PRESET, TIME_PRESET, TIME_PRESET_W_SECONDS, \ METADATA_WDTV, METADATA_TIVO, METADATA_MEDE8ER, IGNORE_WORDS, CALENDAR_UNPROTECTED, CREATE_MISSING_SHOW_DIRS, \ ADD_SHOWS_WO_DIR, USE_SUBTITLES, SUBTITLES_LANGUAGES, SUBTITLES_DIR, SUBTITLES_SERVICES_LIST, SUBTITLES_SERVICES_ENABLED, SUBTITLES_HISTORY, SUBTITLES_FINDER_FREQUENCY, subtitlesFinderScheduler, \ @@ -696,21 +699,21 @@ def initialize(consoleLogging=True): EZRSS = bool(check_setting_int(CFG, 'General', 'use_torrent', 0)) if not EZRSS: EZRSS = bool(check_setting_int(CFG, 'EZRSS', 'ezrss', 0)) - EZRSS_RATIO = check_setting_int(CFG, 'EZRSS', 'ezrss_ratio', 0) + EZRSS_RATIO = check_setting_float(CFG, 'EZRSS', 'ezrss_ratio', 0) TVTORRENTS = bool(check_setting_int(CFG, 'TVTORRENTS', 'tvtorrents', 0)) TVTORRENTS_DIGEST = check_setting_str(CFG, 'TVTORRENTS', 'tvtorrents_digest', '') TVTORRENTS_HASH = check_setting_str(CFG, 'TVTORRENTS', 'tvtorrents_hash', '') - TVTORRENTS_RATIO = check_setting_int(CFG, 'TVTORRENTS', 'tvtorrents_ratio', 0) + TVTORRENTS_RATIO = check_setting_float(CFG, 'TVTORRENTS', 'tvtorrents_ratio', 0) TVTORRENTS_OPTIONS = check_setting_str(CFG, 'TVTORRENTS', 'tvtorrents_options', '') BTN = bool(check_setting_int(CFG, 'BTN', 'btn', 0)) BTN_API_KEY = check_setting_str(CFG, 'BTN', 'btn_api_key', '') - BTN_RATIO = check_setting_int(CFG, 'BTN', 'btn_ratio', 0) + BTN_RATIO = check_setting_float(CFG, 'BTN', 'btn_ratio', 0) BTN_OPTIONS = check_setting_str(CFG, 'BTN', 'btn_options', '') THEPIRATEBAY = bool(check_setting_int(CFG, 'THEPIRATEBAY', 'thepiratebay', 1)) - THEPIRATEBAY_RATIO = check_setting_int(CFG, 'THEPIRATEBAY', 'thepiratebay_ratio', 0) + THEPIRATEBAY_RATIO = check_setting_float(CFG, 'THEPIRATEBAY', 'thepiratebay_ratio', 0) THEPIRATEBAY_TRUSTED = bool(check_setting_int(CFG, 'THEPIRATEBAY', 'thepiratebay_trusted', 1)) THEPIRATEBAY_PROXY = bool(check_setting_int(CFG, 'THEPIRATEBAY', 'thepiratebay_proxy', 0)) THEPIRATEBAY_PROXY_URL = check_setting_str(CFG, 'THEPIRATEBAY', 'thepiratebay_proxy_url', '') @@ -720,60 +723,60 @@ def initialize(consoleLogging=True): TORRENTLEECH = bool(check_setting_int(CFG, 'TORRENTLEECH', 'torrentleech', 0)) TORRENTLEECH_USERNAME = check_setting_str(CFG, 'TORRENTLEECH', 'torrentleech_username', '') TORRENTLEECH_PASSWORD = check_setting_str(CFG, 'TORRENTLEECH', 'torrentleech_password', '') - TORRENTLEECH_RATIO = check_setting_int(CFG, 'TORRENTLEECH', 'torrentleech_ratio', 0) + TORRENTLEECH_RATIO = check_setting_float(CFG, 'TORRENTLEECH', 'torrentleech_ratio', 0) TORRENTLEECH_OPTIONS = check_setting_str(CFG, 'TORRENTLEECH', 'torrentleech_options', '') IPTORRENTS = bool(check_setting_int(CFG, 'IPTORRENTS', 'iptorrents', 0)) IPTORRENTS_USERNAME = check_setting_str(CFG, 'IPTORRENTS', 'iptorrents_username', '') IPTORRENTS_PASSWORD = check_setting_str(CFG, 'IPTORRENTS', 'iptorrents_password', '') - IPTORRENTS_RATIO = check_setting_int(CFG, 'IPTORRENTS', 'iptorrents_ratio', 0) + IPTORRENTS_RATIO = check_setting_float(CFG, 'IPTORRENTS', 'iptorrents_ratio', 0) IPTORRENTS_FREELEECH = bool(check_setting_int(CFG, 'IPTORRENTS', 'iptorrents_freeleech', 0)) IPTORRENTS_OPTIONS = check_setting_str(CFG, 'IPTORRENTS', 'iptorrents_options', '') NEXTGEN = bool(check_setting_int(CFG, 'NEXTGEN', 'nextgen', 0)) NEXTGEN_USERNAME = check_setting_str(CFG, 'NEXTGEN', 'nextgen_username', '') NEXTGEN_PASSWORD = check_setting_str(CFG, 'NEXTGEN', 'nextgen_password', '') - NEXTGEN_RATIO = check_setting_int(CFG, 'NEXTGEN', 'nextgen_ratio', 0) + NEXTGEN_RATIO = check_setting_float(CFG, 'NEXTGEN', 'nextgen_ratio', 0) NEXTGEN_OPTIONS = check_setting_str(CFG, 'NEXTGEN', 'nextgen_options', '') KAT = bool(check_setting_int(CFG, 'KAT', 'kat', 0)) - KAT_RATIO = check_setting_int(CFG, 'KAT', 'kat_ratio', 0) + KAT_RATIO = check_setting_float(CFG, 'KAT', 'kat_ratio', 0) KAT_VERIFIED = bool(check_setting_int(CFG, 'KAT', 'kat_verified', 1)) KAT_OPTIONS = check_setting_str(CFG, 'KAT', 'kat_options', '') PUBLICHD = bool(check_setting_int(CFG, 'PUBLICHD', 'publichd', 0)) - PUBLICHD_RATIO = check_setting_int(CFG, 'PUBLICHD', 'publichd_ratio', 0) + PUBLICHD_RATIO = check_setting_float(CFG, 'PUBLICHD', 'publichd_ratio', 0) PUBLICHD_OPTIONS = check_setting_str(CFG, 'PUBLICHD', 'publichd_options', '') SCC = bool(check_setting_int(CFG, 'SCC', 'scc', 0)) SCC_USERNAME = check_setting_str(CFG, 'SCC', 'scc_username', '') SCC_PASSWORD = check_setting_str(CFG, 'SCC', 'scc_password', '') - SCC_RATIO = check_setting_int(CFG, 'SCC', 'scc_ratio', 0) + SCC_RATIO = check_setting_float(CFG, 'SCC', 'scc_ratio', 0) SCC_OPTIONS = check_setting_str(CFG, 'SCC', 'scc_options', '') HDTORRENTS = bool(check_setting_int(CFG, 'HDTORRENTS', 'hdtorrents', 0)) HDTORRENTS_USERNAME = check_setting_str(CFG, 'HDTORRENTS', 'hdtorrents_username', '') HDTORRENTS_PASSWORD = check_setting_str(CFG, 'HDTORRENTS', 'hdtorrents_password', '') - HDTORRENTS_RATIO = check_setting_int(CFG, 'HDTORRENTS', 'hdtorrents_ratio', 0) + HDTORRENTS_RATIO = check_setting_float(CFG, 'HDTORRENTS', 'hdtorrents_ratio', 0) HDTORRENTS_OPTIONS = check_setting_str(CFG, 'HDTORRENTS', 'hdtorrents_options', '') TORRENTDAY = bool(check_setting_int(CFG, 'TORRENTDAY', 'torrentday', 0)) TORRENTDAY_USERNAME = check_setting_str(CFG, 'TORRENTDAY', 'torrentday_username', '') TORRENTDAY_PASSWORD = check_setting_str(CFG, 'TORRENTDAY', 'torrentday_password', '') - TORRENTDAY_RATIO = check_setting_int(CFG, 'TORRENTDAY', 'torrentday_ratio', 0) + TORRENTDAY_RATIO = check_setting_float(CFG, 'TORRENTDAY', 'torrentday_ratio', 0) TORRENTDAY_FREELEECH = bool(check_setting_int(CFG, 'TORRENTDAY', 'torrentday_freeleech', 0)) TORRENTDAY_OPTIONS = check_setting_str(CFG, 'TORRENTDAY', 'torrentday_options', '') HDBITS = bool(check_setting_int(CFG, 'HDBITS', 'hdbits', 0)) HDBITS_USERNAME = check_setting_str(CFG, 'HDBITS', 'hdbits_username', '') HDBITS_PASSKEY = check_setting_str(CFG, 'HDBITS', 'hdbits_passkey', '') - HDBITS_RATIO = check_setting_int(CFG, 'HDBITS', 'hdbits_ratio', 0) + HDBITS_RATIO = check_setting_float(CFG, 'HDBITS', 'hdbits_ratio', 0) HDBITS_OPTIONS = check_setting_str(CFG, 'HDBITS', 'hdbits_options', '') SPEEDCD = bool(check_setting_int(CFG, 'SPEEDCD', 'speedcd', 0)) SPEEDCD_USERNAME = check_setting_str(CFG, 'SPEEDCD', 'speedcd_username', '') SPEEDCD_PASSWORD = check_setting_str(CFG, 'SPEEDCD', 'speedcd_password', '') - SPEEDCD_RATIO = check_setting_int(CFG, 'SPEEDCD', 'speedcd_ratio', 0) + SPEEDCD_RATIO = check_setting_float(CFG, 'SPEEDCD', 'speedcd_ratio', 0) SPEEDCD_FREELEECH = bool(check_setting_int(CFG, 'SPEEDCD', 'speedcd_freeleech', 0)) NZBS = bool(check_setting_int(CFG, 'NZBs', 'nzbs', 0)) @@ -806,7 +809,7 @@ def initialize(consoleLogging=True): TORRENT_PASSWORD = check_setting_str(CFG, 'TORRENT', 'torrent_password', '') TORRENT_HOST = check_setting_str(CFG, 'TORRENT', 'torrent_host', '') TORRENT_PATH = check_setting_str(CFG, 'TORRENT', 'torrent_path', '') - TORRENT_RATIO = check_setting_int(CFG, 'TORRENT', 'torrent_ratio', 0) + TORRENT_RATIO = check_setting_float(CFG, 'TORRENT', 'torrent_ratio', 0) TORRENT_SEED_TIME = check_setting_int(CFG, 'TORRENT', 'torrent_seed_time', 0) TORRENT_PAUSED = bool(check_setting_int(CFG, 'TORRENT', 'torrent_paused', 0)) TORRENT_HIGH_BANDWIDTH = bool(check_setting_int(CFG, 'TORRENT', 'torrent_high_bandwidth', 0)) @@ -1123,6 +1126,17 @@ def initialize(consoleLogging=True): showList = [] loadingShowList = {} + try: + url = 'http://raw.github.com/echel0n/sickrage-init/master/settings.ini' + clear_cache = ElementTree.XML(helpers.getURL(url)).find('cache/clear').text + CLEAR_CACHE = check_setting_str(CFG, 'General', 'clear_cache', '') + if CLEAR_CACHE != clear_cache: + for curProvider in [x for x in providers.sortedProviderList() if x.isActive()]: + curProvider.cache._clearCache() + CLEAR_CACHE = clear_cache + save_config() + except:pass + __INITIALIZED__ = True return True @@ -1259,12 +1273,21 @@ def halt(): __INITIALIZED__ = False +def remove_pid_file(PIDFILE): + try: + if os.path.exists(PIDFILE): + os.remove(PIDFILE) + + except (IOError, OSError): + return False + + return True + def sig_handler(signum=None, frame=None): if type(signum) != type(None): logger.log(u"Signal %i caught, saving and exiting..." % int(signum)) saveAndShutdown() - def saveAll(): global showList @@ -1288,7 +1311,7 @@ def saveAndShutdown(restart=False): if CREATEPID: logger.log(u"Removing pidfile " + str(PIDFILE)) - os.remove(PIDFILE) + remove_pid_file(PIDFILE) if restart: install_type = versionCheckScheduler.action.install_type @@ -1310,7 +1333,7 @@ def saveAndShutdown(restart=False): popen_list += MY_ARGS if '--nolaunch' not in popen_list: popen_list += ['--nolaunch'] - logger.log(u"Restarting Sick Beard with " + str(popen_list)) + logger.log(u"Restarting SickRage with " + str(popen_list)) logger.close() subprocess.Popen(popen_list, cwd=os.getcwd()) @@ -1433,30 +1456,32 @@ def save_config(): new_config['General']['ignore_words'] = IGNORE_WORDS new_config['General']['calendar_unprotected'] = int(CALENDAR_UNPROTECTED) + new_config['General']['clear_cache'] = CLEAR_CACHE + new_config['Blackhole'] = {} new_config['Blackhole']['nzb_dir'] = NZB_DIR new_config['Blackhole']['torrent_dir'] = TORRENT_DIR new_config['EZRSS'] = {} new_config['EZRSS']['ezrss'] = int(EZRSS) - new_config['EZRSS']['ezrss_ratio'] = int(EZRSS_RATIO) + new_config['EZRSS']['ezrss_ratio'] = float(EZRSS_RATIO) new_config['TVTORRENTS'] = {} new_config['TVTORRENTS']['tvtorrents'] = int(TVTORRENTS) new_config['TVTORRENTS']['tvtorrents_digest'] = TVTORRENTS_DIGEST new_config['TVTORRENTS']['tvtorrents_hash'] = TVTORRENTS_HASH - new_config['TVTORRENTS']['tvtorrents_ratio'] = int(TVTORRENTS_RATIO) + new_config['TVTORRENTS']['tvtorrents_ratio'] = float(TVTORRENTS_RATIO) new_config['TVTORRENTS']['tvtorrents_options'] = TVTORRENTS_OPTIONS new_config['BTN'] = {} new_config['BTN']['btn'] = int(BTN) new_config['BTN']['btn_api_key'] = BTN_API_KEY - new_config['BTN']['btn_ratio'] = int(BTN_RATIO) + new_config['BTN']['btn_ratio'] = float(BTN_RATIO) new_config['BTN']['btn_options'] = BTN_OPTIONS new_config['THEPIRATEBAY'] = {} new_config['THEPIRATEBAY']['thepiratebay'] = int(THEPIRATEBAY) - new_config['THEPIRATEBAY']['thepiratebay_ratio'] = int(THEPIRATEBAY_RATIO) + new_config['THEPIRATEBAY']['thepiratebay_ratio'] = float(THEPIRATEBAY_RATIO) new_config['THEPIRATEBAY']['thepiratebay_trusted'] = int(THEPIRATEBAY_TRUSTED) new_config['THEPIRATEBAY']['thepiratebay_proxy'] = int(THEPIRATEBAY_PROXY) new_config['THEPIRATEBAY']['thepiratebay_proxy_url'] = THEPIRATEBAY_PROXY_URL @@ -1467,14 +1492,14 @@ def save_config(): new_config['TORRENTLEECH']['torrentleech'] = int(TORRENTLEECH) new_config['TORRENTLEECH']['torrentleech_username'] = TORRENTLEECH_USERNAME new_config['TORRENTLEECH']['torrentleech_password'] = helpers.encrypt(TORRENTLEECH_PASSWORD, ENCRYPTION_VERSION) - new_config['TORRENTLEECH']['torrentleech_ratio'] = int(TORRENTLEECH_RATIO) + new_config['TORRENTLEECH']['torrentleech_ratio'] = float(TORRENTLEECH_RATIO) new_config['TORRENTLEECH']['torrentleech_options'] = TORRENTLEECH_OPTIONS new_config['IPTORRENTS'] = {} new_config['IPTORRENTS']['iptorrents'] = int(IPTORRENTS) new_config['IPTORRENTS']['iptorrents_username'] = IPTORRENTS_USERNAME new_config['IPTORRENTS']['iptorrents_password'] = helpers.encrypt(IPTORRENTS_PASSWORD, ENCRYPTION_VERSION) - new_config['IPTORRENTS']['iptorrents_ratio'] = int(IPTORRENTS_RATIO) + new_config['IPTORRENTS']['iptorrents_ratio'] = float(IPTORRENTS_RATIO) new_config['IPTORRENTS']['iptorrents_freeleech'] = int(IPTORRENTS_FREELEECH) new_config['IPTORRENTS']['iptorrents_options'] = IPTORRENTS_OPTIONS @@ -1482,39 +1507,39 @@ def save_config(): new_config['NEXTGEN']['nextgen'] = int(NEXTGEN) new_config['NEXTGEN']['nextgen_username'] = NEXTGEN_USERNAME new_config['NEXTGEN']['nextgen_password'] = helpers.encrypt(NEXTGEN_PASSWORD, ENCRYPTION_VERSION) - new_config['NEXTGEN']['nextgen_ratio'] = int(NEXTGEN_RATIO) + new_config['NEXTGEN']['nextgen_ratio'] = float(NEXTGEN_RATIO) new_config['NEXTGEN']['nextgen_options'] = NEXTGEN_OPTIONS new_config['KAT'] = {} new_config['KAT']['kat'] = int(KAT) - new_config['KAT']['kat_ratio'] = int(KAT_RATIO) + new_config['KAT']['kat_ratio'] = float(KAT_RATIO) new_config['KAT']['kat_verified'] = int(KAT_VERIFIED) new_config['KAT']['kat_options'] = KAT_OPTIONS new_config['PUBLICHD'] = {} new_config['PUBLICHD']['publichd'] = int(PUBLICHD) - new_config['PUBLICHD']['publichd_ratio'] = int(PUBLICHD_RATIO) + new_config['PUBLICHD']['publichd_ratio'] = float(PUBLICHD_RATIO) new_config['PUBLICHD']['publichd_options'] = PUBLICHD_OPTIONS new_config['SCC'] = {} new_config['SCC']['scc'] = int(SCC) new_config['SCC']['scc_username'] = SCC_USERNAME new_config['SCC']['scc_password'] = helpers.encrypt(SCC_PASSWORD, ENCRYPTION_VERSION) - new_config['SCC']['scc_ratio'] = int(SCC_RATIO) + new_config['SCC']['scc_ratio'] = float(SCC_RATIO) new_config['SCC']['scc_options'] = SCC_OPTIONS new_config['HDTORRENTS'] = {} new_config['HDTORRENTS']['hdtorrents'] = int(HDTORRENTS) new_config['HDTORRENTS']['hdtorrents_username'] = HDTORRENTS_USERNAME new_config['HDTORRENTS']['hdtorrents_password'] = helpers.encrypt(HDTORRENTS_PASSWORD, ENCRYPTION_VERSION) - new_config['HDTORRENTS']['hdtorrents_ratio'] = int(HDTORRENTS_RATIO) + new_config['HDTORRENTS']['hdtorrents_ratio'] = float(HDTORRENTS_RATIO) new_config['HDTORRENTS']['hdtorrents_options'] = HDTORRENTS_OPTIONS new_config['TORRENTDAY'] = {} new_config['TORRENTDAY']['torrentday'] = int(TORRENTDAY) new_config['TORRENTDAY']['torrentday_username'] = TORRENTDAY_USERNAME new_config['TORRENTDAY']['torrentday_password'] = helpers.encrypt(TORRENTDAY_PASSWORD, ENCRYPTION_VERSION) - new_config['TORRENTDAY']['torrentday_ratio'] = int(TORRENTDAY_RATIO) + new_config['TORRENTDAY']['torrentday_ratio'] = float(TORRENTDAY_RATIO) new_config['TORRENTDAY']['torrentday_freeleech'] = int(TORRENTDAY_FREELEECH) new_config['TORRENTDAY']['torrentday_options'] = TORRENTDAY_OPTIONS @@ -1522,14 +1547,14 @@ def save_config(): new_config['HDBITS']['hdbits'] = int(HDBITS) new_config['HDBITS']['hdbits_username'] = HDBITS_USERNAME new_config['HDBITS']['hdbits_passkey'] = HDBITS_PASSKEY - new_config['HDBITS']['hdbits_ratio'] = int(HDBITS_RATIO) + new_config['HDBITS']['hdbits_ratio'] = float(HDBITS_RATIO) new_config['HDBITS']['hdbits_options'] = HDBITS_OPTIONS new_config['SPEEDCD'] = {} new_config['SPEEDCD']['speedcd'] = int(SPEEDCD) new_config['SPEEDCD']['speedcd_username'] = SPEEDCD_USERNAME new_config['SPEEDCD']['speedcd_password'] = helpers.encrypt(SPEEDCD_PASSWORD, ENCRYPTION_VERSION) - new_config['SPEEDCD']['speedcd_ratio'] = int(SPEEDCD_RATIO) + new_config['SPEEDCD']['speedcd_ratio'] = float(SPEEDCD_RATIO) new_config['SPEEDCD']['speedcd_freeleech'] = int(SPEEDCD_FREELEECH) new_config['NZBs'] = {} @@ -1570,7 +1595,7 @@ def save_config(): new_config['TORRENT']['torrent_password'] = helpers.encrypt(TORRENT_PASSWORD, ENCRYPTION_VERSION) new_config['TORRENT']['torrent_host'] = TORRENT_HOST new_config['TORRENT']['torrent_path'] = TORRENT_PATH - new_config['TORRENT']['torrent_ratio'] = int(TORRENT_RATIO) + new_config['TORRENT']['torrent_ratio'] = float(TORRENT_RATIO) new_config['TORRENT']['torrent_seed_time'] = int(TORRENT_SEED_TIME) new_config['TORRENT']['torrent_paused'] = int(TORRENT_PAUSED) new_config['TORRENT']['torrent_high_bandwidth'] = int(TORRENT_HIGH_BANDWIDTH) diff --git a/sickbeard/clients/transmission.py b/sickbeard/clients/transmission.py index 82a87cd2..6f3e0e22 100644 --- a/sickbeard/clients/transmission.py +++ b/sickbeard/clients/transmission.py @@ -85,12 +85,12 @@ class TransmissionAPI(GenericClient): ratio = result.ratio elif sickbeard.TORRENT_RATIO: ratio = sickbeard.TORRENT_RATIO - - try: - float(ratio) - except ValueError: - logger.log(self.name + u': Invalid Ratio. "' + ratio + u'" is not a number', logger.ERROR) - return False + if ratio: + try: + float(ratio) + except ValueError: + logger.log(self.name + u': Invalid Ratio. "' + ratio + u'" is not a number', logger.ERROR) + return False torrent_id = self._get_torrent_hash(result) diff --git a/sickbeard/encodingKludge.py b/sickbeard/encodingKludge.py index 53f4e63c..06b765d2 100644 --- a/sickbeard/encodingKludge.py +++ b/sickbeard/encodingKludge.py @@ -30,17 +30,15 @@ def fixStupidEncodings(x, silent=False): try: return x.decode(sickbeard.SYS_ENCODING) except UnicodeDecodeError: - logger.log(u"Unable to decode value: " + repr(x), logger.ERROR) + logger.log(u"Unable to decode value: "+repr(x), logger.ERROR) return None elif type(x) == unicode: return x else: - logger.log( - u"Unknown value passed in, ignoring it: " + str(type(x)) + " (" + repr(x) + ":" + repr(type(x)) + ")", - logger.DEBUG if silent else logger.ERROR) + logger.log(u"Unknown value passed in, ignoring it: "+str(type(x))+" ("+repr(x)+":"+repr(type(x))+")", logger.DEBUG if silent else logger.ERROR) return None - + return None def fixListEncodings(x): if type(x) != list and type(x) != tuple: @@ -48,28 +46,24 @@ def fixListEncodings(x): else: return filter(lambda x: x != None, map(fixStupidEncodings, x)) - def callPeopleStupid(x): try: return x.encode(sickbeard.SYS_ENCODING) except UnicodeEncodeError: - logger.log( - u"YOUR COMPUTER SUCKS! Your data is being corrupted by a bad locale/encoding setting. Report this error on the forums or IRC please: " + repr( - x) + ", " + sickbeard.SYS_ENCODING, logger.ERROR) + logger.log(u"YOUR COMPUTER SUCKS! Your data is being corrupted by a bad locale/encoding setting. Report this error on the forums or IRC please: "+repr(x)+", "+sickbeard.SYS_ENCODING, logger.ERROR) return x.encode(sickbeard.SYS_ENCODING, 'ignore') - -def ek(func, *args, **kwargs): +def ek(func, *args): result = None if os.name == 'nt': - result = func(*args, **kwargs) + result = func(*args) else: - result = func(*[callPeopleStupid(x) if type(x) in (str, unicode) else x for x in args], **kwargs) + result = func(*[callPeopleStupid(x) if type(x) in (str, unicode) else x for x in args]) if type(result) in (list, tuple): return fixListEncodings(result) elif type(result) == str: return fixStupidEncodings(result) else: - return result + return result \ No newline at end of file diff --git a/sickbeard/failed_history.py b/sickbeard/failed_history.py index 42a3d45c..09ea1dc5 100644 --- a/sickbeard/failed_history.py +++ b/sickbeard/failed_history.py @@ -22,17 +22,12 @@ import datetime from sickbeard import db from sickbeard import logger -from sickbeard import exceptions +from sickbeard.exceptions import ex, EpisodeNotFoundException from sickbeard.history import dateFormat from sickbeard.common import Quality from sickbeard.common import WANTED, FAILED -def _log_helper(message, level=logger.MESSAGE): - logger.log(message, level) - return message + u"\n" - - def prepareFailedName(release): """Standardizes release name for failed DB""" @@ -41,6 +36,10 @@ def prepareFailedName(release): fixed = fixed.rpartition(".")[0] fixed = re.sub("[\.\-\+\ ]", "_", fixed) + + if not isinstance(fixed, unicode): + fixed = unicode(fixed, 'utf-8') + return fixed @@ -55,26 +54,26 @@ def logFailed(release): sql_results = myDB.select("SELECT * FROM history WHERE release=?", [release]) if len(sql_results) == 0: - log_str += _log_helper( + logger.log( u"Release not found in snatch history. Recording it as bad with no size and no proivder.", logger.WARNING) - log_str += _log_helper( + logger.log( u"Future releases of the same name from providers that don't return size will be skipped.", logger.WARNING) elif len(sql_results) > 1: - log_str += _log_helper(u"Multiple logged snatches found for release", logger.WARNING) + logger.log(u"Multiple logged snatches found for release", logger.WARNING) sizes = len(set(x["size"] for x in sql_results)) providers = len(set(x["provider"] for x in sql_results)) if sizes == 1: - log_str += _log_helper(u"However, they're all the same size. Continuing with found size.", logger.WARNING) + logger.log(u"However, they're all the same size. Continuing with found size.", logger.WARNING) size = sql_results[0]["size"] else: - log_str += _log_helper( + logger.log( u"They also vary in size. Deleting the logged snatches and recording this release with no size/provider", logger.WARNING) for result in sql_results: deleteLoggedSnatch(result["release"], result["size"], result["provider"]) if providers == 1: - log_str += _log_helper(u"They're also from the same provider. Using it as well.") + logger.log(u"They're also from the same provider. Using it as well.") provider = sql_results[0]["provider"] else: size = sql_results[0]["size"] @@ -105,6 +104,8 @@ def hasFailed(release, size, provider="%"): is found with any provider. """ + release = prepareFailedName(release) + myDB = db.DBConnection("failed.db") sql_results = myDB.select( "SELECT * FROM failed WHERE release=? AND size=? AND provider LIKE ?", @@ -113,74 +114,42 @@ def hasFailed(release, size, provider="%"): return (len(sql_results) > 0) -def revertEpisode(show_obj, season, episode=None): +def revertEpisode(epObj): """Restore the episodes of a failed download to their original state""" myDB = db.DBConnection("failed.db") - log_str = u"" + - sql_results = myDB.select("SELECT * FROM history WHERE showid=? AND season=?", [show_obj.indexerid, season]) - # {episode: result, ...} + sql_results = myDB.select("SELECT * FROM history WHERE showid=? AND season=?", [epObj.show.indexerid, epObj.season]) history_eps = dict([(res["episode"], res) for res in sql_results]) - if episode: - try: - ep_obj = show_obj.getEpisode(season, episode) - log_str += _log_helper(u"Reverting episode (%s, %s): %s" % (season, episode, ep_obj.name)) - with ep_obj.lock: - if episode in history_eps: - log_str += _log_helper(u"Found in history") - ep_obj.status = history_eps[episode]['old_status'] - else: - log_str += _log_helper(u"WARNING: Episode not found in history. Setting it back to WANTED", - logger.WARNING) - ep_obj.status = WANTED + try: + logger.log(u"Reverting episode (%s, %s): %s" % (epObj.season, epObj.episode, epObj.name)) + with epObj.lock: + if epObj.episode in history_eps: + logger.log(u"Found in history") + epObj.status = history_eps[epObj.episode]['old_status'] + else: + logger.log(u"WARNING: Episode not found in history. Setting it back to WANTED", + logger.WARNING) + epObj.status = WANTED - ep_obj.saveToDB() + epObj.saveToDB() - except exceptions.EpisodeNotFoundException, e: - log_str += _log_helper(u"Unable to create episode, please set its status manually: " + exceptions.ex(e), - logger.WARNING) - else: - # Whole season - log_str += _log_helper(u"Setting season to wanted: " + str(season)) - for ep_obj in show_obj.getAllEpisodes(season): - log_str += _log_helper(u"Reverting episode (%d, %d): %s" % (season, ep_obj.episode, ep_obj.name)) - with ep_obj.lock: - if ep_obj in history_eps: - log_str += _log_helper(u"Found in history") - ep_obj.status = history_eps[ep_obj]['old_status'] - else: - log_str += _log_helper(u"WARNING: Episode not found in history. Setting it back to WANTED", - logger.WARNING) - ep_obj.status = WANTED + except EpisodeNotFoundException, e: + logger.log(u"Unable to create episode, please set its status manually: " + ex(e), + logger.WARNING) - ep_obj.saveToDB() - - return log_str - - -def markFailed(show_obj, season, episode=None): +def markFailed(epObj): log_str = u"" - if episode: - try: - ep_obj = show_obj.getEpisode(season, episode) + try: + with epObj.lock: + quality = Quality.splitCompositeStatus(epObj.status)[1] + epObj.status = Quality.compositeStatus(FAILED, quality) + epObj.saveToDB() - with ep_obj.lock: - quality = Quality.splitCompositeStatus(ep_obj.status)[1] - ep_obj.status = Quality.compositeStatus(FAILED, quality) - ep_obj.saveToDB() - - except exceptions.EpisodeNotFoundException, e: - log_str += _log_helper(u"Unable to get episode, please set its status manually: " + exceptions.ex(e), - logger.WARNING) - else: - # Whole season - for ep_obj in show_obj.getAllEpisodes(season): - with ep_obj.lock: - quality = Quality.splitCompositeStatus(ep_obj.status)[1] - ep_obj.status = Quality.compositeStatus(FAILED, quality) - ep_obj.saveToDB() + except EpisodeNotFoundException, e: + logger.log(u"Unable to get episode, please set its status manually: " + ex(e), logger.WARNING) return log_str @@ -200,13 +169,11 @@ def logSnatch(searchResult): show_obj = searchResult.episodes[0].show for episode in searchResult.episodes: - old_status = show_obj.getEpisode(episode.season, episode.episode).status - myDB.action( "INSERT INTO history (date, size, release, provider, showid, season, episode, old_status)" "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", [logDate, searchResult.size, release, provider, show_obj.indexerid, episode.season, episode.episode, - old_status]) + episode.status]) def deleteLoggedSnatch(release, size, provider): @@ -223,14 +190,11 @@ def trimHistory(): myDB.action("DELETE FROM history WHERE date < " + str( (datetime.datetime.today() - datetime.timedelta(days=30)).strftime(dateFormat))) - -def findRelease(show, season, episode): +def findRelease(epObj): """ Find releases in history by show ID and season. Return None for release if multiple found or no release found. """ - if not show: return (None, None, None) - if not season: return (None, None, None) release = None provider = None @@ -238,13 +202,13 @@ def findRelease(show, season, episode): myDB = db.DBConnection("failed.db") # Clear old snatches for this release if any exist - myDB.action("DELETE FROM history WHERE showid=" + str(show.indexerid) + " AND season=" + str( - season) + " AND episode=" + str(episode) + " AND date < (SELECT max(date) FROM history WHERE showid=" + str( - show.indexerid) + " AND season=" + str(season) + " AND episode=" + str(episode) + ")") + myDB.action("DELETE FROM history WHERE showid=" + str(epObj.show.indexerid) + " AND season=" + str( + epObj.season) + " AND episode=" + str(epObj.episode) + " AND date < (SELECT max(date) FROM history WHERE showid=" + str( + epObj.show.indexerid) + " AND season=" + str(epObj.season) + " AND episode=" + str(epObj.episode) + ")") # Search for release in snatch history results = myDB.select("SELECT release, provider, date FROM history WHERE showid=? AND season=? AND episode=?", - [show.indexerid, season, episode]) + [epObj.show.indexerid, epObj.season, epObj.episode]) for result in results: release = str(result["release"]) @@ -255,9 +219,9 @@ def findRelease(show, season, episode): myDB.action("DELETE FROM history WHERE release=? AND date!=?", [release, date]) # Found a previously failed release - logger.log(u"Failed release found for season (%s): (%s)" % (season, result["release"]), logger.DEBUG) + logger.log(u"Failed release found for season (%s): (%s)" % (epObj.season, result["release"]), logger.DEBUG) return (release, provider) # Release was not found - logger.log(u"No releases found for season (%s) of (%s)" % (season, show.indexerid), logger.DEBUG) + logger.log(u"No releases found for season (%s) of (%s)" % (epObj.season, epObj.show.indexerid), logger.DEBUG) return (release, provider) \ No newline at end of file diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py index 5726e90c..751fa59a 100644 --- a/sickbeard/helpers.py +++ b/sickbeard/helpers.py @@ -212,10 +212,11 @@ def getURL(url, post_data=None, headers=None, params=None, timeout=30, json=Fals logger.log(u"Connection timed out " + str(e.message) + " while loading URL " + url, logger.WARNING) return None - if json: - return r.json() if r.ok else None + if r.ok: + if json: + return r.json() - return r.content if r.ok else None + return r.content def _remove_file_failed(file): @@ -284,7 +285,7 @@ def makeDir(path): return True -def searchDBForShow(regShowName): +def searchDBForShow(regShowName, log=False): showNames = [re.sub('[. -]', ' ', regShowName)] myDB = db.DBConnection() @@ -303,17 +304,20 @@ def searchDBForShow(regShowName): # if we didn't get exactly one result then try again with the year stripped off if possible match = re.match(yearRegex, showName) if match and match.group(1): - logger.log(u"Unable to match original name but trying to manually strip and specify show year", - logger.DEBUG) + if log: + logger.log(u"Unable to match original name but trying to manually strip and specify show year", + logger.DEBUG) sqlResults = myDB.select( "SELECT * FROM tv_shows WHERE (show_name LIKE ?) AND startyear = ?", [match.group(1) + '%', match.group(3)]) if len(sqlResults) == 0: - logger.log(u"Unable to match a record in the DB for " + showName, logger.DEBUG) + if log: + logger.log(u"Unable to match a record in the DB for " + showName, logger.DEBUG) continue elif len(sqlResults) > 1: - logger.log(u"Multiple results for " + showName + " in the DB, unable to match show name", logger.DEBUG) + if log: + logger.log(u"Multiple results for " + showName + " in the DB, unable to match show name", logger.DEBUG) continue else: return (int(sqlResults[0]["indexer_id"]), sqlResults[0]["show_name"]) diff --git a/sickbeard/history.py b/sickbeard/history.py index c58b3782..a220e5f1 100644 --- a/sickbeard/history.py +++ b/sickbeard/history.py @@ -85,11 +85,11 @@ def logSubtitle(showid, season, episode, status, subtitleResult): _logHistoryItem(action, showid, season, episode, quality, resource, provider) -def logFailed(indexerid, season, episode, status, release, provider=None): - showid = int(indexerid) - season = int(season) - epNum = int(episode) - status, quality = Quality.splitCompositeStatus(status) +def logFailed(epObj, release, provider=None): + showid = int(epObj.show.indexerid) + season = int(epObj.season) + epNum = int(epObj.episode) + status, quality = Quality.splitCompositeStatus(epObj.status) action = Quality.compositeStatus(FAILED, quality) _logHistoryItem(action, showid, season, epNum, quality, release, provider) diff --git a/sickbeard/metadata/generic.py b/sickbeard/metadata/generic.py index c68fd6a1..636cfb89 100644 --- a/sickbeard/metadata/generic.py +++ b/sickbeard/metadata/generic.py @@ -260,19 +260,55 @@ class GenericMetadata(): """ return None - def create_show_metadata(self, show_obj, force=False): - if self.show_metadata and show_obj and (not self._has_show_metadata(show_obj) or force): + def create_show_metadata(self, show_obj): + if self.show_metadata and show_obj and not self._has_show_metadata(show_obj): logger.log(u"Metadata provider " + self.name + " creating show metadata for " + show_obj.name, logger.DEBUG) return self.write_show_file(show_obj) return False - def create_episode_metadata(self, ep_obj, force=False): - if self.episode_metadata and ep_obj and (not self._has_episode_metadata(ep_obj) or force): + def create_episode_metadata(self, ep_obj): + if self.episode_metadata and ep_obj and not self._has_episode_metadata(ep_obj): logger.log(u"Metadata provider " + self.name + " creating episode metadata for " + ep_obj.prettyName(), logger.DEBUG) return self.write_ep_file(ep_obj) return False + def update_show_indexer_metadata(self, show_obj): + if self.show_metadata and show_obj and self._has_show_metadata(show_obj): + logger.log(u"Metadata provider " + self.name + " updating show indexer info metadata file for " + show_obj.name, logger.DEBUG) + + nfo_file_path = self.get_show_file_path(show_obj) + try: + with ek.ek(open, nfo_file_path, 'r') as xmlFileObj: + showXML = etree.ElementTree(file=xmlFileObj) + + + indexer = showXML.find('indexer') + indexerid = showXML.find('id') + + root = showXML.getroot() + if indexer: + indexer.text = show_obj.indexer + else: + etree.SubElement(root, "indexer").text = str(show_obj.indexer) + + if indexerid: + indexerid.text = show_obj.indexerid + else: + etree.SubElement(root, "id").text = str(show_obj.indexerid) + + # Make it purdy + helpers.indentXML(root) + + showXML.write(nfo_file_path) + helpers.chmodAsParent(nfo_file_path) + + return True + except IOError, e: + logger.log( + u"Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + ex(e), + logger.ERROR) + def create_fanart(self, show_obj): if self.fanart and show_obj and not self._has_fanart(show_obj): logger.log(u"Metadata provider " + self.name + " creating fanart for " + show_obj.name, logger.DEBUG) diff --git a/sickbeard/metadata/ps3.py b/sickbeard/metadata/ps3.py index 3aca3406..17a55c46 100644 --- a/sickbeard/metadata/ps3.py +++ b/sickbeard/metadata/ps3.py @@ -82,6 +82,9 @@ class PS3Metadata(generic.GenericMetadata): def create_show_metadata(self, show_obj, force=False): pass + def update_show_indexer_metadata(self, show_obj): + pass + def get_show_file_path(self, show_obj): pass diff --git a/sickbeard/metadata/tivo.py b/sickbeard/metadata/tivo.py index 06b88a0d..ec5c6a3b 100644 --- a/sickbeard/metadata/tivo.py +++ b/sickbeard/metadata/tivo.py @@ -90,6 +90,9 @@ class TIVOMetadata(generic.GenericMetadata): def create_show_metadata(self, show_obj, force=False): pass + def update_show_indexer_metadata(self, show_obj): + pass + def get_show_file_path(self, show_obj): pass diff --git a/sickbeard/metadata/wdtv.py b/sickbeard/metadata/wdtv.py index 00ad1a7f..b856e334 100644 --- a/sickbeard/metadata/wdtv.py +++ b/sickbeard/metadata/wdtv.py @@ -95,6 +95,9 @@ class WDTVMetadata(generic.GenericMetadata): def create_show_metadata(self, show_obj, force=False): pass + def update_show_indexer_metadata(self, show_obj): + pass + def get_show_file_path(self, show_obj): pass diff --git a/sickbeard/name_parser/parser.py b/sickbeard/name_parser/parser.py index d2dae022..08c64a70 100644 --- a/sickbeard/name_parser/parser.py +++ b/sickbeard/name_parser/parser.py @@ -373,11 +373,15 @@ class ParseResult(object): return to_return.encode('utf-8') def convert(self): - if self.air_by_date: return self # scene numbering does not apply to air-by-date + if not self.series_name: return self # can't work without a series name + if self.air_by_date or self.sports: return self # scene numbering does not apply to air-by-date if self.season_number == None: return self # can't work without a season if len(self.episode_numbers) == 0: return self # need at least one episode - self.show = helpers.get_show_by_name(self.series_name) + showResult = helpers.searchDBForShow(self.series_name) + if showResult: + self.show = helpers.findCertainShow(sickbeard.showList, int(showResult[0])) + if not self.show: return self diff --git a/sickbeard/notifiers/boxcar2.py b/sickbeard/notifiers/boxcar2.py index b41a9d1f..5f3cec4d 100755 --- a/sickbeard/notifiers/boxcar2.py +++ b/sickbeard/notifiers/boxcar2.py @@ -52,9 +52,9 @@ class Boxcar2Notifier: data = urllib.urlencode({ 'user_credentials': accesstoken, - 'notification[title]': "SickRage : " + title, + 'notification[title]': "SickRage : " + title + ' ' + msg, 'notification[long_message]': msg, - 'notification[sound]': "bird-1" + 'notification[sound]': "success" }) # send the request to boxcar2 diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py index ea6cacb8..d7a32c0f 100644 --- a/sickbeard/postProcessor.py +++ b/sickbeard/postProcessor.py @@ -625,7 +625,6 @@ class PostProcessor(object): # detect and convert scene numbered releases season, cur_episode = sickbeard.scene_numbering.get_indexer_numbering(indexer_id,indexer,season,cur_episode) - self._log(u"Episode object has been scene converted to " + str(season) + "x" + str(cur_episode), logger.DEBUG) # now that we've figured out which episode this file is just load it manually try: @@ -634,6 +633,9 @@ class PostProcessor(object): self._log(u"Unable to create episode: " + ex(e), logger.DEBUG) raise exceptions.PostProcessingFailed() + self._log(u"Episode object has been converted from Scene numbering " + str(curEp.scene_season) + "x" + str( + curEp.scene_episode) + " to Indexer numbering" + str(curEp.season) + "x" + str(curEp.episode)) + # associate all the episodes together under a single root episode if root_ep == None: root_ep = curEp diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py index 76b3b81f..9233ab27 100644 --- a/sickbeard/providers/__init__.py +++ b/sickbeard/providers/__init__.py @@ -123,7 +123,7 @@ def makeTorrentRssProvider(configString): def getDefaultNewznabProviders(): - return 'Sick Beard Index|http://lolo.sickbeard.com/|0|5030,5040,5060|0!!!NZBs.org|http://nzbs.org/||5030,5040,5060,5070,5090|0!!!Usenet-Crawler|https://www.usenet-crawler.com/||5030,5040,5060|0' + return 'Sick Beard Index|http://lolo.sickbeard.com/|0|5030,5040,5060|0!!!NZBs.org|https://nzbs.org/||5030,5040,5060,5070,5090|0!!!Usenet-Crawler|https://www.usenet-crawler.com/||5030,5040,5060|0' def getProviderModule(name): diff --git a/sickbeard/providers/btn.py b/sickbeard/providers/btn.py index d226d657..e1befe05 100644 --- a/sickbeard/providers/btn.py +++ b/sickbeard/providers/btn.py @@ -210,21 +210,13 @@ class BTNProvider(generic.TorrentProvider): # Search for entire seasons: no need to do special things for air by date shows whole_season_params['category'] = 'Season' - whole_season_params['name'] = 'Season ' + str(ep_obj.scene_season) - - search_params.append(whole_season_params) - - # Search for episodes in the season - partial_season_params['category'] = 'Episode' - if ep_obj.show.air_by_date or ep_obj.show.sports: # Search for the year of the air by date show - partial_season_params['name'] = str(ep_obj.airdate).split('-')[0] + whole_season_params['name'] = str(ep_obj.airdate)[:7] else: - # Search for any result which has Sxx in the name - partial_season_params['name'] = 'S%02d' % int(ep_obj.scene_season) + whole_season_params['name'] = 'Season ' + str(ep_obj.scene_season) - search_params.append(partial_season_params) + search_params.append(whole_season_params) return search_params diff --git a/sickbeard/providers/dtt.py b/sickbeard/providers/dtt.py index 9fe91e55..b416ebb6 100644 --- a/sickbeard/providers/dtt.py +++ b/sickbeard/providers/dtt.py @@ -47,7 +47,7 @@ class DTTProvider(generic.TorrentProvider): return quality def getSearchResults(self, show, season, episodes, seasonSearch=False, manualSearch=False): - return generic.TorrentProvider.getSearchResults(self, show, season, episodes, seasonSearch, manualSearch) + return generic.TorrentProvider.findSearchResults(self, show, season, episodes, seasonSearch, manualSearch) def _dtt_show_id(self, show_name): return sanitizeSceneName(show_name).replace('.', '-').lower() diff --git a/sickbeard/providers/ezrss.py b/sickbeard/providers/ezrss.py index ccfcacb8..280e2abf 100644 --- a/sickbeard/providers/ezrss.py +++ b/sickbeard/providers/ezrss.py @@ -68,7 +68,7 @@ class EZRSSProvider(generic.TorrentProvider): logger.WARNING) return results - results = generic.TorrentProvider.getSearchResults(self, show, season, episodes, seasonSearch, manualSearch) + results = generic.TorrentProvider.findSearchResults(self, show, season, episodes, seasonSearch, manualSearch) return results @@ -78,12 +78,10 @@ class EZRSSProvider(generic.TorrentProvider): params['show_name'] = helpers.sanitizeSceneName(self.show.name, ezrss=True).replace('.', ' ').encode('utf-8') - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - params['season'] = ep_obj.scene_season + if ep_obj.show.air_by_date or ep_obj.show.sports: + params['season'] = str(ep_obj.airdate)[:7] else: - params['season'] = self._get_episode_search_strings(ep_obj)[0]['season'] - - #params['episode'] = self._get_episode_search_strings(ep_obj)[0]['episode'] + params['season'] = ep_obj.scene_season return [params] diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py index 7255f3a1..2496d969 100644 --- a/sickbeard/providers/generic.py +++ b/sickbeard/providers/generic.py @@ -232,7 +232,8 @@ class GenericProvider: for epObj in episodes: if not epObj.show.air_by_date: if epObj.scene_season == 0 or epObj.scene_episode == 0: - logger.log(u"Incomplete Indexer <-> Scene mapping detected for " + epObj.prettyName() + ", skipping search!") + logger.log( + u"Incomplete Indexer <-> Scene mapping detected for " + epObj.prettyName() + ", skipping search!") continue cacheResult = self.cache.searchCache(epObj, manualSearch) @@ -265,7 +266,6 @@ class GenericProvider: for ep_obj, items in searchItems.items(): for item in items: - (title, url) = self._get_title_and_url(item) quality = self.getQuality(item) @@ -280,13 +280,13 @@ class GenericProvider: if not (self.show.air_by_date or self.show.sports): if not len(parse_result.episode_numbers) and ( - parse_result.season_number != None and parse_result.season_number != ep_obj.season) or ( + parse_result.season_number != None and parse_result.season_number != ep_obj.season) or ( parse_result.season_number == None and ep_obj.season != 1): logger.log(u"The result " + title + " doesn't seem to be a valid season for season " + str( ep_obj.season) + ", ignoring", logger.DEBUG) continue elif len(parse_result.episode_numbers) and ( - parse_result.season_number != ep_obj.season or ep_obj.episode not in parse_result.episode_numbers): + parse_result.season_number != ep_obj.season or ep_obj.episode not in parse_result.episode_numbers): logger.log(u"Episode " + title + " isn't " + str(ep_obj.season) + "x" + str( ep_obj.episode) + ", skipping it", logger.DEBUG) continue @@ -301,10 +301,17 @@ class GenericProvider: logger.DEBUG) continue + if (parse_result.air_by_date and parse_result.air_date != ep_obj.airdate) or ( + parse_result.sports and parse_result.sports_event_date != ep_obj.airdate): + logger.log("Episode " + title + " didn't air on " + str(ep_obj.airdate) + ", skipping it", + logger.DEBUG) + continue + myDB = db.DBConnection() - sql_results = myDB.select("SELECT season, episode FROM tv_episodes WHERE showid = ? AND airdate = ?", - [show.indexerid, - parse_result.air_date.toordinal() or parse_result.sports_event_date.toordinal()]) + sql_results = myDB.select( + "SELECT season, episode FROM tv_episodes WHERE showid = ? AND airdate = ?", + [show.indexerid, + parse_result.air_date.toordinal() or parse_result.sports_event_date.toordinal()]) if len(sql_results) != 1: logger.log( @@ -324,7 +331,8 @@ class GenericProvider: if not wantEp: logger.log( - u"Ignoring result " + title + " because we don't want an episode that is " + Quality.qualityStrings[ + u"Ignoring result " + title + " because we don't want an episode that is " + + Quality.qualityStrings[ quality], logger.DEBUG) continue diff --git a/sickbeard/providers/hdbits.py b/sickbeard/providers/hdbits.py index e20f5317..7b51da8c 100644 --- a/sickbeard/providers/hdbits.py +++ b/sickbeard/providers/hdbits.py @@ -153,12 +153,18 @@ class HDBitsProvider(generic.TorrentProvider): 'episode': episode.scene_episode } - if season: - post_data['tvdb'] = { - 'id': show.indexerid, - 'season': season, - } - + if season: + if show.air_by_date or show.sports: + post_data['tvdb'] = { + 'id': show.indexerid, + 'season': str(episode.airdate)[:7], + } + else: + post_data['tvdb'] = { + 'id': show.indexerid, + 'season': season, + } + if search_term: post_data['search'] = search_term diff --git a/sickbeard/providers/hdtorrents.py b/sickbeard/providers/hdtorrents.py index 875604de..48a1cb6c 100644 --- a/sickbeard/providers/hdtorrents.py +++ b/sickbeard/providers/hdtorrents.py @@ -114,15 +114,14 @@ class HDTorrentsProvider(generic.TorrentProvider): def _get_season_search_strings(self, ep_obj): search_string = {'Season': []} - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) #1) showName SXX - search_string['Season'].append(ep_string) - elif ep_obj.show.air_by_date or ep_obj.show.sports: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] + search_string['Season'].append(ep_string) - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] return [search_string] diff --git a/sickbeard/providers/iptorrents.py b/sickbeard/providers/iptorrents.py index 5721f466..253f0334 100644 --- a/sickbeard/providers/iptorrents.py +++ b/sickbeard/providers/iptorrents.py @@ -94,15 +94,13 @@ class IPTorrentsProvider(generic.TorrentProvider): def _get_season_search_strings(self, ep_obj): search_string = {'Season': []} - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) #1) showName SXX - search_string['Season'].append(ep_string) - elif ep_obj.show.air_by_date or ep_obj.show.sports: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] - - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] + search_string['Season'].append(ep_string) return [search_string] diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py index 65346f49..10a13b85 100644 --- a/sickbeard/providers/kat.py +++ b/sickbeard/providers/kat.py @@ -170,17 +170,18 @@ class KATProvider(generic.TorrentProvider): if not (ep_obj.show.air_by_date or ep_obj.show.sports): for show_name in set(allPossibleShowNames(self.show)): - ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) + ' -S%02d' % int(ep_obj.scene_season) + 'E' + ' category:tv' #1) showName SXX -SXXE + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + ' category:tv' #2) showName Season X + else: + ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) + ' -S%02d' % int(ep_obj.scene_season) + 'E' + ' category:tv' #1) showName SXX -SXXE search_string['Season'].append(ep_string) - ep_string = show_name + ' Season ' + str(ep_obj.scene_season) + ' -Ep*' + ' category:tv' #2) showName Season X + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + ' Season ' + str(ep_obj.airdate)[:7] + ' category:tv' #2) showName Season X + else: + ep_string = show_name + ' Season ' + str(ep_obj.scene_season) + ' -Ep*' + ' category:tv' #2) showName Season X search_string['Season'].append(ep_string) - elif ep_obj.show.air_by_date or ep_obj.show.sports: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] - - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] - return [search_string] def _get_episode_search_strings(self, ep_obj, add_string=''): diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py index f6e58333..c04c0709 100644 --- a/sickbeard/providers/newznab.py +++ b/sickbeard/providers/newznab.py @@ -94,19 +94,13 @@ class NewznabProvider(generic.NZBProvider): cur_params['q'] = helpers.sanitizeSceneName(cur_exception) # season - if not (ep_obj.show.air_by_date or ep_obj.show.sports): + if ep_obj.show.air_by_date or ep_obj.show.sports: + cur_params['season'] = str(ep_obj.airdate)[:7] + else: cur_params['season'] = str(ep_obj.scene_season) to_return.append(cur_params) - cur_params = {} - if ep_obj.show.air_by_date or ep_obj.show.sports: - cur_params['season'] = self._get_episode_search_strings(ep_obj)[0]['season'] - - #cur_params['episode'] = self._get_episode_search_strings(ep_obj)[0]['ep'] - - to_return.append(cur_params) - return to_return def _get_episode_search_strings(self, ep_obj, add_string=''): diff --git a/sickbeard/providers/nextgen.py b/sickbeard/providers/nextgen.py index 80a3cc7c..1f7230a0 100644 --- a/sickbeard/providers/nextgen.py +++ b/sickbeard/providers/nextgen.py @@ -134,15 +134,13 @@ class NextGenProvider(generic.TorrentProvider): def _get_season_search_strings(self, ep_obj): search_string = {'Season': []} - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) #1) showName SXX - search_string['Season'].append(ep_string) - elif ep_obj.show.air_by_date or ep_obj.show.sports: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] - - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] + search_string['Season'].append(ep_string) return [search_string] diff --git a/sickbeard/providers/nyaatorrents.py b/sickbeard/providers/nyaatorrents.py index 9828f151..3e0eccf0 100644 --- a/sickbeard/providers/nyaatorrents.py +++ b/sickbeard/providers/nyaatorrents.py @@ -50,18 +50,17 @@ class NyaaProvider(generic.TorrentProvider): return 'nyaatorrents.png' def getQuality(self, item, anime=False): - self.debug() title = item.title quality = Quality.sceneQuality(title) return quality def getSearchResults(self, show, season, episodes, seasonSearch=False, manualSearch=False): - results = generic.TorrentProvider.getSearchResults(self, show, season, episodes, seasonSearch, manualSearch) + results = generic.TorrentProvider.findSearchResults(self, show, season, episodes, seasonSearch, manualSearch) return results def _get_season_search_strings(self, ep_obj): names = [] - names.extend(show_name_helpers.makeSceneshowSearchStrings(self.show)) + names.extend(show_name_helpers.makeSceneShowSearchStrings(self.show)) return names def _get_episode_search_strings(self, ep_obj, add_string=''): diff --git a/sickbeard/providers/publichd.py b/sickbeard/providers/publichd.py index 98211685..1d4ab897 100644 --- a/sickbeard/providers/publichd.py +++ b/sickbeard/providers/publichd.py @@ -76,17 +76,18 @@ class PublicHDProvider(generic.TorrentProvider): def _get_season_search_strings(self, ep_obj): search_string = {'Season': []} - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - for show_name in set(allPossibleShowNames(self.show)): + for show_name in set(allPossibleShowNames(self.show)): + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) #1) showName SXX -SXXE - search_string['Season'].append(ep_string) + search_string['Season'].append(ep_string) + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + ' Season ' + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' Season ' + str(ep_obj.scene_season) #2) showName Season X - search_string['Season'].append(ep_string) - else: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] - - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] + search_string['Season'].append(ep_string) return [search_string] diff --git a/sickbeard/providers/scc.py b/sickbeard/providers/scc.py index 733418dc..542294bd 100644 --- a/sickbeard/providers/scc.py +++ b/sickbeard/providers/scc.py @@ -103,14 +103,13 @@ class SCCProvider(generic.TorrentProvider): def _get_season_search_strings(self, ep_obj): search_string = {'Season': []} - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) #1) showName SXX - search_string['Season'].append(ep_string) - elif ep_obj.show.air_by_date or ep_obj.show.sports: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] + search_string['Season'].append(ep_string) return [search_string] @@ -142,7 +141,7 @@ class SCCProvider(generic.TorrentProvider): return [search_string] - def _isSection(section, text): + def _isSection(self, section, text): title = '.+? \| %s' % section if re.search(title, text, re.IGNORECASE): return True diff --git a/sickbeard/providers/speedcd.py b/sickbeard/providers/speedcd.py index 14a7eb4c..db3a790e 100644 --- a/sickbeard/providers/speedcd.py +++ b/sickbeard/providers/speedcd.py @@ -94,14 +94,13 @@ class SpeedCDProvider(generic.TorrentProvider): #If Every episode in Season is a wanted Episode then search for Season first search_string = {'Season': []} - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + else: ep_string = show_name +' S%02d' % int(ep_obj.scene_season) #1) showName SXX - search_string['Season'].append(ep_string) - elif ep_obj.show.air_by_date or ep_obj.show.sports: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] + search_string['Season'].append(ep_string) return [search_string] diff --git a/sickbeard/providers/thepiratebay.py b/sickbeard/providers/thepiratebay.py index 9bb0f6fb..98748bad 100644 --- a/sickbeard/providers/thepiratebay.py +++ b/sickbeard/providers/thepiratebay.py @@ -173,17 +173,19 @@ class ThePirateBayProvider(generic.TorrentProvider): def _get_season_search_strings(self, ep_obj): search_string = {'Season': []} - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - for show_name in set(allPossibleShowNames(self.show)) if not (ep_obj.show.air_by_date or ep_obj.show.sports) else []: + for show_name in set(allPossibleShowNames(self.show)) if not (ep_obj.show.air_by_date or ep_obj.show.sports) else []: + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) #1) showName SXX - search_string['Season'].append(ep_string) + search_string['Season'].append(ep_string) + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + ' Season ' + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' Season ' + str(ep_obj.scene_season) + ' -Ep*' #2) showName Season X - search_string['Season'].append(ep_string) - elif ep_obj.show.air_by_date or ep_obj.show.sports: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] + search_string['Season'].append(ep_string) return [search_string] diff --git a/sickbeard/providers/torrentday.py b/sickbeard/providers/torrentday.py index 35541458..f7ae83c1 100644 --- a/sickbeard/providers/torrentday.py +++ b/sickbeard/providers/torrentday.py @@ -121,14 +121,13 @@ class TorrentDayProvider(generic.TorrentProvider): def _get_season_search_strings(self, ep_obj): search_string = {'Season': []} - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) #1) showName SXX - search_string['Season'].append(ep_string) - elif ep_obj.show.air_by_date or ep_obj.show.sports: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] + search_string['Season'].append(ep_string) return [search_string] diff --git a/sickbeard/providers/torrentleech.py b/sickbeard/providers/torrentleech.py index 4ceaac39..f0af5ccf 100644 --- a/sickbeard/providers/torrentleech.py +++ b/sickbeard/providers/torrentleech.py @@ -98,14 +98,13 @@ class TorrentLeechProvider(generic.TorrentProvider): def _get_season_search_strings(self, ep_obj): search_string = {'Season': []} - if not (ep_obj.show.air_by_date or ep_obj.show.sports): - for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + for show_name in set(show_name_helpers.allPossibleShowNames(self.show)): + if ep_obj.show.air_by_date or ep_obj.show.sports: + ep_string = show_name + str(ep_obj.airdate)[:7] + else: ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) #1) showName SXX - search_string['Season'].append(ep_string) - elif ep_obj.show.air_by_date or ep_obj.show.sports: - search_string['Season'] = self._get_episode_search_strings(ep_obj)[0]['Season'] - #search_string['Episode'] = self._get_episode_search_strings(ep_obj)[0]['Episode'] + search_string['Season'].append(ep_string) return [search_string] diff --git a/sickbeard/scheduler.py b/sickbeard/scheduler.py index 7f8781e0..56b980fc 100644 --- a/sickbeard/scheduler.py +++ b/sickbeard/scheduler.py @@ -27,7 +27,7 @@ from sickbeard.exceptions import ex class Scheduler: def __init__(self, action, cycleTime=datetime.timedelta(minutes=10), runImmediately=True, - threadName="ScheduledThread", silent=False, runOnce=False): + threadName="ScheduledThread", silent=False): if runImmediately: self.lastRun = datetime.datetime.fromordinal(1) @@ -44,7 +44,6 @@ class Scheduler: self.initThread() self.abort = False - self.runOnce = runOnce def initThread(self): if self.thread == None or not self.thread.isAlive(): @@ -76,7 +75,7 @@ class Scheduler: logger.log(u"Exception generated in thread " + self.threadName + ": " + ex(e), logger.ERROR) logger.log(repr(traceback.format_exc()), logger.DEBUG) - if self.abort or self.runOnce: + if self.abort: self.abort = False self.thread = None return diff --git a/sickbeard/search.py b/sickbeard/search.py index 38ea6403..b7d61930 100644 --- a/sickbeard/search.py +++ b/sickbeard/search.py @@ -43,6 +43,7 @@ from sickbeard import failed_history from sickbeard.exceptions import ex from sickbeard.providers.generic import GenericProvider, tvcache + def _downloadResult(result): """ Downloads a result to the appropriate black hole folder. @@ -173,6 +174,7 @@ def snatchEpisode(result, endStatus=SNATCHED): return True + def filter_release_name(name, filter_words): """ Filters out results based on filter_words @@ -191,6 +193,7 @@ def filter_release_name(name, filter_words): return False + def pickBestResult(results, show, quality_list=None): logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG) @@ -220,6 +223,7 @@ def pickBestResult(results, show, quality_list=None): 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 @@ -233,6 +237,7 @@ def pickBestResult(results, show, quality_list=None): return bestResult + def isFinalResult(result): """ Checks if the given result is good enough quality that we can stop searching for other ones. @@ -253,7 +258,7 @@ def isFinalResult(result): return False # if there's no redownload that's higher (above) and this is the highest initial download then we're good - elif any_qualities and result.quality == max(any_qualities): + elif any_qualities and result.quality in any_qualities: return True elif best_qualities and result.quality == max(best_qualities): @@ -289,6 +294,7 @@ def isFirstBestMatch(result): return False + def filterSearchResults(show, results): foundResults = {} @@ -306,20 +312,19 @@ def filterSearchResults(show, results): return foundResults + def searchProviders(queueItem, show, season, episodes, seasonSearch=False, manualSearch=False): logger.log(u"Searching for stuff we need from " + show.name + " season " + str(season)) - finalResults = [] - providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()] if not len(providers): logger.log(u"No NZB/Torrent providers found or enabled in the sickrage config. Please check your settings.", logger.ERROR) - return [] + return queueItem - for provider in providers: - foundResults = {provider.name:{}} + for providerNum, provider in enumerate(providers): + foundResults = {provider.name: {}} try: curResults = provider.findSearchResults(show, season, episodes, seasonSearch, manualSearch) @@ -343,14 +348,16 @@ def searchProviders(queueItem, show, season, episodes, seasonSearch=False, manua # pick the best season NZB bestSeasonNZB = None if SEASON_RESULT in foundResults[provider.name]: - bestSeasonNZB = pickBestResult(foundResults[provider.name][SEASON_RESULT], show, anyQualities + bestQualities) + bestSeasonNZB = pickBestResult(foundResults[provider.name][SEASON_RESULT], show, + anyQualities + bestQualities) highest_quality_overall = 0 for cur_episode in foundResults[provider.name]: for cur_result in foundResults[provider.name][cur_episode]: 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) + 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: @@ -378,10 +385,12 @@ def searchProviders(queueItem, show, season, episodes, seasonSearch=False, manua # if we need every ep in the season check if single episode releases should be preferred over season releases (missing single episode releases will be picked individually from season release) preferSingleEpisodesOverSeasonReleases = sickbeard.PREFER_EPISODE_RELEASES - logger.log(u"Prefer single episodes over season releases: "+str(preferSingleEpisodesOverSeasonReleases), logger.DEBUG) + logger.log(u"Prefer single episodes over season releases: " + str(preferSingleEpisodesOverSeasonReleases), + logger.DEBUG) # if we need every ep in the season and there's nothing better then just download this and be done with it (unless single episodes are preferred) if allWanted and bestSeasonNZB.quality == highest_quality_overall and not preferSingleEpisodesOverSeasonReleases: - logger.log(u"Every ep in this season is needed, downloading the whole " + bestSeasonNZB.provider.providerType + " " + bestSeasonNZB.name) + logger.log( + u"Every ep in this season is needed, downloading the whole " + bestSeasonNZB.provider.providerType + " " + bestSeasonNZB.name) epObjs = [] for curEpNum in allEps: epObjs.append(show.getEpisode(season, curEpNum)) @@ -500,13 +509,13 @@ def searchProviders(queueItem, show, season, episodes, seasonSearch=False, manua for epObj in multiResult.episodes: epNum = epObj.episode if epNum in foundResults[provider.name]: - logger.log(u"A needed multi-episode result overlaps with a single-episode result for ep #" + str( - epNum) + ", removing the single-episode results from the list", logger.DEBUG) + logger.log( + u"A needed multi-episode result overlaps with a single-episode result for ep #" + str( + epNum) + ", removing the single-episode results from the list", logger.DEBUG) del foundResults[provider.name][epNum] - finalResults += set(multiResults.values()) - # of all the single ep results narrow it down to the best one for each episode + queueItem.results += set(multiResults.values()) for curEp in foundResults[provider.name]: if curEp in (MULTI_EP_RESULT, SEASON_RESULT): continue @@ -514,30 +523,34 @@ def searchProviders(queueItem, show, season, episodes, seasonSearch=False, manua if len(foundResults[provider.name][curEp]) == 0: continue - result = pickBestResult(foundResults[provider.name][curEp], show) - finalResults.append(result) + bestResult = pickBestResult(foundResults[provider.name][curEp], show) - logger.log(u"Checking if we should snatch " + result.name, logger.DEBUG) - any_qualities, best_qualities = Quality.splitQuality(show.quality) + # if all results were rejected move on to the next episode + if not bestResult: + continue - # if there is a redownload that's higher than this then we definitely need to keep looking - if best_qualities and result.quality == max(best_qualities): - logger.log(u"Found a highest quality archive match to snatch [" + result.name + "]", logger.DEBUG) - queueItem.results = [result] - return queueItem + # add result if its not a duplicate and + if isFinalResult(bestResult): + found = False + for i, result in enumerate(queueItem.results): + for bestResultEp in bestResult.episodes: + if bestResultEp in result.episodes: + if result.quality < bestResult.quality: + queueItem.results.pop(i) + else: + found = True + if not found: + queueItem.results += [bestResult] - # if there's no redownload that's higher (above) and this is the highest initial download then we're good - elif any_qualities and result.quality in any_qualities: - logger.log(u"Found a initial quality match to snatch [" + result.name + "]", logger.DEBUG) - queueItem.results = [result] - return queueItem + # check that we got all the episodes we wanted first before doing a match and snatch + wantedEpCount = 0 + for wantedEp in episodes: + for result in queueItem.results: + if wantedEp in result.episodes: + wantedEpCount += 1 - # remove duplicates and insures snatch of highest quality from results - for i1, result1 in enumerate(finalResults): - for i2, result2 in enumerate(finalResults): - if result2.provider.show == show and result2.episodes.sort() == episodes.sort() and len(finalResults) > 1: - if result1.quality >= result2.quality: - finalResults.pop(i2) + # make sure we search every provider for results unless we found everything we wanted + if providerNum != len(providers) and wantedEpCount != len(episodes): + continue - queueItem.results = finalResults return queueItem diff --git a/sickbeard/search_queue.py b/sickbeard/search_queue.py index f7431f57..9f14a5e9 100644 --- a/sickbeard/search_queue.py +++ b/sickbeard/search_queue.py @@ -90,7 +90,6 @@ class SearchQueue(generic_queue.GenericQueue): status = search.snatchEpisode(result) item.success = status generic_queue.QueueItem.finish(item) - return status class ManualSearchQueueItem(generic_queue.QueueItem): def __init__(self, ep_obj): @@ -100,6 +99,7 @@ class ManualSearchQueueItem(generic_queue.QueueItem): self.success = None self.show = ep_obj.show self.ep_obj = ep_obj + self.results = [] def execute(self): generic_queue.QueueItem.execute(self) @@ -109,25 +109,18 @@ class ManualSearchQueueItem(generic_queue.QueueItem): searchResult = search.searchProviders(self, self.show, self.ep_obj.season, [self.ep_obj],False,True) if searchResult: - self.success = SearchQueue().snatch_item(searchResult) + SearchQueue().snatch_item(searchResult) + else: + ui.notifications.message('No downloads were found', + "Couldn't find a download for %s" % self.ep_obj.prettyName()) + + logger.log(u"Unable to find a download for " + self.ep_obj.prettyName()) except Exception: logger.log(traceback.format_exc(), logger.DEBUG) - if not self.success: - ui.notifications.message('No downloads were found', - "Couldn't find a download for %s" % self.ep_obj.prettyName()) - logger.log(u"Unable to find a download for " + self.ep_obj.prettyName()) - self.finish() - def finish(self): - # don't let this linger if something goes wrong - if self.success == None: - self.success = False - generic_queue.QueueItem.finish(self) - - class BacklogQueueItem(generic_queue.QueueItem): def __init__(self, show, segment): generic_queue.QueueItem.__init__(self, 'Backlog', BACKLOG_SEARCH) @@ -137,6 +130,7 @@ class BacklogQueueItem(generic_queue.QueueItem): self.show = show self.segment = segment self.wantedEpisodes = [] + self.results = [] self._changeMissingEpisodes() @@ -174,21 +168,18 @@ class BacklogQueueItem(generic_queue.QueueItem): if len(seasonEps) == len(self.wantedEpisodes): seasonSearch = True - providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and x] - try: logger.log("Beginning backlog search for episodes from [" + self.show.name + "] - Season[" + str(self.segment) + "]") searchResult = search.searchProviders(self, self.show, self.segment, self.wantedEpisodes, seasonSearch, False) if searchResult: - self.success = SearchQueue().snatch_item(searchResult) + SearchQueue().snatch_item(searchResult) + else: + logger.log(u"No needed episodes found during backlog search") except Exception: logger.log(traceback.format_exc(), logger.DEBUG) - if not self.success: - logger.log(u"No needed episodes found during backlog search") - self.finish() def _need_any_episodes(self, statusResults, bestQualities): @@ -253,32 +244,34 @@ class FailedQueueItem(generic_queue.QueueItem): self.show = show self.episodes = episodes self.success = None + self.results = [] def execute(self): generic_queue.QueueItem.execute(self) + failed_episodes = [] for i, epObj in enumerate(self.episodes): - (release, provider) = failed_history.findRelease(self.show, epObj.season, epObj.episode) + (release, provider) = failed_history.findRelease(epObj) if release: logger.log(u"Marking release as bad: " + release) - failed_history.markFailed(self.show, epObj.season, epObj.episode) + failed_history.markFailed(epObj) failed_history.logFailed(release) - history.logFailed(self.show.indexerid, epObj.season, epObj.episode, epObj.status, release, provider) + history.logFailed(epObj, release, provider) + failed_history.revertEpisode(epObj) + failed_episodes.append(epObj) - failed_history.revertEpisode(self.show, epObj.season, epObj.episode) + if len(failed_episodes): + try: + logger.log( + "Beginning failed download search for episodes from Season [" + str(self.episodes[0].season) + "]") - try: - logger.log( - "Beginning failed download search for episodes from Season [" + str(self.episodes[0].season) + "]") + searchResult = search.searchProviders(self, self.show, failed_episodes[0].season, failed_episodes, False, True) - searchResult = search.searchProviders(self, self.show, self.episodes[0].season, self.episodes, False, True) - if searchResult: - self.success = SearchQueue().snatch_item(searchResult) - - except Exception, e: - logger.log(traceback.format_exc(), logger.DEBUG) - - if not self.success: - logger.log(u"No needed episodes found on the RSS feeds") + if searchResult: + SearchQueue().snatch_item(searchResult) + else: + logger.log(u"No episodes found to retry for failed downloads return from providers!") + except Exception, e: + logger.log(traceback.format_exc(), logger.DEBUG) self.finish() \ No newline at end of file diff --git a/sickbeard/show_name_helpers.py b/sickbeard/show_name_helpers.py index c7d2be51..18ea3337 100644 --- a/sickbeard/show_name_helpers.py +++ b/sickbeard/show_name_helpers.py @@ -119,7 +119,10 @@ def makeSceneSeasonSearchString(show, ep_obj, extraSearchType=None): [show.indexerid]) numseasons = int(numseasonsSQlResult[0][0]) - seasonStrings = ["S%02d" % int(ep_obj.scene_season)] + if show.air_by_date or show.sports: + seasonStrings = [str(ep_obj.airdate)[:7]] + else: + seasonStrings = ["S%02d" % int(ep_obj.scene_season)] showNames = set(makeSceneShowSearchStrings(show)) diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py index 74ab73fb..143b8f72 100644 --- a/sickbeard/show_queue.py +++ b/sickbeard/show_queue.py @@ -144,9 +144,9 @@ class ShowQueue(generic_queue.GenericQueue): return queueItemObj def addShow(self, indexer, indexer_id, showDir, default_status=None, quality=None, flatten_folders=None, - subtitles=None, lang="en", refresh=False): + subtitles=None, lang="en"): queueItemObj = QueueItemAdd(indexer, indexer_id, showDir, default_status, quality, flatten_folders, lang, - subtitles, refresh) + subtitles) self.add_item(queueItemObj) @@ -203,8 +203,7 @@ class ShowQueueItem(generic_queue.QueueItem): class QueueItemAdd(ShowQueueItem): - def __init__(self, indexer, indexer_id, showDir, default_status, quality, flatten_folders, lang, subtitles, - refresh): + def __init__(self, indexer, indexer_id, showDir, default_status, quality, flatten_folders, lang, subtitles): self.indexer = indexer self.indexer_id = indexer_id @@ -214,7 +213,6 @@ class QueueItemAdd(ShowQueueItem): self.flatten_folders = flatten_folders self.lang = lang self.subtitles = subtitles - self.refresh = refresh self.show = None @@ -380,7 +378,8 @@ class QueueItemAdd(ShowQueueItem): logger.log(u"Launching backlog for this show since its episodes are WANTED") sickbeard.backlogSearchScheduler.action.searchBacklog([self.show]) #@UndefinedVariable - self.show.writeMetadata(force=self.refresh) + self.show.writeMetadata() + self.show.updateMetadata() self.show.populateCache() self.show.flushEpisodes() @@ -410,7 +409,8 @@ class QueueItemRefresh(ShowQueueItem): logger.log(u"Performing refresh on " + self.show.name) self.show.refreshDir() - self.show.writeMetadata(force=True) + self.show.writeMetadata() + self.show.updateMetadata() self.show.populateCache() self.inProgress = False diff --git a/sickbeard/tv.py b/sickbeard/tv.py index faae6e43..d436672d 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -205,7 +205,9 @@ class TVShow(object): if ep != None: self.episodes[season][episode] = ep - return self.episodes[season][episode] + epObj = self.episodes[season][episode] + epObj.convertToSceneNumbering() + return epObj def should_update(self, update_date=datetime.date.today()): @@ -251,7 +253,7 @@ class TVShow(object): return False - def writeShowNFO(self, force=False): + def writeShowNFO(self): result = False @@ -261,11 +263,11 @@ class TVShow(object): logger.log(str(self.indexerid) + u": Writing NFOs for show") for cur_provider in sickbeard.metadata_provider_dict.values(): - result = cur_provider.create_show_metadata(self, force) or result + result = cur_provider.create_show_metadata(self) or result return result - def writeMetadata(self, show_only=False, force=False): + def writeMetadata(self, show_only=False): if not ek.ek(os.path.isdir, self._location): logger.log(str(self.indexerid) + u": Show dir doesn't exist, skipping NFO generation") @@ -273,12 +275,12 @@ class TVShow(object): self.getImages() - self.writeShowNFO(force) + self.writeShowNFO() if not show_only: - self.writeEpisodeNFOs(force) + self.writeEpisodeNFOs() - def writeEpisodeNFOs(self, force=False): + def writeEpisodeNFOs(self): if not ek.ek(os.path.isdir, self._location): logger.log(str(self.indexerid) + u": Show dir doesn't exist, skipping NFO generation") @@ -293,9 +295,31 @@ class TVShow(object): logger.log(str(self.indexerid) + u": Retrieving/creating episode " + str(epResult["season"]) + "x" + str( epResult["episode"]), logger.DEBUG) curEp = self.getEpisode(epResult["season"], epResult["episode"]) - curEp.createMetaFiles(force) + curEp.createMetaFiles() + def updateMetadata(self): + + if not ek.ek(os.path.isdir, self._location): + logger.log(str(self.indexerid) + u": Show dir doesn't exist, skipping NFO generation") + return + + self.updateShowNFO() + + def updateShowNFO(self): + + result = False + + if not ek.ek(os.path.isdir, self._location): + logger.log(str(self.indexerid) + u": Show dir doesn't exist, skipping NFO generation") + return False + + logger.log(str(self.indexerid) + u": Updating NFOs for show with new indexer info") + for cur_provider in sickbeard.metadata_provider_dict.values(): + result = cur_provider.update_show_indexer_metadata(self) or result + + return result + # find all media files in the show folder and create episodes for as many as possible def loadEpisodesFromDir(self): @@ -1158,8 +1182,6 @@ class TVEpisode(object): self.specifyEpisode(self.season, self.episode) - self.convertToSceneNumbering() - self.relatedEps = [] self.checkForMetaFiles() @@ -1610,28 +1632,28 @@ class TVEpisode(object): toReturn += "status: " + str(self.status) + "\n" return toReturn - def createMetaFiles(self, force=False): + def createMetaFiles(self): if not ek.ek(os.path.isdir, self.show._location): logger.log(str(self.show.indexerid) + u": The show dir is missing, not bothering to try to create metadata") return - self.createNFO(force) + self.createNFO() self.createThumbnail() if self.checkForMetaFiles(): self.saveToDB() - def createNFO(self, force=False): + def createNFO(self): result = False for cur_provider in sickbeard.metadata_provider_dict.values(): - result = cur_provider.create_episode_metadata(self, force) or result + result = cur_provider.create_episode_metadata(self) or result return result - def createThumbnail(self, force=False): + def createThumbnail(self): result = False @@ -1904,6 +1926,9 @@ class TVEpisode(object): result_name = result_name.replace('%rg', 'sickbeard') logger.log(u"Episode has no release name, replacing it with a generic one: " + result_name, logger.DEBUG) + if not replace_map['%RT']: + result_name = re.sub('([ _.-]*)%RT([ _.-]*)', r'\2', result_name) + # split off ep name part only name_groups = re.split(r'[\\/]', result_name) @@ -2138,4 +2163,4 @@ class TVEpisode(object): (self.season, self.episode) = sickbeard.scene_numbering.get_indexer_numbering(self.show.indexerid, self.show.indexer, self.scene_season, - self.scene_episode) \ No newline at end of file + self.scene_episode) diff --git a/sickbeard/tvcache.py b/sickbeard/tvcache.py index f59d03ff..6f90739f 100644 --- a/sickbeard/tvcache.py +++ b/sickbeard/tvcache.py @@ -232,7 +232,7 @@ class TVCache(): # if we don't have complete info then parse the filename to get it try: myParser = NameParser() - parse_result = myParser.parse(name) + parse_result = myParser.parse(name).convert() except InvalidNameException: logger.log(u"Unable to parse the filename " + name + " into a valid episode", logger.DEBUG) return None @@ -255,13 +255,6 @@ class TVCache(): if showResult: indexerid = int(showResult[0]) - # if not indexerid: - # for curShow in sickbeard.showList: - # if curShow.name == parse_result.series_name: - # if show_name_helpers.isGoodResult(name, curShow, False): - # indexerid = int(curShow.indexerid) - # break - showObj = None if indexerid: showObj = helpers.findCertainShow(sickbeard.showList, indexerid) @@ -327,14 +320,14 @@ class TVCache(): def findNeededEpisodes(self, epObj=None, manualSearch=False): neededEps = {} - myDB = self._getDB() + cacheDB = self._getDB() if not epObj: - sqlResults = myDB.select("SELECT * FROM [" + self.providerID + "]") + sqlResults = cacheDB.select("SELECT * FROM [" + self.providerID + "]") else: - sqlResults = myDB.select( + sqlResults = cacheDB.select( "SELECT * FROM [" + self.providerID + "] WHERE indexerid = ? AND season = ? AND episodes LIKE ?", - [epObj.show.indexerid, epObj.scene_season, "%|" + str(epObj.scene_episode) + "|%"]) + [epObj.show.indexerid, epObj.season, "%|" + str(epObj.episode) + "|%"]) # for each cache entry for curResult in sqlResults: @@ -386,9 +379,9 @@ class TVCache(): # add it to the list if epObj not in neededEps: - neededEps[epObj] = [result] + neededEps[epObj.episode] = [result] else: - neededEps[epObj].append(result) + neededEps[epObj.episode].append(result) return neededEps diff --git a/sickbeard/versionChecker.py b/sickbeard/versionChecker.py index 59ce3397..8dda1a50 100644 --- a/sickbeard/versionChecker.py +++ b/sickbeard/versionChecker.py @@ -27,6 +27,7 @@ import tarfile import stat import traceback import gh_api as github +import threading import sickbeard from sickbeard import helpers @@ -57,23 +58,27 @@ class CheckVersion(): self.updater = None def run(self): + updated = None if self.check_for_new_version(): if sickbeard.AUTO_UPDATE: logger.log(u"New update found for SickRage, starting auto-updater ...") updated = sickbeard.versionCheckScheduler.action.update() if updated: logger.log(u"Update was successfull, restarting SickRage ...") - sickbeard.restart(False) - # refresh scene exceptions too - scene_exceptions.retrieve_exceptions() + # do a soft restart + threading.Timer(2, sickbeard.invoke_restart, [False]).start() - # refresh network timezones - network_timezones.update_network_dict() + if not updated: + # refresh scene exceptions too + scene_exceptions.retrieve_exceptions() - # sure, why not? - if sickbeard.USE_FAILED_DOWNLOADS: - failed_history.trimHistory() + # refresh network timezones + network_timezones.update_network_dict() + + # sure, why not? + if sickbeard.USE_FAILED_DOWNLOADS: + failed_history.trimHistory() def find_install_type(self): """ diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 5ce75cdb..4335630e 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -1565,16 +1565,16 @@ class ConfigProviders: else: logger.log(u"don't know what " + curProvider + " is, skipping") - sickbeard.EZRSS_RATIO = config.to_int(ezrss_ratio) + sickbeard.EZRSS_RATIO = ezrss_ratio sickbeard.TVTORRENTS_DIGEST = tvtorrents_digest.strip() sickbeard.TVTORRENTS_HASH = tvtorrents_hash.strip() sickbeard.TVTORRENTS_RATIO = config.to_int(tvtorrents_ratio) sickbeard.BTN_API_KEY = btn_api_key.strip() - sickbeard.BTN_RATIO = config.to_int(btn_ratio) + sickbeard.BTN_RATIO = btn_ratio - sickbeard.THEPIRATEBAY_RATIO = config.to_int(thepiratebay_ratio) + sickbeard.THEPIRATEBAY_RATIO = thepiratebay_ratio sickbeard.THEPIRATEBAY_TRUSTED = config.checkbox_to_value(thepiratebay_trusted) thepiratebay_proxy = config.checkbox_to_value(thepiratebay_proxy) @@ -1587,48 +1587,48 @@ class ConfigProviders: sickbeard.TORRENTLEECH_USERNAME = torrentleech_username sickbeard.TORRENTLEECH_PASSWORD = torrentleech_password - sickbeard.TORRENTLEECH_RATIO = config.to_int(torrentleech_ratio) + sickbeard.TORRENTLEECH_RATIO = torrentleech_ratio sickbeard.IPTORRENTS_USERNAME = iptorrents_username.strip() sickbeard.IPTORRENTS_PASSWORD = iptorrents_password.strip() - sickbeard.IPTORRENTS_RATIO = config.to_int(iptorrents_ratio) + sickbeard.IPTORRENTS_RATIO = iptorrents_ratio sickbeard.IPTORRENTS_FREELEECH = config.checkbox_to_value(iptorrents_freeleech) sickbeard.KAT_TRUSTED = config.checkbox_to_value(kat_trusted) - sickbeard.KAT_RATIO = config.to_int(kat_ratio) + sickbeard.KAT_RATIO = kat_ratio sickbeard.KAT_VERIFIED = config.checkbox_to_value(kat_verified) sickbeard.PUBLICHD_RATIO = publichd_ratio sickbeard.TORRENTDAY_USERNAME = torrentday_username.strip() sickbeard.TORRENTDAY_PASSWORD = torrentday_password.strip() - sickbeard.TORRENTDAY_RATIO = config.to_int(torrentday_ratio) + sickbeard.TORRENTDAY_RATIO = torrentday_ratio sickbeard.TORRENTDAY_FREELEECH = config.checkbox_to_value(torrentday_freeleech) sickbeard.SCC_USERNAME = scc_username.strip() sickbeard.SCC_PASSWORD = scc_password.strip() - sickbeard.SCC_RATIO = config.to_int(scc_ratio) + sickbeard.SCC_RATIO = scc_ratio sickbeard.HDTORRENTS_USERNAME = hdtorrents_username.strip() sickbeard.HDTORRENTS_PASSWORD = hdtorrents_password.strip() - sickbeard.HDTORRENTS_RATIO = config.to_int(hdtorrents_ratio) + sickbeard.HDTORRENTS_RATIO = hdtorrents_ratio sickbeard.HDBITS_USERNAME = hdbits_username.strip() sickbeard.HDBITS_PASSKEY = hdbits_passkey.strip() - sickbeard.HDBITS_RATIO = config.to_int(hdbits_ratio) + sickbeard.HDBITS_RATIO = hdbits_ratio sickbeard.OMGWTFNZBS_USERNAME = omgwtfnzbs_username.strip() sickbeard.OMGWTFNZBS_APIKEY = omgwtfnzbs_apikey.strip() sickbeard.NEXTGEN_USERNAME = nextgen_username.strip() sickbeard.NEXTGEN_PASSWORD = nextgen_password.strip() - sickbeard.NEXTGEN_RATIO = config.to_int(nextgen_ratio) + sickbeard.NEXTGEN_RATIO = nextgen_ratio sickbeard.SPEEDCD_USERNAME = speedcd_username.strip() sickbeard.SPEEDCD_PASSWORD = speedcd_password.strip() - sickbeard.SPEEDCD_RATIO = config.to_int(speedcd_ratio) + sickbeard.SPEEDCD_RATIO = speedcd_ratio sickbeard.SPEEDCD_FREELEECH = config.checkbox_to_value(speedcd_freeleech) sickbeard.NEWZNAB_DATA = '!!!'.join([x.configStr() for x in sickbeard.newznabProviderList]) @@ -2350,7 +2350,7 @@ class NewHomeAddShows: sickbeard.STATUS_DEFAULT, sickbeard.QUALITY_DEFAULT, sickbeard.FLATTEN_FOLDERS_DEFAULT, - sickbeard.SUBTITLES_DEFAULT, refresh=True) + sickbeard.SUBTITLES_DEFAULT) num_added += 1 if num_added:
SR Version: BRANCH: ($sickbeard.version.SICKBEARD_VERSION) / COMMIT: ($sickbeard.CUR_COMMIT_HASH)
+
SR Version: +#if $sickbeard.VERSION_NOTIFY + BRANCH: ($sickbeard.version.SICKBEARD_VERSION) / COMMIT: ($sickbeard.CUR_COMMIT_HASH)
+#else + You don't have version checking turned on. Please turn on "Check for Update" in Config > General.
+#end if You are using BETA software
SR Config file: $sickbeard.CONFIG_FILE