#!/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