Browse Source

rewrite as api

raylu 12 years ago
parent
commit
031daa32bb

+ 2 - 1
config.py

@@ -13,7 +13,8 @@ class WebConfig(Config):
 	attrs = frozenset([
 		'port',
 		'host',
-		'cookie_secret',
+		'api_port',
+		'api_host',
 		'debug',
 	])
 

+ 3 - 2
config.yaml.example

@@ -1,7 +1,8 @@
 web:
     port: 8888
-    host: 'localhost:8888'
-    cookie_secret: 'dis is super sekrit'
+    host: 'http://localhost:8888'
+    api_port: 8887
+    api_host: 'http://localhost:8887'
     debug: true
 
 db:

+ 56 - 0
db/queries.py

@@ -0,0 +1,56 @@
+from collections import defaultdict
+import operator
+import db
+
+def search(q):
+	with db.cursor() as c:
+		corps = db.query(c, '''
+			SELECT DISTINCT corporation_id, corporation_name FROM characters
+			WHERE corporation_name LIKE ?
+			''', '%{}%'.format(q))
+	return {'corporations': corps}
+
+def corporation(corp_id):
+	with db.cursor() as c:
+		kills = db.query(c, '''
+			SELECT DISTINCT(kills.kill_id), kill_time FROM kills
+			JOIN characters on characters.kill_id = kills.kill_id
+			WHERE corporation_id = ?
+			''', corp_id)
+		kill_ids = list(map(operator.itemgetter('kill_id'), kills))
+		char_rows = db.query(c, '''
+			SELECT
+				kill_id, victim, final_blow,
+				character_id, character_name, corporation_id, corporation_name, alliance_id, alliance_name, faction_id, faction_name
+			FROM characters
+			WHERE kill_id IN ({})
+			'''.format(','.join(map(str, kill_ids))))
+		characters = defaultdict(dict)
+		for char in char_rows:
+			kill_id = char['kill_id']
+			if char['victim']:
+				characters[kill_id]['victim'] = char
+			elif char['final_blow']:
+				characters[kill_id]['final_blow'] = char
+		for kill in kills:
+			chars = characters[kill['kill_id']]
+			kill['victim'] = chars['victim']
+			kill['final_blow'] = chars['final_blow']
+	return kills
+
+def kill(kill_id):
+	with db.cursor() as c:
+		kill = db.get(c, '''
+			SELECT kill_time, solarSystemName, security FROM kills
+			JOIN eve.mapSolarSystems on solar_system_id = solarSystemID
+			WHERE kill_id = ?
+			''', kill_id)
+		characters = db.query(c, '''
+			SELECT ship_type_id, character_id, character_name,
+				corporation_id, corporation_name, alliance_id, alliance_name, faction_id, faction_name
+				typeName
+			FROM characters
+			JOIN eve.invTypes on ship_type_id = typeID
+			WHERE kill_id = ?
+			''', kill_id)
+	return {'kill': kill, 'characters': characters}

+ 10 - 58
server.py

@@ -1,8 +1,5 @@
 #!/usr/bin/env python3
 
-from collections import defaultdict
-import json
-import operator
 import os
 
 import cleancss
@@ -11,11 +8,11 @@ import tornado.ioloop
 import tornado.web
 
 from config import web as config
-import db
+import web.api
 
 class BaseHandler(tornado.web.RequestHandler):
 	def render(self, *args, **kwargs):
-		kwargs['host'] = config.host
+		kwargs['api_host'] = config.api_host
 		return super(BaseHandler, self).render(*args, **kwargs)
 
 	def render_string(self, *args, **kwargs):
@@ -28,60 +25,15 @@ class MainHandler(BaseHandler):
 
 class SearchHandler(BaseHandler):
 	def get(self):
-		q = self.get_argument('q')
-		with db.cursor() as c:
-			corps = db.query(c, '''
-				SELECT DISTINCT corporation_id, corporation_name FROM characters
-				WHERE corporation_name LIKE ?
-				''', '%{}%'.format(q))
-		self.render('search.html', corps=corps)
+		self.render('search.html')
 
 class CorporationHandler(BaseHandler):
