From c07cbf47c83971f3d8c42ca67a994f631c3773fb Mon Sep 17 00:00:00 2001 From: Jeason <1710884619@qq.com> Date: Thu, 2 Apr 2026 15:40:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=A3=9E=E4=B9=A6=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E5=AE=8C=E5=96=84=20=20=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E5=8F=91=E9=80=81=E8=80=85ID=E3=80=81=E5=A7=93=E5=90=8D?= =?UTF-8?q?=E3=80=81=E7=BE=A4=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 同步记录详细来源信息 --- data/tsp_assistant.db | Bin 204800 -> 208896 bytes src/core/models.py | 8 ++--- src/integrations/feishu_longconn_service.py | 27 ++++++++++------- src/integrations/feishu_service.py | 31 ++++++++++++++++++++ src/web/blueprints/feishu_bot.py | 28 +++++++++++++----- 5 files changed, 71 insertions(+), 23 deletions(-) diff --git a/data/tsp_assistant.db b/data/tsp_assistant.db index 2df7fb7a576e60188caac719c6134da2cd2ab573..cec21500cde3bbfe973131472050304076004333 100644 GIT binary patch delta 4048 zcmeHKZ%iBK8Nb&y7znn*2+J~-*>OUbEy207&v&+~YFL!E%hHCfQJ1z$2_dv$T|-x3 zQ^YFcGXa|b#sYFA7!o((kD_AZI0a(Pk z(^Tx={v!s3?)_-sAd3AY+MvyY^(I3szIvicr8!yryI6_gc5#WjBu|S~@5P8cNMGu7 zV&yFQy<(TkN)T4Fm27Kie7g?E31M(7>AS-Bd-*XBcQY#7nW%4QZTeNC;@6F5TACZ) zXl!*j2s3V`Dsi$BHya46!$LX;(qyBol-0J$LgFSnZ6$5yvyHFSxBa5kty5{S8a=Qm z)MLQHR^HOs($ds?zK#z@xmiCqHBd*;w8YA6&b;F$nZ)w2Fm)rj7!Z~xg_SPWu0?w* zEfxo9Hc>X(Lgo6lIIOsdChZp5p7uTeP=gLARJxP8laP|fbnFE^D*u5PeV##CgSI20 z(krWxlrUDOMQV0LkIsL`r7Wy3*q^_SxzHaK>)Jo4EO`-)ueg6lchO`ZaO#`PGpbVT z38tw+jhxQH!re}+0E4uDWI|unW|C)d5QNEQw^BA+{n%bbpaG3J$GG*eNb zF33V1EIWE{6DYAgC=Pj(L7n-f*pHa!b3i|N=3lv>Hj1+2TQil+GU$bZQmoojlN0~7 z!;13Q(@&KkM@|xKK#1BJnzmDRLM~;{fSgE&E5QL{txy+AsbK%H4}Dn;Jpn1T;}E@l zOSF_Zjn>LI6k_<*86d-c^i>8(oU(0zL~{nniNxa6%OTIddH^YqB~6Kd0JotenPsHd za#e*Y*8j8>&EY7ob`N$N(@tv66d%HF7tJWXrF=o<&nML%748cJhITUzFYUtIJ96vC z-fKrVYrcfI>?-243CHaOZGLo28FQKmV|%3(JI>fQwg!9Ii@tb1tAIGjksVOUEl_2% zjB5WGFfMeva$x>@nfi*t?{70 z=hCKWvvrH66yYVaOuO*3m=5N`M)>&~ZuB_X&=}%IV%ri*W|?;T%cWSeN1p?G%ZE%G zMq6qqD?wYfsGiu4qB#vaf2bFIs@#J;#IT2ocI7A9-{d`|G48lkbh=QZp3J`x2>fZc zM_Ugem3a2$`0g7=RhueIZQ~mvmdtWUFP{Ni4fDiCTy{qd+QYti4*vao41Jng3zD{2 zw-9f!79?e%BC z%Pj08O@y7cTOO(4S!THw%>kq=*zG}Q0sZ?-F8V+tdX9Z?6>%F}P$ny3C2WuEPH-Wc z(=NKMqq*yf5*$HcUw3sLHI`r)(S5|J#?+V|E;2Rco6mlpndT;z*Oz*^i?Kw!Kl@sc zyxPeR_9d2sU`-B1!OGA1IDe0DXOj2MCl>lsw+C1TdjYYqF?Lqt%dFa1b26i@AV}wPVxSM z~%gi3|^A)RW97idk0{Pm`;Bru{goA?hh1Ceph_X1OeNEkbt?w z;^j3qy!P%0d;bGP*-L=9>82vxw`>;L^20yFi3h)`JCB8Y^p8Kx+#R>OV#zJ{;m3-q zO4W;)?nSty9n)#t-$O-Mc?AJSyt|B@(kYJ~7B8KIgS45dICWRkqJH+5h61%b|Ox69CRw_yUT^Iay{4J z4NUyn*mz1MgwV9GIx9|afh;J4zkI*URYaH!LS!BUO9hLq^}gZ8CT%C0Ak|06yvm7NTg$a+T6BE&8boqymn h_y%S}pDFel(_hbN?Sj791*ca}Symg(gP#3U@gE$BO=$oC delta 1066 zcmZXTU1(HC6vyY>-OcVz_9MF+^U;)Km8>+Txw$j!O*M&WQ%JiQ zzp#NeJ1f$vLDw}MkVW$pA0;g2LQxcyzWVWC!1!PbeX*tBqfoT7cbk>if%`Cr-}(Q~ zJ?G5K3;)bL|E1=Dj1VH?b58Cf3*^PavlsnDOJY@_1~oLb`1)d3Y%#Y9?EXcV2o`_2 zJJ3@M$DRl5mjP&#c;u1vRWTNGhj^kDn)#JhnEJ4Q+rt){*fqM@~#0 zXWdd1^|5WMcnbLtYUckeOD*|(yC2r+ohpf8Bl*5Sqp>Qm6{5&uBXKV{e)iFJkl=rY zKJ`Doc&De$U2NRmSGA;qXKxeCqToVc)ZbD4mptdocqcu7y9Zrim=)bfLwyzwM^UDW zosN5bCH)4cKs)ghbVD8K#5g7@(`gc0ieVa5*LdnGMAua!hN`nq4+)9x%n5$u8~B)e ze}ornGO2&L=XCoR~oSUYTY}JU!3TM}s z#a9;!a?rDOp-e@iL?h+3@R#OVieO63v-7YtFNM`&Bz8-(e|;kLbh-;DR1ht>9I6=w f88yeTczuYEg 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 {} diff --git a/src/web/blueprints/feishu_bot.py b/src/web/blueprints/feishu_bot.py index 3e721f9..25c638d 100644 --- a/src/web/blueprints/feishu_bot.py +++ b/src/web/blueprints/feishu_bot.py @@ -103,14 +103,27 @@ def _process_message_in_background(app, event_data: dict): chat_manager = service_manager.get_chat_manager() # 获取发送者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 user_id = f"feishu_{chat_id}_{sender_id}" - logger.info(f"[Feishu Bot] 会话用户标识: {user_id}") - # 检查是否已有活跃会话 active_sessions = chat_manager.get_active_sessions() session_id = None @@ -126,17 +139,16 @@ def _process_message_in_background(app, event_data: dict): # 如果没有会话,创建新会话 if not session_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. 调用实时对话接口处理消息 - logger.info(f"[Feishu Bot] 调用实时对话接口处理消息...") response_data = chat_manager.process_message( session_id=session_id, user_message=text_content, - ip_address=None, - invocation_method="feishu_bot" + ip_address=f"feishu:{sender_id}:{sender_name}", + 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. 提取回复并发送 if response_data.get("success"):