feat(weibo): 修正绑定小程序码并增加账号批量操作
This commit is contained in:
@@ -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=""),
|
||||
|
||||
@@ -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(
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user