#!/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()