diff --git a/api/monitor/qrlogin.py b/api/monitor/qrlogin.py index 81ca128..b214792 100644 --- a/api/monitor/qrlogin.py +++ b/api/monitor/qrlogin.py @@ -331,6 +331,23 @@ async def start(platform: str = PLATFORM_XHS) -> Dict[str, Any]: async with _lock: await _discard_current_locked() + # **先问状态,再决定要不要开页面。** 顺序反过来是有代价的:读二维码内部会 + # wait_for_selector 等满 30 秒才放弃,而已经登录时页面上根本没有二维码 —— + # 用户点一下按钮要干等半分钟,还白开一个标签页。 + state = await check_login_state(force=True) + if state.get("logged_in"): + # 已经是登录状态时站点不显示二维码 —— 这本身就是成功,不是失败。 + # 顺带把 cookie 取出来,让调用方可以存进库。 + session = QrLoginSession(platform, None) + session.cookie = await _current_cookie() + session.status = STATUS_SUCCESS + session.logged_in = True + session.nickname = state.get("nickname") + who = f"({session.nickname})" if session.nickname else "" + session.message = f"浏览器已经是登录状态{who},无需扫码" + _current = session + return session.snapshot() + page = await _ensure_page(platform) try: await page.goto( @@ -342,18 +359,7 @@ async def start(platform: str = PLATFORM_XHS) -> Dict[str, Any]: session = QrLoginSession(platform, page) session.image = image - - state = await check_login_state() - if state.get("logged_in"): - # 已经是登录状态时站点不显示二维码——这本身就是成功,不是失败。 - # 顺带把 cookie 取出来,让调用方可以存进库。 - session.cookie = await _current_cookie() - session.status = STATUS_SUCCESS - session.logged_in = True - session.nickname = state.get("nickname") - who = f"({session.nickname})" if session.nickname else "" - session.message = f"浏览器已经是登录状态{who},无需扫码" - elif not image: + if not image: session.status = STATUS_ERROR session.message = "页面上没找到二维码,请确认站点结构没有变化" diff --git a/tests/test_qrlogin.py b/tests/test_qrlogin.py index 0f6c463..5f977a5 100644 --- a/tests/test_qrlogin.py +++ b/tests/test_qrlogin.py @@ -140,6 +140,21 @@ async def test_an_already_signed_in_profile_needs_no_scan(monkeypatch): assert snapshot["nickname"] == "老王" +@pytest.mark.asyncio +async def test_an_already_signed_in_profile_never_opens_a_page(monkeypatch): + """已登录时**根本不该去开页面**。 + + 读二维码内部会 wait_for_selector 等满 30 秒才放弃,而已经登录时页面上没有二维码 —— + 顺序反了的话,用户点一下按钮要干等半分钟,还白开一个标签页。 + """ + manager, _pw, _browser, context, _page, _qr = _fake_stack() + _patch(monkeypatch, manager, resolver=lambda _c: {"user_id": "u1", "nickname": "小明"}) + + await qrlogin.start(qrlogin.PLATFORM_XHS) + + context.new_page.assert_not_called() + + @pytest.mark.asyncio async def test_no_qr_and_not_signed_in_is_an_error(monkeypatch): manager, *_rest = _fake_stack()