收敛864登录态切换异常与日志噪音
This commit is contained in:
@@ -64,7 +64,19 @@ class Server864APIClientBase:
|
||||
params=merged_params,
|
||||
json=json_body,
|
||||
) as response:
|
||||
payload = await response.json(content_type=None)
|
||||
try:
|
||||
payload = await response.json(content_type=None)
|
||||
except Exception:
|
||||
raw_text = await response.text()
|
||||
# 864 少数接口会直接返回纯文本而不是标准 DTO:
|
||||
# 1. 当前已在 `LogOut` 链路里碰到这种情况,旧逻辑会先炸 JSON 解析,再把真正状态信息吞掉;
|
||||
# 2. 对 2xx 响应来说,这通常只是“接口风格不统一”,不应该直接视为致命协议错误;
|
||||
# 3. 因此这里统一包成兼容 DTO,保留原始文本给上层按需处理。
|
||||
payload = {
|
||||
"Code": 200 if response.status < 400 else response.status,
|
||||
"Data": None,
|
||||
"Text": str(raw_text or "").strip(),
|
||||
}
|
||||
return self._validate_payload(payload)
|
||||
|
||||
async def _request_data(
|
||||
@@ -96,6 +108,12 @@ class Server864APIClientBase:
|
||||
return payload
|
||||
|
||||
message = str(payload.get("Text") or payload.get("Message") or "server_864 请求失败").strip()
|
||||
# 864 某些登录接口会用非 200 编码表达“当前 key 已经在线”:
|
||||
# 1. 对二维码申请链路来说,这更接近一种状态回执,而不是硬失败;
|
||||
# 2. 如果这里直接抛异常,上层就会把“已经在线”误判成致命错误并退出线程;
|
||||
# 3. 因此先保留 payload 原样放行,让 runtime 再决定是复用现有登录态还是继续走扫码。
|
||||
if "该链接已绑定微信号" in message and "在线状态良好" in message:
|
||||
return payload
|
||||
lowered_message = message.lower()
|
||||
if any(keyword in lowered_message for keyword in ("重新登录", "已退出登录", "离线", "账号需要重新登录")):
|
||||
raise UserLoggedOut(message)
|
||||
|
||||
@@ -195,7 +195,55 @@ class Server864RuntimeMixin:
|
||||
callback_name="on_login_qr_update",
|
||||
)
|
||||
|
||||
uuid, url = await self.get_qr_code(print_qr=True, login_qr_api=login_qr_api, login_way=login_way)
|
||||
try:
|
||||
uuid, url = await self.get_qr_code(print_qr=True, login_qr_api=login_qr_api, login_way=login_way)
|
||||
except Exception as e:
|
||||
qr_error_message = str(e).strip()
|
||||
if "该链接已绑定微信号" in qr_error_message and "在线状态良好" in qr_error_message:
|
||||
# 当 864 服务端明确提示“当前 key 已在线”时,优先尝试直接复用现有登录态:
|
||||
# 1. 这通常出现在切换二维码模式过快、旧连接尚未完全退出的瞬间;
|
||||
# 2. 若此时直接抛错,线程会把“已经在线”误判成获取二维码失败;
|
||||
# 3. 因此这里先转成“尝试接管现有会话”,成功后直接收口,不再强制继续申请新二维码。
|
||||
identity_ready = await self._refresh_identity_from_profile(logger=logger)
|
||||
if identity_ready:
|
||||
ipad_config["wxid"] = self.wxid
|
||||
ipad_config["login_time"] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
self._save_runtime_state(
|
||||
state_path=state_path,
|
||||
state_payload={"wxid": self.wxid, "login_time": ipad_config["login_time"]},
|
||||
logger=logger,
|
||||
)
|
||||
await self._safe_callback(
|
||||
on_login_qr_cleared,
|
||||
{
|
||||
"status": "logged_in",
|
||||
"status_text": "864 服务端已存在可用登录态,已自动复用当前会话",
|
||||
"provider_name": "server_864",
|
||||
"provider_stage": "logged_in",
|
||||
"connection_ready": True,
|
||||
"login_required": False,
|
||||
},
|
||||
logger=logger,
|
||||
callback_name="on_login_qr_cleared",
|
||||
)
|
||||
return
|
||||
await self._safe_callback(
|
||||
on_login_qr_update,
|
||||
{
|
||||
"status": "unavailable",
|
||||
"status_text": self._normalize_login_runtime_message(qr_error_message),
|
||||
"login_source": "fresh_qr",
|
||||
"provider_name": "server_864",
|
||||
"provider_stage": "status_unavailable",
|
||||
"connection_ready": False,
|
||||
"login_required": True,
|
||||
"login_qr_api": login_qr_api,
|
||||
"login_way": login_way,
|
||||
},
|
||||
logger=logger,
|
||||
callback_name="on_login_qr_update",
|
||||
)
|
||||
raise
|
||||
scan_url = f"http://weixin.qq.com/x/{uuid}" if uuid else ""
|
||||
effective_time = 0
|
||||
raw_state = 0
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from loguru import logger
|
||||
|
||||
from wechat_ipad.errors import UserLoggedOut
|
||||
|
||||
from wechat_ipad.providers.server_864.base import Server864APIClientBase
|
||||
|
||||
|
||||
@@ -59,6 +61,13 @@ class UserMixin(Server864APIClientBase):
|
||||
return True
|
||||
await self.get_profile()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error("server_864 is_logged_in:{}", e)
|
||||
except UserLoggedOut as e:
|
||||
# “未登录 / 需要重新登录”是 864 登录引导中的常规状态,不应该长期污染 error 日志:
|
||||
# 1. 当前首页会主动引导扫码,这类返回本质上只是“当前还没登录完成”;
|
||||
# 2. 若仍按 error 记录,运维排查时很难分清真正异常和正常登录态切换;
|
||||
# 3. 因此这里降级为 info,只保留可读状态文本。
|
||||
logger.info("server_864 is_logged_in:{}", e)
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.warning("server_864 is_logged_in:{}", e)
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user