#!/usr/bin/python3
import os
os.chdir(os.path.dirname(os.path.abspath(__file__)))
import sys
if len(sys.argv) == 2 and sys.argv[1] == "daemon":
sys.stdout = open('log/server.log', 'a')
sys.stderr = sys.stdout
import config
import game
import template
import json
import threading
import http.server
import urllib.parse
class Server(http.server.BaseHTTPRequestHandler):
def write(self, *texts):
for text in texts:
self.wfile.write(bytes(str(text), "utf8"))
def parsePath(self, path):
if not path.startswith(config.prefix):
return None
path = path[len(config.prefix):]
if len(path) and path[0] != '/':
return None
return list(filter(None, path.split("/")))
def err(self, code = 404, message = ""):
self.send_response(int(code))
self.send_header("Content-type", "text/html")
self.end_headers()
tplErrorpage.write(self, {
"host": config.externalHost,
"prefix": config.prefix,
"code": int(code),
"message": str(message),
"waiting": False });
def writeJpeg(self, path):
if not path.endswith(".jpg") or not os.path.isfile(path):
return self.err()
with open(path, "rb") as f:
self.send_response(200)
self.send_header("Content-type", "image/jpeg")
self.send_header("Cache-Control", "max-age=3600")
self.end_headers()
self.wfile.write(f.read())
def writeStatus(self, player):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.write(json.dumps(player.status()))
def do_POST(self):
if self.command != 'POST':
return self.err()
path = self.parsePath(self.path)
if path is None:
return self.err()
length = int(self.headers.get('content-length'))
data = self.rfile.read(length)
fields = urllib.parse.parse_qs(str(data,"UTF-8"))
word = str(fields.get("word", [""])[0])
vocabulary = str(fields.get("vocabulary", [""])[0])
with mutex:
if not path: # create new game
if not vocabulary in game.words:
return self.err()
g = game.Game(vocabulary, word)
self.send_response(303)
self.send_header("Location", str(config.prefix) + "/" + str(g.players[0].id))
self.end_headers()
return
player = game.players.get(path[0], None)
if not player:
return self.err()
del path[0]
if not path:
player.join(word)
elif len(path) == 2 and path[0] == "select":
i = -1
try:
i = int(path[1])
except ValueError:
return self.err()
player.select(i)
elif len(path) == 1 and path[0] == "ready":
player.nextturn(word)
else:
return self.err()
self.send_response(303)
self.send_header("Location", str(config.prefix) + "/" + str(player.id))
self.end_headers()
def do_GET(self):
#loadTemplates()
if self.command != 'GET':
return self.err()
if self.path.startswith(config.cardsPrefix):
p = str(self.path[len(config.cardsPrefix):])
if p and p[0] == "/":
if p.count("/") > 1 or p.count("..") > 0:
return self.err()
return self.writeJpeg("cards" + p)
path = self.parsePath(self.path)
if path is None:
return self.err()
if not path:
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
tplStartpage.write(self, {
"host": config.externalHost,
"prefix": config.prefix,
"vocabularies": list(sorted(game.words.keys())),
"waiting": False });
return
with mutex:
if len(path) != 1:
return self.err()
j = False
if path[0].endswith(".json"):
j = True
path[0] = path[0][0:-5]
player = game.players.get(path[0], None)
if not player:
return self.err()
if j:
return self.writeStatus(player)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
if player.game.started:
tplPlayerpage.write(self, player.status());
else:
tplJoinpage.write(self, player.status());
def loadTemplates():
global tplStartpage, tplJoinpage, tplPlayerpage, tplErrorpage
tplStartpage = template.TplLoader.load("tpl/startpage.tpl")
tplJoinpage = template.TplLoader.load("tpl/joinpage.tpl")
tplPlayerpage = template.TplLoader.load("tpl/playerpage.tpl")
tplErrorpage = template.TplLoader.load("tpl/errorpage.tpl")
mutex = threading.Lock()
loadTemplates()
game.mergeCards("cards")
game.mergeWords("words")
webServer = http.server.HTTPServer((
config.hostName,
config.serverPort ), Server )
print("Server started http://%s:%s" % (
config.hostName,
config.serverPort ))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server stopped.")