feat: 飞书消息记录完善 记录发送者ID、姓名、群信息
- FeishuService 新增 get_user_info() 根据 user_id 获取飞书用户姓名 - feishu_bot.py 处理消息时获取发送者姓名,日志格式改为:发送者=姓名(ID), 群=chat_id, 类型=群聊/私聊, 租户=xxx - feishu_longconn_service.py 同样获取发送者姓名并记录 - Conversation.ip_address 存储 feishu:user_id:sender_name(扩大字段到200字符) - Conversation.invocation_method 存储 feishu_bot(group) / feishu_longconn(p2p) 等详细来源 - ChatSession.source 同步记录详细来源信息
This commit is contained in:
Binary file not shown.
@@ -103,8 +103,8 @@ class ChatSession(Base):
|
|||||||
title = Column(String(200), nullable=True) # 会话标题(取首条消息摘要)
|
title = Column(String(200), nullable=True) # 会话标题(取首条消息摘要)
|
||||||
status = Column(String(20), default="active") # active, ended
|
status = Column(String(20), default="active") # active, ended
|
||||||
message_count = Column(Integer, default=0) # 消息轮数
|
message_count = Column(Integer, default=0) # 消息轮数
|
||||||
source = Column(String(50), nullable=True) # 来源:websocket, api, feishu
|
source = Column(String(100), nullable=True) # 来源:websocket, api, feishu_bot(group) 等
|
||||||
ip_address = Column(String(45), nullable=True)
|
ip_address = Column(String(200), nullable=True) # IP地址或来源标识
|
||||||
created_at = Column(DateTime, default=datetime.now)
|
created_at = Column(DateTime, default=datetime.now)
|
||||||
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
||||||
ended_at = Column(DateTime, nullable=True)
|
ended_at = Column(DateTime, nullable=True)
|
||||||
@@ -143,8 +143,8 @@ class Conversation(Base):
|
|||||||
confidence_score = Column(Float)
|
confidence_score = Column(Float)
|
||||||
knowledge_used = Column(Text) # 使用的知识库条目
|
knowledge_used = Column(Text) # 使用的知识库条目
|
||||||
response_time = Column(Float) # 响应时间(秒)
|
response_time = Column(Float) # 响应时间(秒)
|
||||||
ip_address = Column(String(45), nullable=True) # IP地址
|
ip_address = Column(String(200), nullable=True) # IP地址或来源标识(如 feishu:uid:name)
|
||||||
invocation_method = Column(String(50), nullable=True) # 调用方式(websocket, api等)
|
invocation_method = Column(String(100), nullable=True) # 调用方式(websocket, api, feishu_bot(group) 等)
|
||||||
|
|
||||||
# 系统优化字段
|
# 系统优化字段
|
||||||
processing_time = Column(Float) # 处理时间
|
processing_time = Column(Float) # 处理时间
|
||||||
|
|||||||
@@ -73,19 +73,25 @@ class FeishuLongConnService:
|
|||||||
|
|
||||||
# 获取发送者ID和群信息
|
# 获取发送者ID和群信息
|
||||||
sender_id = sender.sender_id.user_id
|
sender_id = sender.sender_id.user_id
|
||||||
|
sender_open_id = getattr(sender.sender_id, 'open_id', '')
|
||||||
try:
|
try:
|
||||||
tenant_key = sender.sender_id.tenant_key
|
tenant_key = sender.sender_id.tenant_key
|
||||||
except:
|
except:
|
||||||
tenant_key = "unknown"
|
tenant_key = "unknown"
|
||||||
|
|
||||||
|
# 获取发送者姓名
|
||||||
|
sender_name = sender_id
|
||||||
|
try:
|
||||||
|
from src.integrations.feishu_service import FeishuService
|
||||||
|
fs = FeishuService()
|
||||||
|
user_info = fs.get_user_info(sender_id)
|
||||||
|
sender_name = user_info.get('name') or user_info.get('en_name') or sender_id
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"获取发送者信息失败: {e}")
|
||||||
|
|
||||||
# 详细日志记录
|
# 详细日志记录
|
||||||
logger.info(f"📋 消息详情 [长连接]:")
|
chat_type_desc = '群聊(group)' if chat_type == 'group' else '私聊(p2p)' if chat_type == 'p2p' else chat_type
|
||||||
logger.info(f" - 消息ID: {message_id}")
|
logger.info(f"📨 [长连接] 发送者={sender_name}({sender_id}), 群={chat_id}, 类型={chat_type_desc}, 消息ID={message_id}")
|
||||||
logger.info(f" - 会话类型: {'群聊(group)' if chat_type == 'group' else '私聊(p2p)' if chat_type == 'p2p' else chat_type}")
|
|
||||||
logger.info(f" - 会话ID: {chat_id}")
|
|
||||||
logger.info(f" - 发送者ID: {sender_id}")
|
|
||||||
logger.info(f" - 租户Key: {tenant_key}")
|
|
||||||
logger.info(f" - 消息类型: {message_type}")
|
|
||||||
|
|
||||||
# 消息去重检查
|
# 消息去重检查
|
||||||
if cache_manager.check_and_set_message_processed(message_id):
|
if cache_manager.check_and_set_message_processed(message_id):
|
||||||
@@ -163,15 +169,14 @@ class FeishuLongConnService:
|
|||||||
work_order_id=None,
|
work_order_id=None,
|
||||||
tenant_id=tenant_id
|
tenant_id=tenant_id
|
||||||
)
|
)
|
||||||
logger.info(f"🆕 创建新会话: {session_id} (租户: {tenant_id})")
|
logger.info(f"🆕 创建新会话: {session_id}, 用户={sender_name}({sender_id}), 租户={tenant_id}")
|
||||||
|
|
||||||
# 调用实时对话接口处理消息
|
# 调用实时对话接口处理消息
|
||||||
logger.info(f"🤖 调用 TSP Assistant 处理消息...")
|
|
||||||
response_data = chat_manager.process_message(
|
response_data = chat_manager.process_message(
|
||||||
session_id=session_id,
|
session_id=session_id,
|
||||||
user_message=text_content,
|
user_message=text_content,
|
||||||
ip_address=f"Feishu:{sender_id}",
|
ip_address=f"feishu:{sender_id}:{sender_name}",
|
||||||
invocation_method=f"Feishu({chat_type})"
|
invocation_method=f"feishu_longconn({chat_type})"
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(f"📊 处理结果: {response_data.get('success')}")
|
logger.info(f"📊 处理结果: {response_data.get('success')}")
|
||||||
|
|||||||
@@ -174,3 +174,34 @@ class FeishuService:
|
|||||||
|
|
||||||
logger.info(f"获取到 {len(all_chats)} 个机器人所在的群")
|
logger.info(f"获取到 {len(all_chats)} 个机器人所在的群")
|
||||||
return all_chats
|
return all_chats
|
||||||
|
|
||||||
|
def get_user_info(self, user_id: str, id_type: str = "user_id") -> dict:
|
||||||
|
"""
|
||||||
|
获取飞书用户信息(姓名、头像等)。
|
||||||
|
返回 {"user_id": ..., "name": ..., "en_name": ..., "avatar_url": ...} 或空字典。
|
||||||
|
"""
|
||||||
|
token = self._get_tenant_access_token()
|
||||||
|
if not token:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
url = f"{self.BASE_URL}/contact/v3/users/{user_id}?user_id_type={id_type}"
|
||||||
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
data = response.json()
|
||||||
|
if data.get("code") == 0:
|
||||||
|
user = data.get("data", {}).get("user", {})
|
||||||
|
return {
|
||||||
|
"user_id": user.get("user_id", ""),
|
||||||
|
"open_id": user.get("open_id", ""),
|
||||||
|
"name": user.get("name", ""),
|
||||||
|
"en_name": user.get("en_name", ""),
|
||||||
|
"avatar_url": user.get("avatar", {}).get("avatar_72", ""),
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
logger.warning(f"获取用户信息失败: {data.get('msg')} (user_id={user_id})")
|
||||||
|
return {}
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"获取用户信息异常: {e}")
|
||||||
|
return {}
|
||||||
|
|||||||
@@ -103,14 +103,27 @@ def _process_message_in_background(app, event_data: dict):
|
|||||||
chat_manager = service_manager.get_chat_manager()
|
chat_manager = service_manager.get_chat_manager()
|
||||||
|
|
||||||
# 获取发送者ID(从event中提取)
|
# 获取发送者ID(从event中提取)
|
||||||
sender_id = event.get('sender', {}).get('sender_id', {}).get('user_id', 'unknown')
|
sender = event.get('sender', {})
|
||||||
|
sender_id = sender.get('sender_id', {}).get('user_id', 'unknown')
|
||||||
|
sender_open_id = sender.get('sender_id', {}).get('open_id', '')
|
||||||
|
sender_type = sender.get('sender_type', 'user')
|
||||||
|
|
||||||
|
# 获取发送者姓名
|
||||||
|
sender_name = '未知用户'
|
||||||
|
try:
|
||||||
|
if sender_id and sender_id != 'unknown':
|
||||||
|
user_info = feishu_service.get_user_info(sender_id)
|
||||||
|
sender_name = user_info.get('name') or user_info.get('en_name') or sender_id
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"[Feishu Bot] 获取发送者信息失败: {e}")
|
||||||
|
|
||||||
|
logger.info(f"[Feishu Bot] 📨 消息详情: 发送者={sender_name}({sender_id}), 群={chat_id}, 类型={chat_type_desc}, 租户={tenant_id}, 消息ID={message_id}")
|
||||||
|
logger.info(f"[Feishu Bot] 📝 消息内容: '{text_content}'")
|
||||||
|
|
||||||
# 群聊隔离:每个用户在每个群都有独立会话
|
# 群聊隔离:每个用户在每个群都有独立会话
|
||||||
# 格式:feishu_群聊ID_用户ID
|
# 格式:feishu_群聊ID_用户ID
|
||||||
user_id = f"feishu_{chat_id}_{sender_id}"
|
user_id = f"feishu_{chat_id}_{sender_id}"
|
||||||
|
|
||||||
logger.info(f"[Feishu Bot] 会话用户标识: {user_id}")
|
|
||||||
|
|
||||||
# 检查是否已有活跃会话
|
# 检查是否已有活跃会话
|
||||||
active_sessions = chat_manager.get_active_sessions()
|
active_sessions = chat_manager.get_active_sessions()
|
||||||
session_id = None
|
session_id = None
|
||||||
@@ -126,17 +139,16 @@ def _process_message_in_background(app, event_data: dict):
|
|||||||
# 如果没有会话,创建新会话
|
# 如果没有会话,创建新会话
|
||||||
if not session_id:
|
if not session_id:
|
||||||
session_id = chat_manager.create_session(user_id=user_id, work_order_id=None, tenant_id=tenant_id)
|
session_id = chat_manager.create_session(user_id=user_id, work_order_id=None, tenant_id=tenant_id)
|
||||||
logger.info(f"[Feishu Bot] 为用户 {sender_id} 在群聊 {chat_id} 创建新会话: {session_id} (租户: {tenant_id})")
|
logger.info(f"[Feishu Bot] 新建会话: {session_id}, 用户={sender_name}({sender_id}), 租户={tenant_id}")
|
||||||
|
|
||||||
# 4. 调用实时对话接口处理消息
|
# 4. 调用实时对话接口处理消息
|
||||||
logger.info(f"[Feishu Bot] 调用实时对话接口处理消息...")
|
|
||||||
response_data = chat_manager.process_message(
|
response_data = chat_manager.process_message(
|
||||||
session_id=session_id,
|
session_id=session_id,
|
||||||
user_message=text_content,
|
user_message=text_content,
|
||||||
ip_address=None,
|
ip_address=f"feishu:{sender_id}:{sender_name}",
|
||||||
invocation_method="feishu_bot"
|
invocation_method=f"feishu_bot({chat_type})"
|
||||||
)
|
)
|
||||||
logger.info(f"[Feishu Bot] 实时对话接口返回结果: {response_data}")
|
logger.info(f"[Feishu Bot] 处理结果: success={response_data.get('success')}, 用户={sender_name}")
|
||||||
|
|
||||||
# 5. 提取回复并发送
|
# 5. 提取回复并发送
|
||||||
if response_data.get("success"):
|
if response_data.get("success"):
|
||||||
|
|||||||
Reference in New Issue
Block a user