148 lines
4.3 KiB
Python
148 lines
4.3 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""
|
|||
|
|
Webhook 推送工具
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import requests
|
|||
|
|
import logging
|
|||
|
|
from typing import Dict, List, Optional
|
|||
|
|
from .models import Instance, MeetingInstanceMap
|
|||
|
|
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def push_message_to_instances(meeting_id: str, message: Dict, target_agent_ids: Optional[List[str]] = None):
|
|||
|
|
"""
|
|||
|
|
推送消息到相关实例
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
meeting_id: 会议 ID
|
|||
|
|
message: 消息数据(字典)
|
|||
|
|
target_agent_ids: 目标 Agent ID 列表(None 表示广播给所有)
|
|||
|
|
"""
|
|||
|
|
# 找到参与该会议的实例
|
|||
|
|
maps = MeetingInstanceMap.objects.filter(
|
|||
|
|
meeting_id=meeting_id,
|
|||
|
|
left_at__isnull=True,
|
|||
|
|
instance__is_active=True,
|
|||
|
|
instance__webhook_enabled=True
|
|||
|
|
).select_related('instance')
|
|||
|
|
|
|||
|
|
for mapping in maps:
|
|||
|
|
instance = mapping.instance
|
|||
|
|
|
|||
|
|
# 确定要推送的 Agent
|
|||
|
|
if target_agent_ids:
|
|||
|
|
# 只推送给指定的 Agent
|
|||
|
|
agents_to_notify = [aid for aid in mapping.agent_ids if aid in target_agent_ids]
|
|||
|
|
else:
|
|||
|
|
# 广播给所有
|
|||
|
|
agents_to_notify = mapping.agent_ids
|
|||
|
|
|
|||
|
|
if not agents_to_notify:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# 构建推送数据
|
|||
|
|
payload = {
|
|||
|
|
'event': 'new_message',
|
|||
|
|
'meeting_id': str(meeting_id),
|
|||
|
|
'message': message,
|
|||
|
|
'target_agents': agents_to_notify,
|
|||
|
|
'timestamp': message.get('created_at', '')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 发送 webhook
|
|||
|
|
try:
|
|||
|
|
response = requests.post(
|
|||
|
|
instance.webhook_url,
|
|||
|
|
json=payload,
|
|||
|
|
headers={'Content-Type': 'application/json'},
|
|||
|
|
timeout=5
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if response.status_code == 200:
|
|||
|
|
logger.info(f"✅ Webhook 推送成功:{instance.instance_id} -> {agents_to_notify}")
|
|||
|
|
else:
|
|||
|
|
logger.warning(f"⚠️ Webhook 推送失败:{instance.instance_id}, status={response.status_code}")
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"❌ Webhook 推送异常:{instance.instance_id}, error={e}")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def register_instance(instance_id: str, instance_name: str, agent_ids: List[str], webhook_url: str) -> Instance:
|
|||
|
|
"""
|
|||
|
|
注册或更新实例
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
instance_id: 实例 ID
|
|||
|
|
instance_name: 实例名称
|
|||
|
|
agent_ids: Agent ID 列表
|
|||
|
|
webhook_url: Webhook URL
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
Instance: 实例对象
|
|||
|
|
"""
|
|||
|
|
instance, created = Instance.objects.update_or_create(
|
|||
|
|
instance_id=instance_id,
|
|||
|
|
defaults={
|
|||
|
|
'instance_name': instance_name,
|
|||
|
|
'agent_ids': agent_ids,
|
|||
|
|
'webhook_url': webhook_url,
|
|||
|
|
'webhook_enabled': True,
|
|||
|
|
'is_active': True
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if created:
|
|||
|
|
logger.info(f"✅ 新实例注册:{instance_id} ({instance_name})")
|
|||
|
|
else:
|
|||
|
|
logger.info(f"🔄 实例更新:{instance_id}")
|
|||
|
|
|
|||
|
|
return instance
|
|||
|
|
|
|||
|
|
|
|||
|
|
def join_meeting(instance_id: str, meeting_id: str, agent_ids: List[str]):
|
|||
|
|
"""
|
|||
|
|
实例加入会议
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
instance_id: 实例 ID
|
|||
|
|
meeting_id: 会议 ID
|
|||
|
|
agent_ids: 参与的 Agent ID 列表
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
instance = Instance.objects.get(instance_id=instance_id)
|
|||
|
|
|
|||
|
|
MeetingInstanceMap.objects.update_or_create(
|
|||
|
|
meeting_id=meeting_id,
|
|||
|
|
instance=instance,
|
|||
|
|
defaults={'agent_ids': agent_ids, 'left_at': None}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
logger.info(f"✅ 实例 {instance_id} 加入会议 {meeting_id}, Agents: {agent_ids}")
|
|||
|
|
except Instance.DoesNotExist:
|
|||
|
|
logger.error(f"❌ 实例不存在:{instance_id}")
|
|||
|
|
raise
|
|||
|
|
|
|||
|
|
|
|||
|
|
def leave_meeting(instance_id: str, meeting_id: str):
|
|||
|
|
"""
|
|||
|
|
实例离开会议
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
instance_id: 实例 ID
|
|||
|
|
meeting_id: 会议 ID
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
instance = Instance.objects.get(instance_id=instance_id)
|
|||
|
|
mapping = MeetingInstanceMap.objects.get(meeting_id=meeting_id, instance=instance)
|
|||
|
|
mapping.left_at = timezone.now()
|
|||
|
|
mapping.save()
|
|||
|
|
|
|||
|
|
logger.info(f"✅ 实例 {instance_id} 离开会议 {meeting_id}")
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.warning(f"⚠️ 离开会议失败:{e}")
|
|||
|
|
|
|||
|
|
|
|||
|
|
# 导入 timezone
|
|||
|
|
from django.utils import timezone
|