-	def get(self, corp_id):
-		with db.cursor() as c:
-			kills = db.query(c, '''
-				SELECT DISTINCT(kills.kill_id), kill_time FROM kills
-				JOIN characters on characters.kill_id = kills.kill_id
-				WHERE corporation_id = ?
-				''', corp_id)
-			kill_ids = list(map(operator.itemgetter('kill_id'), kills))
-			char_rows = db.query(c, '''
-				SELECT
-					kill_id, victim, final_blow,
-					character_id, character_name, corporation_id, corporation_name, alliance_id, alliance_name, faction_id, faction_name
-				FROM characters
-				WHERE kill_id IN ({})
-				'''.format(','.join(map(str, kill_ids))))
-			characters = defaultdict(dict)
-			for char in char_rows:
-				kill_id = char['kill_id']
-				if char['victim']:
-					characters[kill_id]['victim'] = char
-				elif char['final_blow']:
-					characters[kill_id]['final_blow'] = char
-			for kill in kills:
-				chars = characters[kill['kill_id']]
-				kill['victim'] = chars['victim']
-				kill['final_blow'] = chars['final_blow']
-		self.render('corporation.html', kills=kills)
+	def get(self):
+		self.render('corporation.html')
 
 class KillHandler(BaseHandler):
-	def get(self, kill_id):
-		with db.cursor() as c:
-			kill = db.get(c, '''
-				SELECT kill_time, solarSystemName, security FROM kills
-				JOIN eve.mapSolarSystems on solar_system_id = solarSystemID
-				WHERE kill_id = ?
-				''', kill_id)
-			characters = db.query(c, '''
-				SELECT ship_type_id, character_id, character_name,
-					corporation_id, corporation_name, alliance_id, alliance_name, faction_id, faction_name
-					typeName
-				FROM characters
-				JOIN eve.invTypes on ship_type_id = typeID
-				WHERE kill_id = ?
-				''', kill_id)
-		self.render('kill.html', kill=kill, characters=characters)
+	def get(self):
+		self.render('kill.html')
 
 class CSSHandler(tornado.web.RequestHandler):
 	def get(self, css_path):
@@ -95,13 +47,13 @@ if __name__ == '__main__':
 		handlers=[
 			(r'/', MainHandler),
 			(r'/search', SearchHandler),
-			(r'/corporation/(.+)', CorporationHandler),
-			(r'/kill/(.+)', KillHandler),
+			(r'/corporation/.+', CorporationHandler),
+			(r'/kill/.+', KillHandler),
 			(r'/(css/.+)\.css', CSSHandler),
 		],
 		template_path=os.path.join(os.path.dirname(__file__), 'web/templates'),
-		cookie_secret=config.cookie_secret,
 		debug=config.debug,
 	).listen(config.port)
+	web.api.start()
 	print('listening on :%d' % config.port)
 	tornado.ioloop.IOLoop.instance().start()

+ 57 - 0
web/api.py

@@ -0,0 +1,57 @@
+import datetime
+import json
+
+import tornado.web
+
+from config import web as config
+import db.queries
+
+class JSONDateEncoder(json.JSONEncoder):
+	def default(self, data):
+		if isinstance(data, datetime.datetime):
+			return str(data)
+		return super(JSONDateEncoder, self).default(data)
+
+class APIHandler(tornado.web.RequestHandler):
+	def set_default_headers(self):
+		self.set_header('Access-Control-Allow-Origin', '*')
+		self.set_header('Access-Control-Allow-Headers', 'X-Requested-With, X-Request')
+
+	def compute_etag(self):
+		return None
+
+	def respond_json(self, data):
+		self.set_header('Content-Type', 'application/json; charset=UTF-8')
+		for chunk in JSONDateEncoder().iterencode(data):
+			self.write(chunk)
+		self.finish()
+
+	def options(self, *args):
+		return
+
+class SearchHandler(APIHandler):
+	def get(self):
+		q = self.get_argument('q')
+		data = db.queries.search(q)
+		self.respond_json(data)
+
+class CorporationHandler(APIHandler):
+	def get(self, corp_id):
+		kills = db.queries.corporation(corp_id)
+		self.respond_json(kills)
+
+class KillHandler(APIHandler):
+	def get(self, kill_id):
+		kill = db.queries.kill(kill_id)
+		self.respond_json(kill)
+
+def start():
+	tornado.web.Application(
+		handlers=[
+			(r'/search', SearchHandler),
+			(r'/corporation/(.+)', CorporationHandler),
+			(r'/kill/(.+)', KillHandler),
+		],
+		debug=config.debug,
+	).listen(config.api_port)
+	print('listening on :%d' % config.api_port)

