import uuid from channels.generic.websocket import AsyncJsonWebsocketConsumer rooms = {} class CallConsumer(AsyncJsonWebsocketConsumer): async def connect(self): self.room_code = self.scope["url_route"]["kwargs"]["room_code"] self.room_group_name = f"call_{self.room_code}" self.client_id = uuid.uuid4().hex self.username = "Guest" await self.channel_layer.group_add(self.room_group_name, self.channel_name) await self.accept() await self.send_json({"event": "connect", "socketId": self.client_id}) async def disconnect(self, close_code): room = rooms.get(self.room_code, {}) was_joined = self.client_id in room if was_joined: room.pop(self.client_id, None) if not room: rooms.pop(self.room_code, None) await self.channel_layer.group_send( self.room_group_name, { "type": "room_event", "sender_channel_name": self.channel_name, "payload": { "event": "user-left", "socketId": self.client_id, }, }, ) await self.channel_layer.group_discard(self.room_group_name, self.channel_name) async def receive_json(self, content): event = content.get("event") if event == "username": self.username = content.get("username") or "Guest" room = rooms.get(self.room_code, {}) if self.client_id in room: room[self.client_id]["username"] = self.username await self._broadcast({ "event": "username", "socketId": self.client_id, "username": self.username, }) return if event == "join-call": room = rooms.setdefault(self.room_code, {}) existing_users = [ {"socketId": socket_id, "username": participant["username"]} for socket_id, participant in room.items() if socket_id != self.client_id ] room[self.client_id] = { "channel_name": self.channel_name, "username": self.username, } await self.send_json({"event": "room-users", "users": existing_users}) await self._broadcast({ "event": "user-joined", "user": { "socketId": self.client_id, "username": self.username, }, }) return if event == "signal": await self._send_to_peer( content.get("toId"), { "event": "signal", "fromSocketId": self.client_id, "message": content.get("message"), }, ) return if event == "chat-message": await self._broadcast( { "event": "chat-message", "data": content.get("data", ""), "sender": content.get("sender") or self.username, "socketIdSender": self.client_id, }, include_sender=False, ) return if event in ("screen-share-started", "screen-share-stopped"): await self._broadcast( { "event": event, "sharerSocketId": content.get("sharerSocketId") or self.client_id, }, include_sender=False, ) async def _send_to_peer(self, socket_id, payload): participant = rooms.get(self.room_code, {}).get(socket_id) if not participant: return await self.channel_layer.send( participant["channel_name"], { "type": "direct_event", "payload": payload, }, ) async def _broadcast(self, payload, include_sender=True): await self.channel_layer.group_send( self.room_group_name, { "type": "room_event", "sender_channel_name": None if include_sender else self.channel_name, "payload": payload, }, ) async def room_event(self, event): if event.get("sender_channel_name") == self.channel_name: return await self.send_json(event["payload"]) async def direct_event(self, event): await self.send_json(event["payload"])