fix: resolve Feishu cross-app notification routing bug

Implement per-app open_id storage via user_feishu_open_ids table with
union_id-based cross-app user identification. WS handlers now auto-capture
open_id+union_id and resolve/associate user accounts. Schedule notifications
route through the correct bot's open_id instead of always falling back to 苹果.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
renjianbo
2026-05-06 00:36:40 +08:00
parent 3dd098482e
commit f33bc461ff
11 changed files with 503 additions and 24 deletions

View File

@@ -70,6 +70,21 @@ def _get_sender_open_id(data) -> Optional[str]:
return None
def _get_sender_union_id(data) -> Optional[str]:
"""从 Feishu 消息事件中提取发送者 union_id跨应用唯一"""
try:
ev = data.event
sender = getattr(ev, "sender", None)
if not sender:
return None
sender_id = getattr(sender, "sender_id", None)
if not sender_id:
return None
return getattr(sender_id, "union_id", None)
except Exception:
return None
def _get_chat_type(data) -> str:
"""获取聊天类型。"""
try:
@@ -103,6 +118,7 @@ def _reply_card(open_id: str, title: str, content: str, status: str = "info"):
async def _handle_message_async(data):
"""异步处理飞书消息。"""
open_id = _get_sender_open_id(data)
union_id = _get_sender_union_id(data)
chat_type = _get_chat_type(data)
text = _get_message_text(data)
@@ -128,11 +144,21 @@ async def _handle_message_async(data):
from app.core.database import SessionLocal
from app.models.user import User
from app.models.agent import Agent
from app.services.feishu_open_id_service import resolve_user_and_save
db: Optional[Session] = None
try:
db = SessionLocal()
# 自动保存/关联此应用的 open_id跨应用识别
resolved_uid = resolve_user_and_save(
db, app_id=settings.FEISHU_APP_ID or "",
open_id=open_id, union_id=union_id,
)
user = db.query(User).filter(User.feishu_open_id == open_id).first()
if not user and resolved_uid:
user = db.query(User).filter(User.id == resolved_uid).first()
if not user:
_reply_to_feishu(open_id, "你的账号未绑定平台用户,请先在平台绑定飞书。")
return