Files

237 lines
7.9 KiB
Python

from rest_framework import viewsets, status, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from django.utils import timezone
from datetime import timedelta
from .models import Meeting, Participant, Message
from .serializers import MeetingSerializer, ParticipantSerializer, MessageSerializer
from django.contrib.auth import get_user_model
from django.shortcuts import get_object_or_404
import uuid
User = get_user_model()
class MeetingViewSet(viewsets.ModelViewSet):
"""会议室视图集"""
queryset = Meeting.objects.all()
serializer_class = MeetingSerializer
permission_classes = [] # 临时开放所有权限
def get_queryset(self):
return Meeting.objects.all().order_by('-created_at')
def create(self, request, *args, **kwargs):
"""创建会议"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
# 使用第一个用户作为 host
host = User.objects.first()
meeting = serializer.save(host=host)
# 设置 1 小时过期时间
meeting.expires_at = timezone.now() + timedelta(hours=1)
meeting.save()
# 创建主持人参会记录
Participant.objects.create(
meeting=meeting,
user=host,
agent_type='human',
nickname=host.username,
is_host=True
)
# 处理随行龙虾
agent_ids = request.data.get('agent_ids', [])
for agent_id in agent_ids:
Participant.objects.create(
meeting=meeting,
agent_type='openclaw',
agent_id=agent_id,
agent_name='Agent',
agent_emoji='🤖',
nickname=f'Agent {agent_id}',
is_host=False
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
@action(detail=True, methods=['post'])
def join(self, request, pk=None):
"""加入会议(支持批量加入)"""
meeting = self.get_object()
# 检查会议是否过期
if meeting.expires_at and timezone.now() > meeting.expires_at:
# 过期会议,清空坐席
meeting.participants.all().delete()
return Response(
{'error': '会议已过期,坐席已清空'},
status=status.HTTP_400_BAD_REQUEST
)
if meeting.status == 'ended':
return Response(
{'error': '会议已结束'},
status=status.HTTP_400_BAD_REQUEST
)
invite_code = request.data.get('invite_code')
if invite_code != meeting.invite_code:
return Response(
{'error': '邀请码错误'},
status=status.HTTP_400_BAD_REQUEST
)
# 获取要加入的龙虾 ID 列表
agent_ids = request.data.get('agent_ids', [])
# 获取当前用户
user = User.objects.first() # 临时使用第一个用户
# 检查用户是否已加入
existing = Participant.objects.filter(
meeting=meeting,
user=user,
left_at__isnull=True
).first()
if not existing:
# 用户加入会议
Participant.objects.create(
meeting=meeting,
user=user,
agent_type='human',
nickname=user.username if user else '用户',
is_host=False
)
# 随行龙虾加入会议
joined_agents = []
for agent_id in agent_ids:
# 检查是否已存在
exists = Participant.objects.filter(
meeting=meeting,
agent_id=agent_id,
left_at__isnull=True
).first()
if not exists:
participant = Participant.objects.create(
meeting=meeting,
agent_type='openclaw',
agent_id=agent_id,
agent_name='Agent',
agent_emoji='🤖',
nickname=f'Agent {agent_id}',
is_host=False
)
joined_agents.append(ParticipantSerializer(participant).data)
# 返回所有参会者
participants = Participant.objects.filter(
meeting=meeting,
left_at__isnull=True
)
return Response({
'message': '加入成功',
'participants': ParticipantSerializer(participants, many=True).data,
'joined_agents': joined_agents
})
@action(detail=True, methods=['post'])
def send_message(self, request, pk=None):
"""发送消息"""
meeting = self.get_object()
# 获取或创建参会者
participant = Participant.objects.filter(
meeting=meeting,
left_at__isnull=True
).first()
if not participant:
host = meeting.host
participant = Participant.objects.create(
meeting=meeting,
user=host,
agent_type='human',
nickname=host.username
)
content = request.data.get('content')
if not content:
return Response(
{'error': '消息内容不能为空'},
status=status.HTTP_400_BAD_REQUEST
)
message = Message.objects.create(
meeting=meeting,
sender=participant,
content=content,
is_broadcast=request.data.get('is_broadcast', True),
requires_response=request.data.get('requires_response', False)
)
# 如果是@消息,触发龙虾自动回复
if content.startswith('@') and message.requires_response:
self.auto_reply(message)
return Response(MessageSerializer(message).data, status=status.HTTP_201_CREATED)
def auto_reply(self, message):
"""龙虾自动回复"""
# 获取会议中所有龙虾
agents = Participant.objects.filter(
meeting=message.meeting,
agent_type='openclaw',
left_at__isnull=True
)
# 每个龙虾都有 30% 概率回复
import random
for agent in agents:
if random.random() < 0.3: # 30% 概率
replies = [
'收到!',
'明白了~',
'好的,我会处理',
'👌',
'嗯嗯',
'在的!',
]
import random
reply_content = random.choice(replies)
Message.objects.create(
meeting=message.meeting,
sender=agent,
content=reply_content,
is_broadcast=True,
in_reply_to=message
)
@action(detail=True, methods=['get'])
def messages(self, request, pk=None):
"""获取消息"""
meeting = self.get_object()
last_id = request.query_params.get('last_id', 0)
messages = meeting.messages.filter(id__gt=last_id).select_related('sender')
serializer = MessageSerializer(messages, many=True)
return Response({'messages': serializer.data})
@action(detail=True, methods=['get'])
def participants(self, request, pk=None):
"""获取参会者列表"""
meeting = self.get_object()
participants = meeting.participants.filter(left_at__isnull=True)
serializer = ParticipantSerializer(participants, many=True)
return Response(serializer.data)