134 lines
3.5 KiB
Python
Executable file
134 lines
3.5 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
# vi:si:et:sw=4:sts=4:ts=4
|
|
from __future__ import division, print_function
|
|
|
|
import json
|
|
import os
|
|
import signal
|
|
import mimetypes
|
|
|
|
from tornado.httpserver import HTTPServer
|
|
from tornado.ioloop import IOLoop, PeriodicCallback
|
|
from tornado.web import Application
|
|
import tornado
|
|
|
|
import websocket
|
|
from websocket import trigger_event
|
|
import state
|
|
from tasks import Tasks
|
|
import link
|
|
|
|
import logging
|
|
logger = logging.getLogger('server')
|
|
|
|
root_dir = os.path.normpath(os.path.abspath(os.path.dirname(__file__)))
|
|
STATIC_PATH = os.path.join(root_dir, 'static')
|
|
|
|
class BaseHandler(tornado.web.RequestHandler):
|
|
|
|
def serve_static(self, path, mimetype=None, include_body=True):
|
|
if not mimetype:
|
|
mimetype = mimetypes.guess_type(path)[0]
|
|
logging.debug('serve %s', path)
|
|
if os.path.exists(path):
|
|
self.set_header('Content-Type', mimetype)
|
|
self.set_header('Content-Length', str(os.stat(path).st_size))
|
|
if include_body:
|
|
with open(path) as fd:
|
|
self.write(fd.read())
|
|
else:
|
|
self.set_status(404)
|
|
return
|
|
|
|
def render_json(self, response):
|
|
response = json.dumps(response)
|
|
self.set_header('Content-Type', 'application/json')
|
|
self.set_header('Content-Length', str(len(response)))
|
|
self.write(response)
|
|
self.finish()
|
|
|
|
class RemoteHandler(BaseHandler):
|
|
|
|
def post(self, action):
|
|
data = json.loads(self.request.body)
|
|
response = {}
|
|
print ('GOT remote request', action, data)
|
|
if action == 'info':
|
|
response = state.info
|
|
elif action == 'message':
|
|
data['from'] = self.request.headers['From']
|
|
trigger_event(action, data)
|
|
else:
|
|
response = {'error': 'unknown action'}
|
|
return self.render_json(response)
|
|
|
|
class MainHandler(BaseHandler):
|
|
|
|
def get(self, path):
|
|
path = path[1:]
|
|
if not path:
|
|
path = 'index.html'
|
|
path = os.path.join(STATIC_PATH, path)
|
|
self.serve_static(path)
|
|
|
|
def post(self, path):
|
|
action = path.split('/')[1]
|
|
data = json.loads(self.request.body)
|
|
response = {}
|
|
if action in ('info', 'ping'):
|
|
if 'id' in data:
|
|
id = data['id']
|
|
del data['id']
|
|
response = link.remote_json(id, action, data)
|
|
return self.render_json(response)
|
|
|
|
if __name__ == '__main__':
|
|
address = ''
|
|
port = int(os.environ.get('PORT', 8000))
|
|
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
options = {
|
|
'debug': True,
|
|
}
|
|
handlers = [
|
|
(r'/ws', websocket.Handler),
|
|
(r"/remote/(.*)", RemoteHandler),
|
|
(r"(.*)", MainHandler),
|
|
]
|
|
|
|
http_server = HTTPServer(Application(handlers, **options))
|
|
|
|
http_server.listen(port, address)
|
|
|
|
state.tasks = Tasks()
|
|
state.main = IOLoop.instance()
|
|
|
|
state._status = PeriodicCallback(lambda: state.info.update(link.post('info')), 60000)
|
|
state._status.start()
|
|
|
|
if ':' in address:
|
|
host = '[%s]' % address
|
|
elif not address:
|
|
host = '[::1]'
|
|
else:
|
|
host = address
|
|
url = 'http://%s:%s/' % (host, port)
|
|
|
|
link.add('chat', url + 'remote/')
|
|
state.info = link.post('info')
|
|
|
|
print('listening at %s' % url)
|
|
|
|
def shutdown():
|
|
state.tasks.join()
|
|
http_server.stop()
|
|
|
|
signal.signal(signal.SIGTERM, shutdown)
|
|
|
|
try:
|
|
state.main.start()
|
|
except:
|
|
print('shutting down...')
|
|
shutdown()
|