feat(weibo): 修正绑定小程序码并增加账号批量操作

This commit is contained in:
yml2213
2026-11-08 13:17:29 +08:00
parent 79cfd4a634
commit ed15701392
11 changed files with 591 additions and 54 deletions
+38
View File
@@ -11,6 +11,7 @@ from sqlalchemy import text
from core.weibo import (
WeiboAuthError,
WeiboBindError,
WeiboBindQrCode,
WeiboExchangeResult,
WeiboHomeSnapshot,
WeiboPaymentStatus,
@@ -90,6 +91,17 @@ class StubWeiboClient:
)
return prefix
def generate_bind_qrcode(self, bind_url: str, account_type: str):
self.calls.append(("qrcode", account_type))
error = self.scheme_errors.get(account_type)
if error:
raise WeiboBindError(error)
mime = "png" if account_type == "wx" else "jpeg"
return WeiboBindQrCode(
image_src=f"data:image/{mime};base64,test-{account_type}",
token=f"token-{account_type}",
)
@pytest.fixture
def current_user(db):
@@ -333,6 +345,32 @@ def test_bind_qrcodes_returns_both_channels_and_partial_error(db, current_user):
assert by_channel["qq"]["error"] == "QQ Scheme 暂时不可用"
def test_bind_qrcodes_selected_channel_returns_scannable_image(db, current_user):
account = import_cookies(
WeiboCookieImport(text="SCF=a; SUB=b", tag=""),
db=db,
current=current_user,
).accounts[0]
result = create_bind_qrcodes(
account.id,
channel="qq",
db=db,
current=current_user,
)
dumped = result.model_dump()
assert len(dumped["schemes"]) == 1
qq = dumped["schemes"][0]
assert qq["channel"] == "qq"
assert qq["qrcode_image"] == "data:image/jpeg;base64,test-qq"
assert qq["qrcode_token"] == "token-qq"
assert qq["scheme"].startswith("mqqapi://miniapp/open")
assert [call for call in StubWeiboClient.calls if call[0] == "qrcode"] == [
("qrcode", "qq")
]
def test_bind_qrcodes_rejects_bound_account_without_rebind(db, current_user):
account = import_cookies(
WeiboCookieImport(text="SCF=a; SUB=b", tag=""),
+56
View File
@@ -11,6 +11,7 @@ from core.weibo import (
WeiboApiError,
WeiboAuthError,
WeiboBindError,
WeiboBindQrCode,
WeiboClient,
WeiboExchangeError,
WeiboExchangeUncertainError,
@@ -187,6 +188,61 @@ def test_generate_bind_scheme_rejects_missing_url_scheme():
client.generate_bind_scheme(BIND_URL, "qq")
def test_generate_bind_qrcode_posts_channel_and_preserves_raw_query():
session = FakeSession(
[
{
"iRet": 0,
"sMsg": "ok",
"jData": {
"qrcode": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB",
"qrcodeToken": "token-1",
},
}
]
)
client = WeiboClient(session=session)
qrcode = client.generate_bind_qrcode(BIND_URL, "qq")
assert isinstance(qrcode, WeiboBindQrCode)
assert qrcode.image_src == (
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB"
)
assert qrcode.token == "token-1"
method, url, kwargs = session.calls[0]
assert method == "POST"
assert url == "https://livelinkbind.game.qq.com/api/qrcode/getMiniAppQrcode"
body = kwargs["json"]
raw_url = extract_bind_raw_url(BIND_URL)
assert body["queryString"].startswith(f"{raw_url}&sessionId=")
assert body["accountType"] == "qq"
assert kwargs["headers"]["Gap-Act-Id"] == "16722"
assert kwargs["headers"]["Gap-Plat-Id"] == "weiyouxi"
assert kwargs["headers"]["Gap-User-From"] == "pc"
assert "Cookie" not in kwargs["headers"]
def test_generate_bind_qrcode_supports_jpeg_and_server_rate_limit():
jpeg_session = FakeSession(
[
{
"iRet": 0,
"sMsg": "ok",
"jData": {"qrcode": "/9j/4AAQSkZJRgABAQ", "qrcodeToken": "token-2"},
}
]
)
qrcode = WeiboClient(session=jpeg_session).generate_bind_qrcode(BIND_URL, "wx")
assert qrcode.image_src == "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ"
rate_limited = FakeSession(
[{"iRet": -1140603, "sMsg": "刷新二维码频率过快,请间隔5秒后重试"}]
)
with pytest.raises(WeiboBindError, match="间隔5秒"):
WeiboClient(session=rate_limited).generate_bind_qrcode(BIND_URL, "qq")
def test_mall_exchange_and_point_queries():
session = FakeSession(
[