diff --git a/app/core/wecomclient.py b/app/core/wecomclient.py index 9823b9c..39dd1e4 100644 --- a/app/core/wecomclient.py +++ b/app/core/wecomclient.py @@ -181,6 +181,36 @@ class WecomClient: logger.error(f"获取外部联系人信息异常: {str(e)}") return None + async def get_internal_user_info(self, user_id: str) -> Optional[Dict[str, Any]]: + """获取企业内部成员信息 + + Args: + user_id: 企业成员userid + + Returns: + Dict: 企业成员信息 + """ + try: + access_token = await self.get_access_token() + if not access_token: + logger.error("获取access_token失败") + return None + + url = f"https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token={access_token}&userid={user_id}" + + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + result = await response.json() + if result.get("errcode") == 0: + logger.info(f"获取内部成员信息成功: {result}") + return result + else: + logger.error(f"获取内部成员信息失败: {result}") + return None + except Exception as e: + logger.error(f"获取内部成员信息异常: {str(e)}") + return None + async def handle_chat_change_event(self, chat_id: str, change_type: str, update_detail: str, join_user_id: str = None) -> bool: """处理群聊变更事件 @@ -227,7 +257,16 @@ class WecomClient: # 保存群成员信息 for member in chat_info.get("member_list", []): user_id = member.get("userid") - member_type = member.get("type") + # 处理数字类型: 1=企业成员, 2=外部联系人 + member_type_num = member.get("type") + if member_type_num == 1: + member_type = "INTERNAL" + elif member_type_num == 2: + member_type = "EXTERNAL" + else: + member_type = "EXTERNAL" # 默认为外部联系人 + + logger.info(f"成员类型: {member_type}(原始值:{member_type_num}), 成员ID: {user_id}") # 检查成员是否已存在 member_db = db.query(WecomExternalChatMemberDB).filter( @@ -236,20 +275,44 @@ class WecomClient: ).first() if not member_db: - # 获取外部联系人详情 + # 获取成员详情 - 根据成员类型调用不同API user_info = None + if member_type == "EXTERNAL": try: user_info = await self.get_external_contact_info(user_id) + logger.info(f"获取到外部联系人详情: {user_info}") except Exception as e: logger.warning(f"获取外部联系人信息失败: {user_id}, 错误: {str(e)}") + elif member_type == "INTERNAL": + try: + user_info = await self.get_internal_user_info(user_id) + logger.info(f"获取到内部成员详情: {user_info}") + except Exception as e: + logger.warning(f"获取内部成员信息失败: {user_id}, 错误: {str(e)}") + + # 获取名称和unionid (内部成员可能没有unionid) + member_name = None + member_unionid = None + + if user_info: + if member_type == "EXTERNAL": + member_name = user_info.get("name") + member_unionid = user_info.get("unionid") + elif member_type == "INTERNAL": + member_name = user_info.get("name") + # 注意: 内部成员可能没有unionid字段 + + # 如果API获取失败,则使用群聊详情中的信息 + if not member_name: + member_name = "未知成员" # 没有任何名称信息时的默认值 member_create = WecomExternalChatMemberCreate( chat_id=chat_id, user_id=user_id, type=member_type, - name=user_info.get("name") if user_info else member.get("name", "未知"), - unionid=user_info.get("unionid") if user_info else None + name=member_name, + unionid=member_unionid ) member_db = WecomExternalChatMemberDB(**member_create.model_dump()) db.add(member_db) @@ -297,35 +360,59 @@ class WecomClient: if chat_info and "member_list" in chat_info: for member in chat_info["member_list"]: if member.get("userid") == join_user_id: - member_type = member.get("type", "EXTERNAL") + # 处理数字类型: 1=企业成员, 2=外部联系人 + member_type_num = member.get("type") + if member_type_num == 1: + member_type = "INTERNAL" + elif member_type_num == 2: + member_type = "EXTERNAL" + else: + member_type = "EXTERNAL" # 默认为外部联系人 + member_name = member.get("name") - logger.info(f"从群聊详情中确定成员类型: {member_type}, 成员: {join_user_id}") + logger.info(f"从群聊详情中确定成员类型: {member_type}(原始值:{member_type_num}), 成员: {join_user_id}") break except Exception as e: logger.warning(f"获取群聊详情失败: {str(e)}") # 如果确定是外部联系人,尝试获取详情 + user_info = None + member_name = None + member_unionid = None + if member_type == "EXTERNAL": try: user_info = await self.get_external_contact_info(join_user_id) if user_info: member_name = user_info.get("name") - logger.info(f"获取到外部联系人详情: {member_name}") + member_unionid = user_info.get("unionid") + logger.info(f"获取到外部联系人详情: {member_name}, unionid: {member_unionid}") except Exception as e: logger.warning(f"获取外部联系人信息失败,可能是内部成员: {str(e)}") - # 如果获取失败但在群聊详情中找到了,则使用群聊详情中的信息 + elif member_type == "INTERNAL": + try: + user_info = await self.get_internal_user_info(join_user_id) + if user_info: + member_name = user_info.get("name") + # 内部成员没有unionid + logger.info(f"获取到内部成员详情: {member_name}") + except Exception as e: + logger.warning(f"获取内部成员信息失败: {str(e)}") + + # 如果API获取失败,则使用群聊详情中的信息 + if not member_name: + member_name = "未知成员" # 没有任何名称信息时的默认值 member_create = WecomExternalChatMemberCreate( chat_id=chat_id, user_id=join_user_id, type=member_type, name=member_name, - unionid=user_info.get("unionid") if user_info else None + unionid=member_unionid ) member_db = WecomExternalChatMemberDB(**member_create.model_dump()) db.add(member_db) db.commit() - # 更新群成员数量 if chat_db: diff --git a/jobs.sqlite b/jobs.sqlite index 628cfce..59ef3a3 100644 Binary files a/jobs.sqlite and b/jobs.sqlite differ