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