+ 6 - 0
web/static/js/common.js

@@ -0,0 +1,6 @@
+window.ykill.api = function (path, cb) {
+	new Request.JSON({
+		'url': ykill.api_host + path,
+		'onSuccess': cb,
+	}).get();
+}

+ 49 - 0
web/static/js/corporation.js

@@ -0,0 +1,49 @@
+window.addEvent('domready', function() {
+	var corp_id = document.location.pathname.split('/').getLast();
+	ykill.api('/corporation/' + corp_id, function(kills) {
+		var div = $('kills');
+		kills.each(function(kill) {
+			var a = new Element('a', {'href': '/kill/' + kill['kill_id']});
+			a.appendText(kill['kill_time']);
+
+			a.adopt(new Element('img', {
+				'src': '//image.eveonline.com/Character/' + kill['victim']['character_id'] + '_32.jpg',
+				'alt': kill['victim']['character_name'],
+			}));
+			a.appendText(kill['victim']['character_name']);
+			a.adopt(new Element('img', {
+				'src': '//image.eveonline.com/Corporation/' + kill['victim']['corporation_id'] + '_32.png',
+				'alt': kill['victim']['corporation_name'],
+			}));
+			a.appendText(kill['victim']['corporation_name']);
+			if (kill['victim']['alliance_id']) {
+				a.adopt(new Element('img', {
+					'src': '//image.eveonline.com/Alliance/' + kill['victim']['alliance_id'] + '_32.png',
+					'alt': kill['victim']['alliance_name'],
+				}));
+				a.appendText(kill['victim']['alliance_name']);
+			}
+
+			a.adopt(new Element('img', {
+				'src': '//image.eveonline.com/Character/' + kill['final_blow']['character_id'] + '_32.jpg',
+				'alt': kill['final_blow']['character_name'],
+			}));
+			a.appendText(kill['final_blow']['character_name']);
+			a.adopt(new Element('img', {
+				'src': '//image.eveonline.com/Corporation/' + kill['final_blow']['corporation_id'] + '_32.png',
+				'alt': kill['final_blow']['corporation_name'],
+			}));
+			a.appendText(kill['final_blow']['corporation_name']);
+			if (kill['final_blow']['alliance_id']) {
+				a.adopt(new Element('img', {
+					'src': '//image.eveonline.com/Alliance/' + kill['final_blow']['alliance_id'] + '_32.png',
+					'alt': kill['final_blow']['alliance_name'],
+				}));
+				a.appendText(kill['final_blow']['alliance_name']);
+			}
+
+			div.adopt(a);
+			div.adopt(new Element('br'));
+		});
+	});
+});

+ 30 - 0
web/static/js/kill.js

@@ -0,0 +1,30 @@
+window.addEvent('domready', function() {
+	var kill_id = document.location.pathname.split('/').getLast();
+	ykill.api('/kill/' + kill_id, function(data) {
+		var kill = data.kill;
+		$('kill_time').appendText(kill['kill_time']);
+		$('solar_system').appendText(kill['solarSystemName'] + ' (' + kill['security'].toFixed(1) + ')');
+
+		var div = $('characters');
+		data.characters.each(function(char) {
+			div.adopt(new Element('img', {
+				'src': '//image.eveonline.com/Character/' + char['character_id'] + '_64.jpg',
+				'alt': char['character_name'],
+			}));
+			div.appendText(char['character_name']);
+			div.adopt(new Element('img', {
+				'src': '//image.eveonline.com/Corporation/' + char['corporation_id'] + '_64.png',
+				'alt': char['corporation_name'],
+			}));
+			div.appendText(char['corporation_name']);
+			if (char['alliance_id']) {
+				div.adopt(new Element('img', {
+					'src': '//image.eveonline.com/Alliance/' + char['alliance_id'] + '_64.png',
+					'alt': char['alliance_name'],
+				}));
+				div.appendText(char['alliance_name']);
+			}
+			div.adopt(new Element('br'));
+		});
+	});
+});

+ 11 - 0
web/static/js/search.js

@@ -0,0 +1,11 @@
+window.addEvent('domready', function() {
+	ykill.api('/search' + document.location.search, function(results) {
+		var corps = $('corps');
+		results.corporations.each(function(corp) {
+			corps.grab(new Element('a', {
+				'html': corp.corporation_name,
+				'href': '/corporation/' + corp.corporation_id,
+			}));
+		});
+	});
+});

