import os import json import logging import asyncio import sys from typing import Optional # 将项目根目录添加到 python 路径,确保可以作为独立脚本运行 PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", "..")) if PROJECT_ROOT not in sys.path: sys.path.append(PROJECT_ROOT) from agent.tools.builtin.feishu.feishu_client import FeishuClient, FeishuMessageEvent, FeishuDomain from agent.tools.builtin.feishu.chat import ( FEISHU_APP_ID, FEISHU_APP_SECRET, get_contact_by_id, load_chat_history, save_chat_history, update_unread_count, _convert_feishu_msg_to_openai_content ) # 配置日志 logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger("FeishuWebsocket") class FeishuMessageListener: def __init__(self): self.client = FeishuClient( app_id=FEISHU_APP_ID, app_secret=FEISHU_APP_SECRET, domain=FeishuDomain.FEISHU ) def handle_incoming_message(self, event: FeishuMessageEvent): """处理收到的飞书消息事件""" # 1. 识别联系人 # 优先使用 sender_open_id 匹配联系人,如果没有则尝试 chat_id contact = get_contact_by_id(event.sender_open_id) or get_contact_by_id(event.chat_id) if not contact: logger.warning(f"收到未知发送者的消息: open_id={event.sender_open_id}, chat_id={event.chat_id}") # 对于未知联系人,我们可以选择忽略,或者记录到 'unknown' 分类 contact = {"name": "未知联系人", "open_id": event.sender_open_id} contact_name = contact.get("name") logger.info(f"收到来自 [{contact_name}] 的消息: {event.content[:50]}...") # 2. 转换为 OpenAI 多模态格式 # 构造一个类似 get_message_list 返回的字典对象,以便重用转换逻辑 msg_dict = { "message_id": event.message_id, "content_type": event.content_type, "content": event.content, # 对于 text, websocket 传来的已经是解析后的字符串;对于 image 则是原始 JSON 字符串 "sender_id": event.sender_open_id, "sender_type": "user" # WebSocket 收到的一般是用户消息,除非是机器人自己的回显(通常会过滤) } openai_content = _convert_feishu_msg_to_openai_content(self.client, msg_dict) # 3. 维护聊天记录 history = load_chat_history(contact_name) new_message = { "role": "user", "message_id": event.message_id, "timestamp": os.path.getmtime(os.path.join(os.path.dirname(__file__), "chat.py")), # 简单模拟一个时间戳,实际应使用事件时间 "content": openai_content } history.append(new_message) save_chat_history(contact_name, history) # 4. 更新未读计数 update_unread_count(contact_name, increment=1) logger.info(f"已更新 [{contact_name}] 的聊天记录并增加未读计数") def start(self): """启动监听""" logger.info("正在启动飞书消息实时监听...") try: self.client.start_websocket( on_message=self.handle_incoming_message, blocking=True ) except KeyboardInterrupt: logger.info("监听已停止") except Exception as e: logger.error(f"监听过程中出现错误: {e}") if __name__ == "__main__": listener = FeishuMessageListener() listener.start()