summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorraylu <raylu@gridium.com>2013-10-20 03:07:32 -0700
committerraylu <raylu@gridium.com>2013-10-20 03:19:40 -0700
commit031daa32bbe11417d0dfb968dfbf888f0dc65d86 (patch)
tree33491f786aa8edf5b6548b1d5e518a2834e4c0a9
parent585ad90d3cc59ad7d4fd306170b710699e48efda (diff)
downloadykill-031daa32bbe11417d0dfb968dfbf888f0dc65d86.tar.xz
rewrite as api
-rw-r--r--config.py3
-rw-r--r--config.yaml.example5
-rw-r--r--db/queries.py56
-rwxr-xr-xserver.py68
-rw-r--r--web/api.py57
-rw-r--r--web/static/js/common.js6
-rw-r--r--web/static/js/corporation.js49
-rw-r--r--web/static/js/kill.js30
-rw-r--r--web/static/js/search.js11
-rw-r--r--web/templates/base.html7
-rw-r--r--web/templates/corporation.html26
-rw-r--r--web/templates/kill.html21
-rw-r--r--web/templates/search.html10
13 files changed, 248 insertions, 101 deletions
diff --git a/config.py b/config.py
index 46df4d4..426d968 100644
--- a/config.py
+++ b/config.py
@@ -13,7 +13,8 @@ class WebConfig(Config):
attrs = frozenset([
'port',
'host',
- 'cookie_secret',
+ 'api_port',
+ 'api_host',
'debug',
])
diff --git a/config.yaml.example b/config.yaml.example
index d521366..f29bfdd 100644
--- a/config.yaml.example
+++ b/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:
diff --git a/db/queries.py b/db/queries.py
new file mode 100644
index 0000000..f795b39
--- /dev/null
+++ b/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}
diff --git a/server.py b/server.py
index 54afcc2..c68aaaf 100755
--- a/server.py
+++ b/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()
diff --git a/web/api.py b/web/api.py
new file mode 100644
index 0000000..4993393
--- /dev/null
+++ b/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)
diff --git a/web/static/js/common.js b/web/static/js/common.js
new file mode 100644
index 0000000..4592cbe
--- /dev/null
+++ b/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();
+}
diff --git a/web/static/js/corporation.js b/web/static/js/corporation.js
new file mode 100644
index 0000000..10a1753
--- /dev/null
+++ b/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'));
+ });
+ });
+});
diff --git a/web/static/js/kill.js b/web/static/js/kill.js
new file mode 100644
index 0000000..67f819d
--- /dev/null
+++ b/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'));
+ });
+ });
+});
diff --git a/web/static/js/search.js b/web/static/js/search.js
new file mode 100644
index 0000000..faeb8fe
--- /dev/null
+++ b/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,
+ }));
+ });
+ });
+});
diff --git a/web/templates/base.html b/web/templates/base.html
index afd3c68..ffbe99b 100644
--- a/web/templates/base.html
+++ b/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">
diff --git a/web/templates/corporation.html b/web/templates/corporation.html
index 0afe4c3..66eceb2 100644
--- a/web/templates/corporation.html
+++ b/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 %}
diff --git a/web/templates/kill.html b/web/templates/kill.html
index bb286bc..112c2e8 100644
--- a/web/templates/kill.html
+++ b/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 %}
diff --git a/web/templates/search.html b/web/templates/search.html
index 03980af..d84c5da 100644
--- a/web/templates/search.html
+++ b/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 %}