summaryrefslogtreecommitdiff
path: root/server.py
diff options
context:
space:
mode:
Diffstat (limited to 'server.py')
-rw-r--r--server.py88
1 files changed, 88 insertions, 0 deletions
diff --git a/server.py b/server.py
new file mode 100644
index 0000000..76eddd8
--- /dev/null
+++ b/server.py
@@ -0,0 +1,88 @@
+import asyncio
+import json
+import random
+import typing
+import weakref
+
+import aiohttp
+import chess
+import chess.engine
+from aiohttp import web
+
+app = web.Application()
+app['websockets'] = weakref.WeakSet()
+app['chessgames'] = weakref.WeakSet()
+
+
+async def index(request: web.Request) -> web.Response:
+ return web.Response(text="Welcome to the chess hell backend!")
+
+
+async def handle_socket(request: web.Request):
+ ws = web.WebSocketResponse()
+ await ws.prepare(request)
+ request.app['websockets'].add(ws)
+ engine: typing.Optional[chess.engine.UciProtocol] = None
+ try:
+ board = chess.Board()
+ transport, engine = await chess.engine.popen_uci('stockfish')
+ await ws.send_json(dict(event="ready", player_color='white', board=board.fen()))
+ async for msg in ws:
+ msg: aiohttp.WSMessage
+ if msg.type == aiohttp.WSMsgType.TEXT:
+ req = json.loads(msg.data)
+ m = req["method"]
+ if m == "move":
+ user_move = chess.Move.from_uci(req['params']['move'])
+ if user_move not in board.legal_moves:
+ await ws.send_json(dict(
+ event="reject_move",
+ board=board.fen(),
+ ))
+ continue
+ board.push(user_move)
+ # candidates = await engine.analyse(board, chess.engine.Limit(time=1), multipv=100)
+ my_move: chess.Move = random.choice(list(board.legal_moves))
+ board.push(my_move)
+ await ws.send_json(dict(
+ event="computer_moved", board=board.fen(),
+ lastmove=my_move.uci(),
+ ))
+
+ finally:
+ if not ws.closed:
+ await ws.close()
+ print("Cleaning up websocket")
+ request.app['websockets'].discard(ws)
+ if engine is not None:
+ asyncio.create_task(engine.quit())
+ return ws
+
+
+async def on_shutdown(app):
+ print("On shutdown called")
+ for ws in set(app['websockets']):
+ ws: web.WebSocketResponse
+ await ws.close(code=aiohttp.WSCloseCode.GOING_AWAY,
+ message=b'Server shutdown')
+ print("Closing websocket")
+
+
+async def handle_status(request: web.Request):
+ return web.json_response(dict(
+ all_tasks=len(asyncio.all_tasks(asyncio.get_running_loop())),
+ websockets=len(request.app['websockets']),
+ games=len(request.app['chessgames']),
+ ))
+
+
+app.add_routes([
+ web.get('/', index),
+ web.get('/socket', handle_socket),
+ web.get('/status', handle_status),
+])
+
+app.on_shutdown.append(on_shutdown)
+
+if __name__ == '__main__':
+ web.run_app(app, )