与员工django频道聊天

时间:2018-11-08 14:06:30

标签: python django websocket django-channels

我正在开发一个聊天平台,该平台的用户将可以与工作人员聊天。仅当它们已连接时,否则聊天将被禁用。可能有一个或多个工作人员。

我还没有完全理解如何计算相关人员,现在我有一个增加或减少使用者的变量实例(total_staff),但是效果不佳。

这是我的代码:

from channels.generic.websocket import AsyncJsonWebsocketConsumer
from .exceptions import ClientError


class ChatConsumer(AsyncJsonWebsocketConsumer):
    """
    Chat consumer
    """
    rooms = set()
    total_staff = 0

    async def connect(self):
        """
        Called when the websocket is handshaking as part of initial connection.
        """

        # Accept the connection
        await self.accept()

    async def receive_json(self, content):
        """
        Called when we get a text frame. Channels will JSON-decode the payload
        for us and pass it as the first argument.
        """
        # Messages will have a "command" key we can switch on
        command = content.get("command", None)

        try:
            # User normal join to platform
            if command == "join":
                # Make them join the room
                await self.join_room(content["room"])
            elif command == "staff_connect":
                # Staff online
                await self.staff_connect()
            elif command == "staff_diconnect":
                # Staff disconnect
                await self.staff_diconnect()
            elif command == "leave":
                # User normal leave the room
                await self.leave_room(content["room"])
            elif command == "send":
                # Message between staff and user
                await self.send_room(content["room"], content["message"])
        except ClientError as e:
            # Catch any errors and send it back
            await self.send_json({"error": e.code})

    async def disconnect(self, code):
        """
        Called when the WebSocket closes for any reason.
        """
        if self.scope["user"].is_authenticated:
            if self.scope["user"].is_staff and self.total_staff == 1:
                # Leave all the rooms we are still in
                for room_id in list(self.rooms):
                    try:
                        await self.leave_room(room_id)
                    except ClientError:
                        pass

                await self.staff_disconnect()
            elif self.scope["user"].is_staff and self.total_staff > 1:
                pass
            else:
                self.leave_room(self.scope["user"].pk)
        else:
            self.leave_room(self.room_id)

    # Command helper methods called by receive_json

    async def join_room(self, room_id):
        """
        Called by receive_json when someone sent a join command.
        """
        group_name = "room-%s" % room_id

        if self.scope["user"].is_authenticated:
            username = self.scope["user"].username
        else:
            username = ''

        self.room_id = room_id

        await self.channel_layer.group_send(
            group_name,
            {
                "type": "chat.join",
                "room_id": room_id,
                "username": username,
            }
        )

        # Store that we're in the room
        self.rooms.add(room_id)

        # Add them to the group so they get room messages
        await self.channel_layer.group_add(
            group_name,
            self.channel_name,
        )

        # Instruct their client to finish opening the room
        await self.send_json({
            "join": str(room_id),
            "staff_connect": self.total_staff > 0 if True else False,
        })

    async def staff_connect(self):
        """
        Called by receive_json when someone sent a staff_connect command.
        """
        for room_id in list(self.rooms):
            try:
                group_name = "room-%s" % room_id
                await self.channel_layer.group_send(
                    group_name,
                    {
                        "type": "chat.staff_connect",
                        "room_id": room_id,
                    }
                )
            except ClientError:
                pass

        self.total_staff = self.total_staff + 1

    async def staff_disconnect(self):
        """
        Called by receive_json when someone sent a staff_disconnect command.
        """
        for room_id in list(self.rooms):
            try:
                group_name = "room-%s" % room_id
                await self.channel_layer.group_send(
                    group_name,
                    {
                        "type": "chat.staff_disconnect",
                        "room_id": room_id,
                    }
                )
            except ClientError:
                pass

        self.total_staff = self.total_staff - 1

    async def leave_room(self, room_id):
        """
        Called by receive_json when someone sent a leave command.
        """
        group_name = "room-%s" % room_id

        if self.scope["user"].is_authenticated:
            username = self.scope["user"].username
        else:
            username = ''

        # Send a leave message if it's turned on
        await self.channel_layer.group_send(
            group_name,
            {
                "type": "chat.leave",
                "room_id": room_id,
                "username": username,
            }
        )

        # Remove that we're in the room
        self.rooms.discard(room_id)
        # Remove them from the group so they no longer get room messages
        await self.channel_layer.group_discard(
            group_name,
            self.channel_name,
        )
        # Instruct their client to finish closing the room
        await self.send_json({
            "leave": str(room_id),
        })

    async def send_room(self, room_id, message):
        """
        Called by receive_json when someone sends a message to a room.
        """
        # Check they are in this room
        if room_id not in self.rooms:
            raise ClientError("ROOM_ACCESS_DENIED")

        # Get the room and send to the group about it
        group_name = "room-%s" % room_id

        if self.scope["user"].is_authenticated:
            username = self.scope["user"].username
        else:
            username = ''

        await self.channel_layer.group_send(
            group_name,
            {
                "type": "chat.message",
                "room_id": room_id,
                "username": username,
                "message": message,
            }
        )

    # Handlers for messages sent over the channel layer

    # These helper methods are named by the types we send - so
    # chat.join becomes chat_join
    async def chat_join(self, event):
        """
        Called when someone has joined our chat.
        """
        # Send a message down to the client
        await self.send_json(
            {
                "msg_type": "chat_join",
                "room": event["room_id"],
                "username": event["username"],
            },
        )

    async def chat_leave(self, event):
        """
        Called when someone has left our chat.
        """
        # Send a message down to the client
        await self.send_json(
            {
                "msg_type": "chat_leave",
                "room": event["room_id"],
                "username": event["username"],
            },
        )

    async def chat_message(self, event):
        """
        Called when someone has messaged our chat.
        """
        # Send a message down to the client
        await self.send_json(
            {
                "msg_type": "chat_message",
                "room": event["room_id"],
                "username": event["username"],
                "message": event["message"],
            },
        )

    async def chat_staff_connect(self, event):
        """
        Called when someone has staff joined our chat.
        """
        await self.send_json(
            {
                "msg_type": "chat_staff_connect",
                "room": event["room_id"],
            },
        )

    async def chat_staff_disconnect(self, event):
        """
        Called when someone has staff leave our chat.
        """
        await self.send_json(
            {
                "msg_type": "chat_staff_disconnect",
                "room": event["room_id"],
            },
        )

最后,我想了解一下这是我进行员工与用户之间聊天的正确方法。

谢谢!

0 个答案:

没有答案