1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-11-15 13:55:05 -05:00

Auto-reloads app on code changes automatically detected from git.

Fixed issues with basicauth/cookies and login page.
Parse results now displayed all the time.
This commit is contained in:
echel0n 2014-06-16 03:44:33 -07:00
parent 088e32b117
commit 489a181cdb
8 changed files with 59 additions and 44 deletions

View File

@ -18,8 +18,10 @@
# along with SickRage. If not, see <http://www.gnu.org/licenses/>. # along with SickRage. If not, see <http://www.gnu.org/licenses/>.
# Check needed software dependencies to nudge users to fix their setup # Check needed software dependencies to nudge users to fix their setup
import functools
import sys import sys
import tornado.ioloop import tornado.ioloop
import tornado.autoreload
if sys.version_info < (2, 6): if sys.version_info < (2, 6):
print "Sorry, requires Python 2.6 or 2.7." print "Sorry, requires Python 2.6 or 2.7."
@ -151,6 +153,8 @@ def main():
TV for me TV for me
""" """
io_loop = IOLoop.current()
# do some preliminary stuff # do some preliminary stuff
sickbeard.MY_FULLNAME = os.path.normpath(os.path.abspath(__file__)) sickbeard.MY_FULLNAME = os.path.normpath(os.path.abspath(__file__))
sickbeard.MY_NAME = os.path.basename(sickbeard.MY_FULLNAME) sickbeard.MY_NAME = os.path.basename(sickbeard.MY_FULLNAME)
@ -381,10 +385,21 @@ def main():
sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable
# init startup tasks # init startup tasks
IOLoop.current().add_timeout(datetime.timedelta(seconds=5), startup) io_loop.add_timeout(datetime.timedelta(seconds=5), startup)
# start IOLoop def autoreload_shutdown():
IOLoop.current().start() logger.log('SickRage is now auto-reloading, please stand by ...')
webserveInit.server.stop()
sickbeard.halt()
sickbeard.saveAll()
sickbeard.cleanup_tornado_sockets(io_loop)
# autoreload.
tornado.autoreload.start(io_loop)
tornado.autoreload.add_reload_hook(autoreload_shutdown)
# start IOLoop.
io_loop.start()
sickbeard.saveAndShutdown() sickbeard.saveAndShutdown()
return return

View File

@ -1279,7 +1279,7 @@ def remove_pid_file(PIDFILE):
def sig_handler(signum=None, frame=None): def sig_handler(signum=None, frame=None):
if type(signum) != type(None): if type(signum) != type(None):
logger.log(u"Signal %i caught, saving and exiting..." % int(signum)) logger.log(u"Signal %i caught, saving and exiting..." % int(signum))
saveAndShutdown() webserveInit.shutdown()
def saveAll(): def saveAll():
global showList global showList
@ -1293,10 +1293,20 @@ def saveAll():
logger.log(u"Saving config file to disk") logger.log(u"Saving config file to disk")
save_config() save_config()
def cleanup_tornado_sockets(io_loop):
for fd in io_loop._handlers.keys():
try:
os.close(fd)
except Exception:
pass
def saveAndShutdown(): def saveAndShutdown():
halt() halt()
saveAll() saveAll()
cleanup_tornado_sockets(IOLoop.current())
if CREATEPID: if CREATEPID:
logger.log(u"Removing pidfile " + str(PIDFILE)) logger.log(u"Removing pidfile " + str(PIDFILE))
remove_pid_file(PIDFILE) remove_pid_file(PIDFILE)

View File

@ -369,6 +369,8 @@ class NameParser(object):
if cache_result: if cache_result:
name_parser_cache.add(name, final_result) name_parser_cache.add(name, final_result)
logger.log(u"Parsed " + name + " into " + str(final_result).decode('utf-8', 'xmlcharrefreplace'), logger.DEBUG)
return final_result return final_result
@ -547,6 +549,8 @@ class ParseResult(object):
self.episode_numbers = new_episode_numbers self.episode_numbers = new_episode_numbers
self.season_number = new_season_numbers[0] self.season_number = new_season_numbers[0]
logger.log(u"Converted parsed result " + self.original_name + " into " + str(self).decode('utf-8', 'xmlcharrefreplace'), logger.DEBUG)
return self return self
def _is_air_by_date(self): def _is_air_by_date(self):

View File

@ -481,8 +481,6 @@ class PostProcessor(object):
np = NameParser(file, useIndexers=True, convert=True) np = NameParser(file, useIndexers=True, convert=True)
parse_result = np.parse(name) parse_result = np.parse(name)
self._log(u"Parsed " + name + " into " + str(parse_result).decode('utf-8', 'xmlcharrefreplace'), logger.DEBUG)
# couldn't find this in our show list # couldn't find this in our show list
if not parse_result.show: if not parse_result.show:
return to_return return to_return

View File

@ -19,13 +19,13 @@
import datetime import datetime
import sickbeard import sickbeard
from tornado.httputil import HTTPHeaders from tornado.web import RequestHandler
MESSAGE = 'notice' MESSAGE = 'notice'
ERROR = 'error' ERROR = 'error'
class Notifications(object): class Notifications(RequestHandler):
""" """
A queue of Notification objects. A queue of Notification objects.
""" """
@ -71,7 +71,7 @@ class Notifications(object):
notifications = Notifications() notifications = Notifications()
class Notification(object): class Notification(RequestHandler):
""" """
Represents a single notification. Tracks its own timeout and a list of which clients have Represents a single notification. Tracks its own timeout and a list of which clients have
seen it before. seen it before.

