我正在开发一个聊天平台,该平台的用户将可以与工作人员聊天。仅当它们已连接时,否则聊天将被禁用。可能有一个或多个工作人员。
我还没有完全理解如何计算相关人员,现在我有一个增加或减少使用者的变量实例(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"],
},
)
最后,我想了解一下这是我进行员工与用户之间聊天的正确方法。
谢谢!