diff --git a/SickBeard.py b/SickBeard.py
index a5c476fd..64876036 100755
--- a/SickBeard.py
+++ b/SickBeard.py
@@ -19,10 +19,11 @@
# Check needed software dependencies to nudge users to fix their setup
from __future__ import with_statement
-import functools
+import time
import sys
import shutil
+import subprocess
if sys.version_info < (2, 6):
print "Sorry, requires Python 2.6 or 2.7."
@@ -60,368 +61,356 @@ import sickbeard
from sickbeard import db
from sickbeard.tv import TVShow
from sickbeard import logger
-from sickbeard import webserveInit
+from sickbeard.webserveInit import SRWebServer
from sickbeard.version import SICKBEARD_VERSION
from sickbeard.databases.mainDB import MIN_DB_VERSION
from sickbeard.databases.mainDB import MAX_DB_VERSION
from lib.configobj import ConfigObj
-
-from tornado.ioloop import IOLoop
+from daemon import Daemon
signal.signal(signal.SIGINT, sickbeard.sig_handler)
signal.signal(signal.SIGTERM, sickbeard.sig_handler)
throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
-def loadShowsFromDB():
- """
- Populates the showList with shows from the database
- """
+class SickRage(object):
- logger.log(u"Loading initial show list")
+ def loadShowsFromDB(self):
+ """
+ Populates the showList with shows from the database
+ """
- myDB = db.DBConnection()
- sqlResults = myDB.select("SELECT * FROM tv_shows")
+ logger.log(u"Loading initial show list")
- sickbeard.showList = []
- for sqlShow in sqlResults:
- try:
- curShow = TVShow(int(sqlShow["indexer"]), int(sqlShow["indexer_id"]))
- sickbeard.showList.append(curShow)
- except Exception, e:
- logger.log(
+ myDB = db.DBConnection()
+ sqlResults = myDB.select("SELECT * FROM tv_shows")
+
+ sickbeard.showList = []
+ for sqlShow in sqlResults:
+ try:
+ curShow = TVShow(int(sqlShow["indexer"]), int(sqlShow["indexer_id"]))
+ sickbeard.showList.append(curShow)
+ except Exception, e:
+ logger.log(
u"There was an error creating the show in " + sqlShow["location"] + ": " + str(e).decode('utf-8'),
- logger.ERROR)
- logger.log(traceback.format_exc(), logger.DEBUG)
+ logger.ERROR)
+ logger.log(traceback.format_exc(), logger.DEBUG)
- # TODO: update the existing shows if the showlist has something in it
-
-def daemonize():
- try:
- pid = os.fork()
- if pid > 0:
- sys.exit(0)
- except OSError:
- print "fork() failed"
- sys.exit(1)
-
- os.chdir(sickbeard.PROG_DIR)
- os.setsid()
- # Make sure I can read my own files and shut out others
- prev= os.umask(0)
- os.umask(prev and int('077',8))
-
- try:
- pid = os.fork()
- if pid > 0:
- sys.exit(0)
- except OSError:
- print "fork() failed"
- sys.exit(1)
-
- # Write pid
- if sickbeard.CREATEPID:
- pid = str(os.getpid())
- logger.log(u"Writing PID: " + pid + " to " + str(sickbeard.PIDFILE))
+ def restore(self, srcDir, dstDir):
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) + "]")
+ for file in os.listdir(srcDir):
+ srcFile = os.path.join(srcDir, file)
+ dstFile = os.path.join(dstDir, file)
+ bakFile = os.path.join(dstDir, file + '.bak')
+ shutil.move(dstFile, bakFile)
+ shutil.move(srcFile, dstFile)
- dev_null = file('/dev/null', 'r')
- os.dup2(dev_null.fileno(), sys.stdin.fileno())
+ os.rmdir(srcDir)
+ return True
+ except:
+ return False
-def restore(srcDir, dstDir):
- try:
- for file in os.listdir(srcDir):
- srcFile = os.path.join(srcDir, file)
- dstFile = os.path.join(dstDir, file)
- bakFile = os.path.join(dstDir, file + '.bak')
- shutil.move(dstFile, bakFile)
- shutil.move(srcFile, dstFile)
+ def __init__(self):
+ self.daemon = None
+ self.webserver = None
+ self.runAsDaemon = False
+ self.CREATEPID = False
+ self.PIDFILE = None
+ self.forceUpdate = False
+ self.forcedPort = None
+ self.noLaunch = False
- os.rmdir(srcDir)
- return True
- except:
- return False
+ def start(self):
+ # do some preliminary stuff
+ sickbeard.MY_FULLNAME = os.path.normpath(os.path.abspath(__file__))
+ sickbeard.MY_NAME = os.path.basename(sickbeard.MY_FULLNAME)
+ sickbeard.PROG_DIR = os.path.dirname(sickbeard.MY_FULLNAME)
+ sickbeard.DATA_DIR = sickbeard.PROG_DIR
+ sickbeard.MY_ARGS = sys.argv[1:]
+ sickbeard.SYS_ENCODING = None
-def main():
- """
- TV for me
- """
-
- # do some preliminary stuff
- sickbeard.MY_FULLNAME = os.path.normpath(os.path.abspath(__file__))
- sickbeard.MY_NAME = os.path.basename(sickbeard.MY_FULLNAME)
- sickbeard.PROG_DIR = os.path.dirname(sickbeard.MY_FULLNAME)
- sickbeard.DATA_DIR = sickbeard.PROG_DIR
- sickbeard.MY_ARGS = sys.argv[1:]
- sickbeard.DAEMON = False
- sickbeard.CREATEPID = False
-
- sickbeard.SYS_ENCODING = None
-
- try:
- locale.setlocale(locale.LC_ALL, "")
- sickbeard.SYS_ENCODING = locale.getpreferredencoding()
- except (locale.Error, IOError):
- pass
-
- # For OSes that are poorly configured I'll just randomly force UTF-8
- if not sickbeard.SYS_ENCODING or sickbeard.SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'):
- sickbeard.SYS_ENCODING = 'UTF-8'
-
- if not hasattr(sys, "setdefaultencoding"):
- reload(sys)
-
- try:
- # pylint: disable=E1101
- # 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 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)
-
- # Need console logging for SickBeard.py and SickBeard-console.exe
- consoleLogging = (not hasattr(sys, "frozen")) or (sickbeard.MY_NAME.lower().find('-console') > 0)
-
- # Rename the main thread
- threading.currentThread().name = "MAIN"
-
- try:
- opts, args = getopt.getopt(sys.argv[1:], "qfdp::",
- ['quiet', 'forceupdate', 'daemon', 'port=', 'pidfile=', 'nolaunch', 'config=',
- 'datadir=']) # @UnusedVariable
- except getopt.GetoptError:
- print "Available Options: --quiet, --forceupdate, --port, --daemon, --pidfile, --config, --datadir"
- sys.exit()
-
- forceUpdate = False
- forcedPort = None
- noLaunch = False
-
- for o, a in opts:
- # For now we'll just silence the logging
- if o in ('-q', '--quiet'):
- consoleLogging = False
-
- # Should we update (from indexer) all shows in the DB right away?
- if o in ('-f', '--forceupdate'):
- forceUpdate = True
-
- # Suppress launching web browser
- # Needed for OSes without default browser assigned
- # Prevent duplicate browser window when restarting in the app
- if o in ('--nolaunch',):
- noLaunch = True
-
- # Override default/configured port
- if o in ('-p', '--port'):
- forcedPort = int(a)
-
- # 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':
- sickbeard.DAEMON = False
-
- # Specify folder to load the config file from
- if o in ('--config',):
- sickbeard.CONFIG_FILE = os.path.abspath(a)
-
- # Specify folder to use as the data dir
- if o in ('--datadir',):
- sickbeard.DATA_DIR = os.path.abspath(a)
-
- # Prevent resizing of the banner/posters even if PIL is installed
- if o in ('--noresize',):
- sickbeard.NO_RESIZE = True
-
- # 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.")
-
- # The pidfile is only useful in daemon mode, make sure we can write the file properly
- if sickbeard.CREATEPID and not sickbeard.restarted:
- 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:
- sickbeard.CONFIG_FILE = os.path.join(sickbeard.DATA_DIR, "config.ini")
-
- # Make sure that we can create the data dir
- if not os.access(sickbeard.DATA_DIR, os.F_OK):
try:
- os.makedirs(sickbeard.DATA_DIR, 0744)
- except os.error, e:
- raise SystemExit("Unable to create datadir '" + sickbeard.DATA_DIR + "'")
+ locale.setlocale(locale.LC_ALL, "")
+ sickbeard.SYS_ENCODING = locale.getpreferredencoding()
+ except (locale.Error, IOError):
+ pass
- # Make sure we can write to the data dir
- if not os.access(sickbeard.DATA_DIR, os.W_OK):
- raise SystemExit("Datadir must be writeable '" + sickbeard.DATA_DIR + "'")
+ # For OSes that are poorly configured I'll just randomly force UTF-8
+ if not sickbeard.SYS_ENCODING or sickbeard.SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'):
+ sickbeard.SYS_ENCODING = 'UTF-8'
- # Make sure we can write to the config file
- if not os.access(sickbeard.CONFIG_FILE, os.W_OK):
- if os.path.isfile(sickbeard.CONFIG_FILE):
- raise SystemExit("Config file '" + sickbeard.CONFIG_FILE + "' must be writeable.")
- elif not os.access(os.path.dirname(sickbeard.CONFIG_FILE), os.W_OK):
- raise SystemExit("Config file root dir '" + os.path.dirname(sickbeard.CONFIG_FILE) + "' must be writeable.")
+ if not hasattr(sys, "setdefaultencoding"):
+ reload(sys)
- # Check if we need to perform a restore first
- restoreDir = os.path.join(sickbeard.DATA_DIR, 'restore')
- if os.path.exists(restoreDir):
- if restore(restoreDir, sickbeard.DATA_DIR):
- logger.log(u"Restore successful...")
+ try:
+ # pylint: disable=E1101
+ # 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 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)
+
+ # Need console logging for SickBeard.py and SickBeard-console.exe
+ self.consoleLogging = (not hasattr(sys, "frozen")) or (sickbeard.MY_NAME.lower().find('-console') > 0)
+
+ # Rename the main thread
+ threading.currentThread().name = "MAIN"
+
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "qfdp::",
+ ['quiet', 'forceupdate', 'daemon', 'port=', 'pidfile=', 'nolaunch', 'config=',
+ 'datadir=']) # @UnusedVariable
+ except getopt.GetoptError:
+ print "Available Options: --quiet, --forceupdate, --port, --daemon, --pidfile, --config, --datadir"
+ sys.exit()
+
+ for o, a in opts:
+ # For now we'll just silence the logging
+ if o in ('-q', '--quiet'):
+ self.consoleLogging = False
+
+ # Should we update (from indexer) all shows in the DB right away?
+ if o in ('-f', '--forceupdate'):
+ self.forceUpdate = True
+
+ # Suppress launching web browser
+ # Needed for OSes without default browser assigned
+ # Prevent duplicate browser window when restarting in the app
+ if o in ('--nolaunch',):
+ self.noLaunch = True
+
+ # Override default/configured port
+ if o in ('-p', '--port'):
+ self.forcedPort = int(a)
+
+ # Run as a double forked daemon
+ if o in ('-d', '--daemon'):
+ self.runAsDaemon = True
+ # When running as daemon disable consoleLogging and don't start browser
+ self.consoleLogging = False
+ self.noLaunch = True
+
+ if sys.platform == 'win32':
+ self.runAsDaemon = False
+
+ # Specify folder to load the config file from
+ if o in ('--config',):
+ sickbeard.CONFIG_FILE = os.path.abspath(a)
+
+ # Specify folder to use as the data dir
+ if o in ('--datadir',):
+ sickbeard.DATA_DIR = os.path.abspath(a)
+
+ # Prevent resizing of the banner/posters even if PIL is installed
+ if o in ('--noresize',):
+ sickbeard.NO_RESIZE = True
+
+ # Write a pidfile if requested
+ if o in ('--pidfile',):
+ self.CREATEPID = True
+ self.PIDFILE = str(a)
+
+ # If the pidfile already exists, sickbeard may still be running, so exit
+ if os.path.exists(self.PIDFILE):
+ sys.exit("PID file: " + self.PIDFILE + " already exists. Exiting.")
+
+ # The pidfile is only useful in daemon mode, make sure we can write the file properly
+ if self.CREATEPID:
+ if self.runAsDaemon:
+ pid_dir = os.path.dirname(self.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 self.consoleLogging:
+ sys.stdout.write("Not running in daemon mode. PID file creation disabled.\n")
+
+ self.CREATEPID = False
+
+ # If they don't specify a config file then put it in the data dir
+ if not sickbeard.CONFIG_FILE:
+ sickbeard.CONFIG_FILE = os.path.join(sickbeard.DATA_DIR, "config.ini")
+
+ # Make sure that we can create the data dir
+ if not os.access(sickbeard.DATA_DIR, os.F_OK):
+ try:
+ os.makedirs(sickbeard.DATA_DIR, 0744)
+ except os.error, e:
+ raise SystemExit("Unable to create datadir '" + sickbeard.DATA_DIR + "'")
+
+ # Make sure we can write to the data dir
+ if not os.access(sickbeard.DATA_DIR, os.W_OK):
+ raise SystemExit("Datadir must be writeable '" + sickbeard.DATA_DIR + "'")
+
+ # Make sure we can write to the config file
+ if not os.access(sickbeard.CONFIG_FILE, os.W_OK):
+ if os.path.isfile(sickbeard.CONFIG_FILE):
+ raise SystemExit("Config file '" + sickbeard.CONFIG_FILE + "' must be writeable.")
+ elif not os.access(os.path.dirname(sickbeard.CONFIG_FILE), os.W_OK):
+ raise SystemExit(
+ "Config file root dir '" + os.path.dirname(sickbeard.CONFIG_FILE) + "' must be writeable.")
+
+ # Check if we need to perform a restore first
+ restoreDir = os.path.join(sickbeard.DATA_DIR, 'restore')
+ if os.path.exists(restoreDir):
+ if self.restore(restoreDir, sickbeard.DATA_DIR):
+ logger.log(u"Restore successful...")
+ else:
+ logger.log(u"Restore FAILED!", logger.ERROR)
+
+ os.chdir(sickbeard.DATA_DIR)
+
+ # Load the config and publish it to the sickbeard package
+ if not os.path.isfile(sickbeard.CONFIG_FILE):
+ logger.log(u"Unable to find '" + sickbeard.CONFIG_FILE + "' , all settings will be default!", logger.ERROR)
+
+ sickbeard.CFG = ConfigObj(sickbeard.CONFIG_FILE)
+
+ CUR_DB_VERSION = db.DBConnection().checkDBVersion()
+
+ if CUR_DB_VERSION > 0:
+ if CUR_DB_VERSION < MIN_DB_VERSION:
+ raise SystemExit("Your database version (" + str(
+ CUR_DB_VERSION) + ") 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(
+ CUR_DB_VERSION) + ") 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
+ sickbeard.initialize(consoleLogging=self.consoleLogging)
+
+ if self.runAsDaemon:
+ self.daemon = Daemon(self.PIDFILE or os.path.join(sickbeard.DATA_DIR, 'sickbeard.pid'))
+ self.daemon.daemonize()
+
+ # Get PID
+ sickbeard.PID = os.getpid()
+
+ if self.forcedPort:
+ logger.log(u"Forcing web server to port " + str(self.forcedPort))
+ self.startPort = self.forcedPort
else:
- logger.log(u"Restore FAILED!", logger.ERROR)
+ self.startPort = sickbeard.WEB_PORT
- os.chdir(sickbeard.DATA_DIR)
-
- if consoleLogging:
- 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):
- logger.log(u"Unable to find '" + sickbeard.CONFIG_FILE + "' , all settings will be default!", logger.ERROR)
-
- sickbeard.CFG = ConfigObj(sickbeard.CONFIG_FILE)
-
- CUR_DB_VERSION = db.DBConnection().checkDBVersion()
-
- if CUR_DB_VERSION > 0:
- if CUR_DB_VERSION < MIN_DB_VERSION:
- raise SystemExit("Your database version (" + str(
- CUR_DB_VERSION) + ") 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(
- CUR_DB_VERSION) + ") 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
- sickbeard.initialize(consoleLogging=consoleLogging)
-
- if sickbeard.DAEMON:
- daemonize()
-
- # Use this PID for everything
- sickbeard.PID = os.getpid()
-
- if forcedPort:
- logger.log(u"Forcing web server to port " + str(forcedPort))
- startPort = forcedPort
- else:
- startPort = sickbeard.WEB_PORT
-
- if sickbeard.WEB_LOG:
- log_dir = sickbeard.LOG_DIR
- else:
- log_dir = None
-
- # sickbeard.WEB_HOST is available as a configuration value in various
- # places but is not configurable. It is supported here for historic reasons.
- if sickbeard.WEB_HOST and sickbeard.WEB_HOST != '0.0.0.0':
- webhost = sickbeard.WEB_HOST
- else:
- if sickbeard.WEB_IPV6:
- webhost = '::'
+ if sickbeard.WEB_LOG:
+ self.log_dir = sickbeard.LOG_DIR
else:
- webhost = '0.0.0.0'
+ self.log_dir = None
- options = {
- 'port': int(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,
+ # sickbeard.WEB_HOST is available as a configuration value in various
+ # places but is not configurable. It is supported here for historic reasons.
+ if sickbeard.WEB_HOST and sickbeard.WEB_HOST != '0.0.0.0':
+ self.webhost = sickbeard.WEB_HOST
+ else:
+ if sickbeard.WEB_IPV6:
+ self.webhost = '::'
+ else:
+ self.webhost = '0.0.0.0'
+
+ # web server options
+ self.web_options = {
+ 'port': int(self.startPort),
+ 'host': self.webhost,
+ 'data_root': os.path.join(sickbeard.PROG_DIR, 'gui', sickbeard.GUI_NAME),
+ 'web_root': sickbeard.WEB_ROOT,
+ 'log_dir': self.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,
}
- # init tornado
- try:
- webserveInit.initWebServer(options)
- 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:
- logger.log(u"Launching browser and exiting", logger.ERROR)
- sickbeard.launchBrowser(startPort)
- sys.exit()
+ # start web server
+ try:
+ self.webserver = SRWebServer(self.web_options)
+ self.webserver.start()
+ except IOError:
+ logger.log(u"Unable to start web server, is something else running on port %d?" % self.startPort,
+ logger.ERROR)
+ if sickbeard.LAUNCH_BROWSER and not self.runAsDaemon:
+ logger.log(u"Launching browser and exiting", logger.ERROR)
+ sickbeard.launchBrowser(self.startPort)
+ os._exit(1)
- # Build from the DB to start with
- loadShowsFromDB()
+ if self.consoleLogging:
+ print "Starting up SickRage " + SICKBEARD_VERSION + " from " + sickbeard.CONFIG_FILE
- # Fire up all our threads
- sickbeard.start()
+ # Build from the DB to start with
+ self.loadShowsFromDB()
- # Launch browser if we're supposed to
- if sickbeard.LAUNCH_BROWSER and not noLaunch:
- sickbeard.launchBrowser(startPort)
+ # Fire up all our threads
+ sickbeard.start()
- # Start an update if we're supposed to
- if forceUpdate or sickbeard.UPDATE_SHOWS_ON_START:
- sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable
+ # Start an update if we're supposed to
+ if self.forceUpdate or sickbeard.UPDATE_SHOWS_ON_START:
+ sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable
- # If we restarted then unset the restarted flag
- if sickbeard.restarted:
- sickbeard.restarted = False
+ if sickbeard.LAUNCH_BROWSER and not (self.noLaunch or self.runAsDaemon):
+ sickbeard.launchBrowser(self.startPort)
- # IOLoop
- io_loop = IOLoop.current()
-
- # Open browser window
- if sickbeard.LAUNCH_BROWSER and not (noLaunch or sickbeard.DAEMON or sickbeard.restarted):
- io_loop.add_timeout(datetime.timedelta(seconds=5), functools.partial(sickbeard.launchBrowser, startPort))
-
- # Start web server
- io_loop.start()
-
- # Save and restart/shutdown
- sickbeard.saveAndShutdown()
+ while(sickbeard.started):
+ time.sleep(1)
if __name__ == "__main__":
if sys.hexversion >= 0x020600F0:
freeze_support()
- while(True):
- main()
+ sr = None
+ try:
+ # init sickrage
+ sr = SickRage()
- # check if restart was requested
- if not sickbeard.restarted:
- if sickbeard.CREATEPID:
- logger.log(u"Removing pidfile " + str(sickbeard.PIDFILE))
- sickbeard.remove_pid_file(sickbeard.PIDFILE)
- break
+ # start sickrage
+ sr.start()
- # restart
- logger.log("Restarting SickRage, please stand by...")
\ No newline at end of file
+ # shutdown web server
+ sr.webserver.shutDown()
+ sr.webserver.join()
+ sr.webserver = None
+
+ # if run as daemon delete the pidfile
+ if sr.runAsDaemon:
+ sr.daemon.delpid()
+
+ if not sickbeard.shutdown:
+ install_type = sickbeard.versionCheckScheduler.action.install_type
+
+ popen_list = []
+
+ if install_type in ('git', 'source'):
+ popen_list = [sys.executable, sickbeard.MY_FULLNAME]
+ elif install_type == 'win':
+ if hasattr(sys, 'frozen'):
+ # c:\dir\to\updater.exe 12345 c:\dir\to\sickbeard.exe
+ popen_list = [os.path.join(sickbeard.PROG_DIR, 'updater.exe'), str(sickbeard.PID), sys.executable]
+ else:
+ logger.log(u"Unknown SB launch method, please file a bug report about this", logger.ERROR)
+ popen_list = [sys.executable, os.path.join(sickbeard.PROG_DIR, 'updater.py'), str(sickbeard.PID), sys.executable,
+ sickbeard.MY_FULLNAME]
+
+ if popen_list:
+ popen_list += sickbeard.MY_ARGS
+ if '--nolaunch' not in popen_list:
+ popen_list += ['--nolaunch']
+ logger.log(u"Restarting SickRage with " + str(popen_list))
+ logger.close()
+ subprocess.Popen(popen_list, cwd=os.getcwd())
+
+ # exit process
+ os._exit(0)
+ except:
+ if sr:
+ logger.log(traceback.format_exc(), logger.ERROR)
+ else:
+ print(traceback.format_exc())
+ sys.exit(1)
\ No newline at end of file
diff --git a/gui/slick/css/trakt.css b/gui/slick/css/trakt.css
new file mode 100644
index 00000000..f2de517f
--- /dev/null
+++ b/gui/slick/css/trakt.css
@@ -0,0 +1,92 @@
+.traktShowDiv {
+
+ clear: both;
+ border-left: 1px solid #CCCCCC;
+ border-right: 1px solid #CCCCCC;
+ border-bottom: 1px solid #CCCCCC;
+ margin: auto;
+ padding: 0px;
+ text-align: left;
+ width: 750px;
+}
+
+.traktShowDiv a, .traktShowDiv a:link, .traktShowDiv a:visited, .traktShowDiv a:hover {
+ text-decoration: none;
+ background: none;
+}
+
+.traktShowTitle a {
+ color: #000000;
+ float: left;
+ padding-top: 3px;
+ line-height: 1.2em;
+ font-size: 1.1em;
+ text-shadow: -1px -1px 0 #FFF);
+}
+
+.traktShowTitleIcons {
+ float: right;
+ padding: 3px 5px;
+}
+
+.traktShowDiv .title {
+ font-weight: 900;
+ color: #333;
+}
+.imgWrapper {
+ background: url("../images/loading.gif") no-repeat scroll center center #FFFFFF;
+ border: 3px solid #FFFFFF;
+ box-shadow: 1px 1px 2px 0 #555555;
+ float: left;
+ height: 50px;
+ overflow: hidden;
+ text-indent: -3000px;
+ width: 50px;
+}
+.imgWrapper .traktPosterThumb {
+ float: left;
+ min-height: 100%;
+ min-width: 100%;
+ width: 50px;
+ height: auto;
+ position: relative;
+ border: none;
+ vertical-align: middle;
+}
+.traktPosterThumb {
+ -ms-interpolation-mode: bicubic; /* make scaling look nicer for ie */
+ vertical-align: top;
+ height: auto;
+ width: 160px;
+ border-top: 1px solid #ccc;
+ border-right: 1px solid #ccc;
+}
+
+.traktShowDiv th {
+ color: #000;
+ letter-spacing: 1px;
+ text-align: left;
+ background-color: #333333;
+}
+
+.traktShowDiv th.nobg {
+ background: #efefef;
+ border-top: 1px solid #666;
+ text-align: center;
+}
+
+.traktShowDiv td {
+ border-top: 1px solid #d2ebe8;
+ background: #fff;
+ padding: 5px 10px 5px 10px;
+ color: #000;
+}
+
+.traktShowDiv td.trakts_show {
+ width: 100%;
+ height: 90%;
+ border-top: 1px solid #ccc;
+ vertical-align: top;
+ background: #F5FAFA;
+ color: #000;
+}
diff --git a/gui/slick/interfaces/default/home_addShows.tmpl b/gui/slick/interfaces/default/home_addShows.tmpl
index 4d28ec81..953ccf96 100644
--- a/gui/slick/interfaces/default/home_addShows.tmpl
+++ b/gui/slick/interfaces/default/home_addShows.tmpl
@@ -26,15 +26,23 @@
For shows that you haven't downloaded yet, this option finds a show on theTVDB.com and TVRage.com, creates a directory for its episodes, and adds it to SickRage.