View File

@ -58,8 +58,8 @@ class CheckVersion():
if sickbeard.AUTO_UPDATE: if sickbeard.AUTO_UPDATE:
logger.log(u"New update found for SickRage, starting auto-updater ...") logger.log(u"New update found for SickRage, starting auto-updater ...")
if sickbeard.versionCheckScheduler.action.update(): if sickbeard.versionCheckScheduler.action.update():
logger.log(u"Update was successfull, restarting SickRage ...") logger.log(u"Update was successfull, auto-reloading SickRage ...")
threading.Timer(2, sickbeard.invoke_restart, [False]).start() #threading.Timer(2, sickbeard.invoke_restart, [False]).start()
def find_install_type(self): def find_install_type(self):
""" """

View File

@ -105,15 +105,13 @@ def require_basic_auth(handler_class):
return True return True
auth_header = handler.request.headers.get('Authorization') auth_header = handler.request.headers.get('Authorization')
if auth_header is None or not auth_header.startswith('Basic '): if auth_header and auth_header.startswith('Basic '):
get_auth() auth_decoded = base64.decodestring(auth_header[6:])
basicauth_user, basicauth_pass = auth_decoded.split(':', 2)
auth_decoded = base64.decodestring(auth_header[6:]) if basicauth_user == sickbeard.WEB_USERNAME and basicauth_pass == sickbeard.WEB_PASSWORD:
basicauth_user, basicauth_pass = auth_decoded.split(':', 2) if not handler.get_secure_cookie("user"):
if basicauth_user == sickbeard.WEB_USERNAME and basicauth_pass == sickbeard.WEB_PASSWORD: handler.set_secure_cookie("user", str(time.time()))
if not handler.get_secure_cookie("user"): return True
handler.set_secure_cookie("user", str(time.time()))
return True
handler.clear_cookie("user") handler.clear_cookie("user")
get_auth() get_auth()
@ -128,28 +126,12 @@ def require_basic_auth(handler_class):
handler_class._execute = wrap_execute(handler_class._execute) handler_class._execute = wrap_execute(handler_class._execute)
return handler_class return handler_class
@require_basic_auth
class RedirectHandler(RequestHandler): class RedirectHandler(RequestHandler):
"""Redirects the client to the given URL for all GET requests.
You should provide the keyword argument ``url`` to the handler, e.g.:: def get(self, path, **kwargs):
application = web.Application([
(r"/oldpath", web.RedirectHandler, {"url": "/newpath"}),
])
"""
def get(self, path):
self.redirect(path, permanent=True) self.redirect(path, permanent=True)
@require_basic_auth
class LoginHandler(RedirectHandler):
def get(self, path):
self.redirect(self.get_argument("next", u"/"))
@require_basic_auth
class IndexHandler(RedirectHandler): class IndexHandler(RedirectHandler):
def __init__(self, application, request, **kwargs): def __init__(self, application, request, **kwargs):
super(IndexHandler, self).__init__(application, request, **kwargs) super(IndexHandler, self).__init__(application, request, **kwargs)
@ -171,10 +153,7 @@ class IndexHandler(RedirectHandler):
return args return args
def _dispatch(self): def _dispatch(self):
"""
Load up the requested URL if it matches one of our own methods.
Skip methods that start with an underscore (_).
"""
args = None args = None
path = self.request.uri.split('?')[0] path = self.request.uri.split('?')[0]
@ -469,6 +448,9 @@ class IndexHandler(RedirectHandler):
browser = WebFileBrowser browser = WebFileBrowser
class LoginHandler(IndexHandler):
def get(self):
self.redirect(self.get_argument("next", u"/"))
class PageTemplate(Template): class PageTemplate(Template):
def __init__(self, *args, **KWs): def __init__(self, *args, **KWs):

View File

@ -10,6 +10,8 @@ from sickbeard.helpers import create_https_certificates
from tornado.web import Application, StaticFileHandler, RedirectHandler, HTTPError from tornado.web import Application, StaticFileHandler, RedirectHandler, HTTPError
from tornado.httpserver import HTTPServer from tornado.httpserver import HTTPServer
server = None
class MultiStaticFileHandler(StaticFileHandler): class MultiStaticFileHandler(StaticFileHandler):
def initialize(self, paths, default_filename=None): def initialize(self, paths, default_filename=None):
self.paths = paths self.paths = paths
@ -95,10 +97,11 @@ def initWebServer(options={}):
# Load the app # Load the app
app = Application([], app = Application([],
debug=True, log_function=lambda x: None,
debug=False,
gzip=True, gzip=True,
autoreload=True, autoreload=True,
xheaders=False, xheaders=True,
cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=', cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=',
login_url='/login' login_url='/login'
) )
@ -140,9 +143,12 @@ def initWebServer(options={}):
server.listen(options['port'], options['host']) server.listen(options['port'], options['host'])
def shutdown(): def shutdown():
global server
logger.log('Shutting down tornado') logger.log('Shutting down tornado')
try: try:
IOLoop.current().stop() IOLoop.current().stop()
server.stop()
except RuntimeError: except RuntimeError:
pass pass
except: except: