diff options
Diffstat (limited to 'swiftstory/interface/ws.py')
-rw-r--r-- | swiftstory/interface/ws.py | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/swiftstory/interface/ws.py b/swiftstory/interface/ws.py new file mode 100644 index 0000000..d63e71c --- /dev/null +++ b/swiftstory/interface/ws.py @@ -0,0 +1,80 @@ +import asyncio +import contextlib +import json +import logging + +import websockets.exceptions +from websockets.server import WebSocketServerProtocol + +from swiftstory.client import Client +from swiftstory.exception import WrongAction, JoinError +from swiftstory.game_manager import GameManager +from swiftstory.status import error + + +class WebsocketsInterface: + """ Interface with WebSockets for SwiftStory. """ + def __init__(self, game_manager: GameManager): + self.game_manager = game_manager + + async def connection_handler(self, websocket: WebSocketServerProtocol, path: str): + client = Client(websocket, self.game_manager) + + with contextlib.suppress(websockets.exceptions.ConnectionClosed): + async for message in client.socket: + await client.socket.send(self.message_received_handler(client, message)) + + client.disconnect() + + def message_received_handler(self, client, message): + def join_game(): + try: + game_name = json_msg['game_name'] + except KeyError: + return error('field `game_name\' is required') + else: + lang = json_msg.get('lang') + return client.join_game(game_name, lang) + + def designate_card(): + card_id = None + try: + card_id = int(json_msg['card_id']) + except (KeyError, TypeError): + pass + finally: + return client.designate_card(card_id) + + def play_white_card(): + try: + card_id = int(json_msg['card_id']) + except KeyError: + return error('field `card_id\' is required') + else: + return client.play_white_card(card_id) + + opcodes_map = { + "join_game": join_game, + "view_player_cards": lambda: client.view_player_cards(), + "view_black_card": lambda: client.view_black_card(), + "view_played_cards": lambda: client.view_played_cards(), + "pick_black_card": lambda: client.pick_black_card(), + "collect_cards": lambda: client.collect_cards(), + "designate_card": designate_card, + "play_white_card": play_white_card, + } + + try: + json_msg = json.loads(message) + except json.JSONDecodeError: + return error('badly formatted json') + + try: + return opcodes_map[json_msg["op"]]() + except (KeyError, TypeError): + return error('invalid command') + except WrongAction as e: + return error(str(e)) + except JoinError as e: + logging.warning("player could not join game: %s", e.__repr__()) + return error(str(e)) |