+ 7 - 0
web/templates/base.html

@@ -3,6 +3,13 @@
 <head>
 	<link rel="stylesheet" type="text/css" href="/css/base.css" />
 	<script src="//ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools.js"></script>
+	<script>
+		window.ykill = {
+			'api_host': '{{ api_host }}',
+		};
+	</script>
+	<script src="/static/js/common.js"></script>
+	{% block js %}{% end %}
 </head>
 <body>
 	<div id="wrapper">

+ 5 - 21
web/templates/corporation.html

@@ -1,27 +1,11 @@
 {% extends "base.html" %}
 
+{% block js %}
+	<script src="/static/js/corporation.js"></script>
+{% end %}
+
 {% block main %}
 
-{% for kill in kills %}
-	<a href="/kill/{{ kill['kill_id'] }}">
-		{{ kill['kill_time'] }}
-		<img src="//image.eveonline.com/Character/{{ kill['victim']['character_id'] }}_32.jpg" alt="{{ kill['victim']['character_name'] }}">
-		{{ kill['victim']['character_name'] }}
-		<img src="//image.eveonline.com/Corporation/{{ kill['victim']['corporation_id'] }}_32.png" alt="{{ kill['victim']['corporation_name'] }}">
-		{{ kill['victim']['corporation_name'] }}
-		{% if kill['victim']['alliance_id'] != 0 %}
-			<img src="//image.eveonline.com/Alliance/{{ kill['victim']['alliance_id'] }}_32.png" alt="{{ kill['victim']['alliance_name'] }}">
-			{{ kill['victim']['alliance_name'] }}
-		{% end %}
-		<img src="//image.eveonline.com/Character/{{ kill['final_blow']['character_id'] }}_32.jpg" alt="{{ kill['final_blow']['character_name'] }}">
-		{{ kill['final_blow']['character_name'] }}
-		<img src="//image.eveonline.com/Corporation/{{ kill['final_blow']['corporation_id'] }}_32.png" alt="{{ kill['final_blow']['corporation_name'] }}">
-		{{ kill['final_blow']['corporation_name'] }}
-		{% if kill['final_blow']['alliance_id'] != 0 %}
-			<img src="//image.eveonline.com/Alliance/{{ kill['final_blow']['alliance_id'] }}_32.png" alt="{{ kill['final_blow']['alliance_name'] }}">
-			{{ kill['final_blow']['alliance_name'] }}
-		{% end %}
-	</a><br>
-{% end %}
+<div id="kills"></div>
 
 {% end %}

+ 7 - 14
web/templates/kill.html

@@ -1,21 +1,14 @@
 {% extends "base.html" %}
 
+{% block js %}
+	<script src="/static/js/kill.js"></script>
+{% end %}
+
 {% block main %}
 
-{{ kill['kill_time'] }}<br>
-{{ kill['solarSystemName'] }} ({{ round(kill['security'], 1) }})<br>
+<div id="kill_time"></div>
+<div id="solar_system"></div>
 
-{% for char in characters %}
-	<img src="//image.eveonline.com/Type/{{ char['ship_type_id'] }}_64.png" alt="{{ char ['typeName'] }}">
-	<img src="//image.eveonline.com/Character/{{ char['character_id'] }}_64.jpg" alt="{{ char['character_name'] }}">
-	{{ char['character_name'] }}
-	<img src="//image.eveonline.com/Corporation/{{ char['corporation_id'] }}_64.png" alt="{{ char['corporation_name'] }}">
-	{{ char['corporation_name'] }}
-	{% if char['alliance_id'] != 0 %}
-		<img src="//image.eveonline.com/Alliance/{{ char['alliance_id'] }}_64.png" alt="alliance">
-		{{ char['alliance_name'] }}
-	{% end %}
-	<br>
-{% end %}
+<div id="characters"></div>
 
 {% end %}

+ 5 - 5
web/templates/search.html

@@ -1,12 +1,12 @@
 {% extends "base.html" %}
 
+{% block js %}
+	<script src="/static/js/search.js"></script>
+{% end %}
+
 {% block main %}
 
 <h2>Corporations</h2>
-{% for corp in corps %}
-	<a href="/corporation/{{ corp['corporation_id'] }}">
-		{{ corp['corporation_name'] }}
-	</a>
-{% end %}
+<div id="corps"></div>
 
 {% end %}