import asyncio import websockets.exceptions from ws.server.ws_server import WsServer from ws.user import User, UserSet, update from ws.connection import IConnection class WsServerMultiUser(WsServer): def __init__(self, loop=None, listener: IConnection = None): WsServer.__init__(self, loop) self.listener = listener self.USERS = UserSet() self.global_state = {} async def notify_state(self, data): if self.USERS: # asyncio.wait doesn't accept an empty list await asyncio.gather(*[user.send(data) for user in self.USERS]) async def notify_users(self): if self.USERS: # asyncio.wait doesn't accept an empty list message = {"info": {"type": "users", "count": len(self.USERS)}} await asyncio.gather(*[user.send(message) for user in self.USERS]) async def register(self, websocket): usr = User(websocket) usr.path_add("info") self.USERS.add(websocket, usr) await self.notify_users() async def unregister(self, websocket): self.USERS.remove(websocket) await self.notify_users() async def handler_recv(self, websocket, path): try: while True: data = await websocket.recv() usr = self.USERS.get(websocket) processed = await usr.process(data) if processed: await usr.send(self.global_state) else: await self.listener.on_recv(data) except websockets.exceptions.ConnectionClosed: pass async def handler_send(self, websocket, path): while True: data = await self.listener.on_send() await self.notify_state(data) self.global_state = update(self.global_state, data)