diff --git a/src/langbot/libs/wecom_api/api.py b/src/langbot/libs/wecom_api/api.py index c3f1b76a..9e911a80 100644 --- a/src/langbot/libs/wecom_api/api.py +++ b/src/langbot/libs/wecom_api/api.py @@ -4,6 +4,7 @@ import base64 import binascii import httpx import traceback +from urllib.parse import quote from quart import Quart import xml.etree.ElementTree as ET from typing import Callable, Dict, Any @@ -67,6 +68,31 @@ class WecomClient: await self.logger.error(f'获取accesstoken失败:{response.json()}') raise Exception(f'未获取access token: {data}') + async def get_user_info(self, userid: str) -> dict: + """ + Get user information by user ID using the contacts secret. + + Args: + userid: The user ID to look up. + + Returns: + dict: User information including 'name' field. + """ + if not await self.check_access_token_for_contacts(): + self.access_token_for_contacts = await self.get_access_token(self.secret_for_contacts) + + url = self.base_url + '/user/get?access_token=' + self.access_token_for_contacts + '&userid=' + quote(userid) + async with httpx.AsyncClient() as client: + response = await client.get(url) + data = response.json() + if data.get('errcode') == 40014 or data.get('errcode') == 42001: + self.access_token_for_contacts = await self.get_access_token(self.secret_for_contacts) + return await self.get_user_info(userid) + if data.get('errcode', 0) != 0: + await self.logger.error(f'获取用户信息失败:{data}') + return {} + return data + async def get_users(self): if not self.check_access_token_for_contacts(): self.access_token_for_contacts = await self.get_access_token(self.secret_for_contacts) diff --git a/src/langbot/pkg/platform/sources/wecom.py b/src/langbot/pkg/platform/sources/wecom.py index 7bed676f..777118d7 100644 --- a/src/langbot/pkg/platform/sources/wecom.py +++ b/src/langbot/pkg/platform/sources/wecom.py @@ -163,22 +163,33 @@ class WecomEventConverter(abstract_platform_adapter.AbstractEventConverter): return wecom_event @staticmethod - async def target2yiri(event: WecomEvent): + async def target2yiri(event: WecomEvent, bot: WecomClient = None): """ 将 WecomEvent 转换为平台的 FriendMessage 对象。 Args: event (WecomEvent): 企业微信事件。 + bot (WecomClient): 企业微信客户端,用于获取用户信息。 Returns: platform_events.FriendMessage: 转换后的 FriendMessage 对象。 """ + # Try to get the user's real name from the WeCom API + nickname = str(event.user_id) + if bot and event.user_id: + try: + user_info = await bot.get_user_info(event.user_id) + if user_info and user_info.get('name'): + nickname = user_info.get('name') + except Exception: + pass # Fall back to user_id as nickname + # 转换消息链 if event.type == 'text': yiri_chain = await WecomMessageConverter.target2yiri(event.message, event.message_id) friend = platform_entities.Friend( id=f'u{event.user_id}', - nickname=str(event.agent_id), + nickname=nickname, remark='', ) @@ -186,7 +197,7 @@ class WecomEventConverter(abstract_platform_adapter.AbstractEventConverter): elif event.type == 'image': friend = platform_entities.Friend( id=f'u{event.user_id}', - nickname=str(event.agent_id), + nickname=nickname, remark='', ) @@ -287,7 +298,7 @@ class WecomAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): async def on_message(event: WecomEvent): self.bot_account_id = event.receiver_id try: - return await callback(await self.event_converter.target2yiri(event), self) + return await callback(await self.event_converter.target2yiri(event, self.bot), self) except Exception: await self.logger.error(f'Error in wecom callback: {traceback.format_exc()}')