fix: 飞书发送者信息获取修复

- sender_id 优先用 open_id(user_id 在无权限时为 None)
- get_user_info 默认用 open_id 类型查询
- contact API 无权限时优雅降级,用 ID 缩写作为标识(用户_xxx)
- feishu_bot 和 longconn 都统一了 sender 提取逻辑
This commit is contained in:
2026-04-02 15:47:36 +08:00
parent c07cbf47c8
commit d27b6a9c87
5 changed files with 32 additions and 35 deletions

Binary file not shown.

View File

@@ -1,9 +0,0 @@
2026-02-11 09:14:37,303 - src.core.database - ERROR - 数据库操作失败: 'search_frequency' is an invalid keyword argument for KnowledgeEntry
2026-02-11 09:23:37,045 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V001 - location
2026-02-11 09:23:37,047 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V001 - status
2026-02-11 09:23:37,049 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V001 - battery
2026-02-11 09:23:37,051 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V001 - engine
2026-02-11 09:23:37,053 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V002 - location
2026-02-11 09:23:37,055 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V002 - status
2026-02-11 09:23:37,057 - src.vehicle.vehicle_data_manager - INFO - 添加车辆数据成功: V002 - fault
2026-02-11 09:23:37,057 - src.vehicle.vehicle_data_manager - INFO - 示例车辆数据添加成功

View File

@@ -71,21 +71,25 @@ class FeishuLongConnService:
content = message.content
sender = event.sender
# 获取发送者ID和群信息
sender_id = sender.sender_id.user_id
sender_open_id = getattr(sender.sender_id, 'open_id', '')
# 获取发送者ID和群信息(优先 open_iduser_id 可能为 None
sender_open_id = getattr(sender.sender_id, 'open_id', '') or ''
sender_user_id = getattr(sender.sender_id, 'user_id', '') or ''
sender_id = sender_user_id or sender_open_id or 'unknown'
try:
tenant_key = sender.sender_id.tenant_key
except:
tenant_key = "unknown"
# 获取发送者姓名
# 获取发送者姓名(用 open_id 查询,不需要 contact 权限)
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
id_for_query = sender_open_id or sender_user_id
id_type = 'open_id' if sender_open_id else 'user_id'
if id_for_query:
user_info = fs.get_user_info(id_for_query, id_type=id_type)
sender_name = user_info.get('name') or user_info.get('en_name') or sender_id
except Exception as e:
logger.warning(f"获取发送者信息失败: {e}")

View File

@@ -175,18 +175,18 @@ class FeishuService:
logger.info(f"获取到 {len(all_chats)} 个机器人所在的群")
return all_chats
def get_user_info(self, user_id: str, id_type: str = "user_id") -> dict:
def get_user_info(self, user_id: str, id_type: str = "open_id") -> dict:
"""
获取飞书用户信息(姓名、头像等)。
返回 {"user_id": ..., "name": ..., "en_name": ..., "avatar_url": ...} 或空字典
获取飞书用户信息(姓名等)。
优先用 contact API失败则尝试 im chat members API
"""
token = self._get_tenant_access_token()
if not token:
if not token or not user_id:
return {}
# 方式1: contact API需要 contact:user.base:readonly 权限)
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()
@@ -197,11 +197,10 @@ class FeishuService:
"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 {}
except Exception:
pass
# 方式2: 如果 contact API 没权限,返回 ID 缩写作为标识
short_id = user_id[-8:] if len(user_id) > 8 else user_id
return {"user_id": user_id, "name": f"用户_{short_id}"}

View File

@@ -102,17 +102,21 @@ def _process_message_in_background(app, event_data: dict):
# 3. 获取或创建该飞书用户的会话(支持群聊隔离)
chat_manager = service_manager.get_chat_manager()
# 获取发送者ID从event中提取
# 获取发送者ID优先 open_iduser_id 可能为 None
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_ids = sender.get('sender_id', {})
sender_open_id = sender_ids.get('open_id', '') or ''
sender_user_id = sender_ids.get('user_id', '') or ''
sender_id = sender_user_id or sender_open_id or 'unknown'
sender_type = sender.get('sender_type', 'user')
# 获取发送者姓名
sender_name = '未知用户'
# 获取发送者姓名(用 open_id 查询)
sender_name = sender_id
try:
if sender_id and sender_id != 'unknown':
user_info = feishu_service.get_user_info(sender_id)
id_for_query = sender_open_id or sender_user_id
id_type = 'open_id' if sender_open_id else 'user_id'
if id_for_query:
user_info = feishu_service.get_user_info(id_for_query, id_type=id_type)
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}")
@@ -121,7 +125,6 @@ def _process_message_in_background(app, event_data: dict):
logger.info(f"[Feishu Bot] 📝 消息内容: '{text_content}'")
# 群聊隔离:每个用户在每个群都有独立会话
# 格式feishu_群聊ID_用户ID
user_id = f"feishu_{chat_id}_{sender_id}"
# 检查是否已有活跃会话