dd-re/server.py

121 lines
3.3 KiB
Python
Executable File

#!/usr/bin/python3
import json
import logging
import os
import time
from urllib.parse import unquote
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.web import StaticFileHandler, Application, HTTPError
import tornado.gen
import tornado.web
from recommendation_engine import Engine
from utils import json_dumps, run_async
BANNER_PUBLIC = 'DD recommondation engine'
BANNER = '%s - use POST at / to access JSON-RPC 2.0 endpoint' % BANNER_PUBLIC
logger = logging.getLogger(__name__)
@run_async
def api_task(request, engine, callback):
try:
if request['method'] == 'getVideos':
result = engine.get_videos(**request['params'])
elif request['method'] == 'getNext':
result = engine.get_next(**request['params'])
elif request['method'] == 'getRecommendations':
result = engine.state
elif request['method'] == 'setRecommendations':
result = engine.update_state(request['params'])
else:
result = {}
response = {
'result': result
}
except:
logger.error('api failed: %s', request, exc_info=True)
response = {'error': {'code': -32000, 'message': 'Server error'}}
callback(response)
class RPCHandler(tornado.web.RequestHandler):
def initialize(self, engine):
self.engine = engine
def get(self):
self.write(BANNER)
@tornado.gen.coroutine
def post(self):
error = None
request = None
try:
request = json.loads(self.request.body.decode())
if request['method'] not in ('getVideos', 'getNext', 'getRecommendations', 'setRecommendations'):
raise Exception('unknown method')
except:
error = {'error': {'code': -32700, 'message': 'Parse error'}}
if not error:
try:
response = yield tornado.gen.Task(api_task, request, self.engine)
except:
logger.error("ERROR: %s", request, exc_info=True)
error = {'error': {'code': -32000, 'message': 'Server error'}}
if error:
response = error
if request and 'id' in request:
response['id'] = request['id']
response['jsonrpc'] = '2.0'
response = json_dumps(response)
self.write(response)
def main(prefix='json/'):
settings = {
'debug': False,
'port': 8081,
'address': '',
'pandora': 'http://pandora.dmp/api/',
'pandora_ws': 'ws://pandora.dmp/api/ws/',
'username': 'dd.re',
'password': 'dd.re'
}
engine = Engine(prefix, **settings)
handlers = [
(r'/', RPCHandler, dict(engine=engine)),
]
options = {
'debug': settings['debug'],
'gzip': True,
}
if settings['debug']:
log_format = '%(asctime)s:%(levelname)s:%(name)s:%(message)s'
logging.basicConfig(level=logging.DEBUG, format=log_format)
app = Application(handlers, **options)
app.listen(settings['port'], settings['address'])
main = IOLoop.instance()
update_cb = PeriodicCallback(engine.update_async, 15*60*1000)
update_cb.start()
#main.spawn_callback(update, engine)
#fixme run periodically
try:
main.start()
except:
print('shutting down...')
if __name__ == '__main__':
main()