Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a48d9c624 | ||
|
|
b06b622eb3 |
@@ -1522,6 +1522,87 @@ class HuyaHttpClient:
|
|||||||
return self._raw_from_wup(resp) if isinstance(resp, WupResponse) else None
|
return self._raw_from_wup(resp) if isinstance(resp, WupResponse) else None
|
||||||
|
|
||||||
|
|
||||||
|
def _bind_game_account_has_role(resp: Any) -> bool:
|
||||||
|
"""响应是否真的带出了角色名(角色名是判断「最新角色」的唯一可靠信号)。"""
|
||||||
|
account_data = getattr(resp, "accountData", None)
|
||||||
|
game_role = getattr(account_data, "gameRole", None)
|
||||||
|
return bool(getattr(game_role, "roleName", ""))
|
||||||
|
|
||||||
|
|
||||||
|
def query_bind_game_account(
|
||||||
|
client: Any,
|
||||||
|
*,
|
||||||
|
uid: int,
|
||||||
|
cookie: str,
|
||||||
|
b_act_id: int,
|
||||||
|
gid: int = 0,
|
||||||
|
outer_act_id: str = "",
|
||||||
|
is_use_outer_act_id: int = 1,
|
||||||
|
scene: str = "",
|
||||||
|
timeout: float | None = None,
|
||||||
|
) -> tuple[Any, dict[str, Any]]:
|
||||||
|
"""查询绑定游戏账号(官方活动页两条查询,返回最新角色)。
|
||||||
|
|
||||||
|
2026-11-09 真机定论:新版活动页先查 ``gid + outerActId``,再查
|
||||||
|
``gid + outerActId=空``;**角色名以第二路为准**(第一路会返回旧的缓存角色)。
|
||||||
|
旧协议(gid=0)第二路会被服务端判 501,保持外层优先、缺角色时补查内层。
|
||||||
|
|
||||||
|
返回 ``(status, detail)``:
|
||||||
|
- ``status``:最终选中的 ``CheckUserBindGameAccountResp``(``None`` 表示接口无响应);
|
||||||
|
- ``detail``:两路响应与来源标记,供任务结果透传(可 JSON 序列化)。
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _call(outer_id: str, use_outer: int):
|
||||||
|
kwargs: dict[str, Any] = {
|
||||||
|
"uid": uid,
|
||||||
|
"cookie": cookie,
|
||||||
|
"b_act_id": b_act_id,
|
||||||
|
"gid": gid,
|
||||||
|
"outer_act_id": outer_id,
|
||||||
|
"is_use_outer_act_id": use_outer,
|
||||||
|
"scene": scene,
|
||||||
|
}
|
||||||
|
if timeout is not None:
|
||||||
|
kwargs["timeout"] = timeout
|
||||||
|
return client.check_user_bind_game_account(**kwargs)
|
||||||
|
|
||||||
|
outer = _call(outer_act_id, is_use_outer_act_id)
|
||||||
|
if outer is None:
|
||||||
|
return None, {}
|
||||||
|
detail: dict[str, Any] = {
|
||||||
|
"bind_status_source": "outer",
|
||||||
|
"outer_bind_status": outer.to_dict(),
|
||||||
|
}
|
||||||
|
if outer.status != 200:
|
||||||
|
return outer, detail
|
||||||
|
|
||||||
|
chosen = outer
|
||||||
|
if gid:
|
||||||
|
# 第二路(gid + outerActId=空)是最新角色源,带出角色就优先采用。
|
||||||
|
inner = _call("", 0)
|
||||||
|
if inner is not None:
|
||||||
|
detail["inner_bind_status"] = inner.to_dict()
|
||||||
|
if inner.status == 200 and _bind_game_account_has_role(inner):
|
||||||
|
chosen = inner
|
||||||
|
detail["bind_status_source"] = "inner"
|
||||||
|
else:
|
||||||
|
account_data = getattr(outer, "accountData", None)
|
||||||
|
if not _bind_game_account_has_role(outer) and bool(
|
||||||
|
getattr(account_data, "isNeedActCheck", 0)
|
||||||
|
or not getattr(account_data, "isBindAcount", 0)
|
||||||
|
or not getattr(account_data, "isBindRole", 0)
|
||||||
|
):
|
||||||
|
inner = _call("", 0)
|
||||||
|
if inner is not None:
|
||||||
|
detail["inner_bind_status"] = inner.to_dict()
|
||||||
|
if inner.status == 200 and _bind_game_account_has_role(inner):
|
||||||
|
chosen = inner
|
||||||
|
detail["bind_status_source"] = "inner"
|
||||||
|
|
||||||
|
detail["bind_status"] = chosen.to_dict()
|
||||||
|
return chosen, detail
|
||||||
|
|
||||||
|
|
||||||
def _self_check():
|
def _self_check():
|
||||||
uid = 1199647239697
|
uid = 1199647239697
|
||||||
guid = "0a8973013ad3476a53029ddb9edb071f"
|
guid = "0a8973013ad3476a53029ddb9edb071f"
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ from core.huya.taf_protocol import TafOutputStream, TafType
|
|||||||
from tests.support.db import get_test_engine, make_test_session
|
from tests.support.db import get_test_engine, make_test_session
|
||||||
from web.backend.deps import require_permission
|
from web.backend.deps import require_permission
|
||||||
from web.backend.huya_defaults import (
|
from web.backend.huya_defaults import (
|
||||||
HUYA_DEFAULT_BIND_ACT_ID,
|
HUYA_DEFAULT_BIND_GID,
|
||||||
HUYA_DEFAULT_OUTER_ACT_ID,
|
|
||||||
)
|
)
|
||||||
from web.backend.models import (
|
from web.backend.models import (
|
||||||
AuditLog,
|
AuditLog,
|
||||||
@@ -763,6 +762,13 @@ class FakeBindResp:
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
return {
|
||||||
|
"status": self.status,
|
||||||
|
"msg": self.msg,
|
||||||
|
"game_name": self.gameName,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class FakeGiftResp:
|
class FakeGiftResp:
|
||||||
"""合成一份 ``getActPrizeList`` 响应(礼包列表)。"""
|
"""合成一份 ``getActPrizeList`` 响应(礼包列表)。"""
|
||||||
@@ -883,12 +889,21 @@ class FakeProbeClient:
|
|||||||
self.calls: list[dict] = []
|
self.calls: list[dict] = []
|
||||||
self.gift_calls: list[dict] = []
|
self.gift_calls: list[dict] = []
|
||||||
self.points_calls: list[dict] = []
|
self.points_calls: list[dict] = []
|
||||||
|
self._current_bind_outcome: object | None = None
|
||||||
|
|
||||||
def check_user_bind_game_account(self, **kwargs):
|
def check_user_bind_game_account(self, **kwargs):
|
||||||
self.calls.append(kwargs)
|
self.calls.append(kwargs)
|
||||||
if not self.outcomes:
|
if kwargs.get("outer_act_id"):
|
||||||
raise AssertionError("探针被调用的次数超出用例预期")
|
# 外层(第一路):按脚本弹一个响应。
|
||||||
outcome = self.outcomes.pop(0)
|
if not self.outcomes:
|
||||||
|
raise AssertionError("探针被调用的次数超出用例预期")
|
||||||
|
outcome = self.outcomes.pop(0)
|
||||||
|
self._current_bind_outcome = outcome
|
||||||
|
else:
|
||||||
|
# 内层(第二路):复用当前外层响应;需要内外层不同时用自定义 client。
|
||||||
|
outcome = self._current_bind_outcome
|
||||||
|
if outcome is None:
|
||||||
|
raise AssertionError("内层查询在没有外层结果时被调用")
|
||||||
if isinstance(outcome, Exception):
|
if isinstance(outcome, Exception):
|
||||||
raise outcome
|
raise outcome
|
||||||
return outcome
|
return outcome
|
||||||
@@ -947,21 +962,49 @@ class TestCollabCkProbe(TestCollabBase):
|
|||||||
|
|
||||||
collab.verify_ck(self.db, self.user, order, client=client)
|
collab.verify_ck(self.db, self.user, order, client=client)
|
||||||
|
|
||||||
call = client.calls[0]
|
# 通用查询两路:外层 gid+outerActId,内层 gid+outerActId=空。
|
||||||
assert call["uid"] == 1199647239697
|
outer, inner = client.calls[0], client.calls[1]
|
||||||
assert isinstance(call["uid"], int)
|
assert outer["uid"] == 1199647239697
|
||||||
assert call["cookie"] == order.cookie
|
assert isinstance(outer["uid"], int)
|
||||||
assert (
|
assert outer["cookie"] == order.cookie
|
||||||
call["b_act_id"]
|
assert outer["b_act_id"] == 0
|
||||||
== collab.PROBE_BIND_ACT_ID
|
assert outer["gid"] == collab.PROBE_GID == int(HUYA_DEFAULT_BIND_GID)
|
||||||
== int(HUYA_DEFAULT_BIND_ACT_ID)
|
assert outer["outer_act_id"] == collab.PROBE_OUTER_ACT_ID
|
||||||
)
|
assert outer["is_use_outer_act_id"] == 0
|
||||||
assert call["is_use_outer_act_id"] == 1
|
assert outer["scene"] == collab.PROBE_SCENE == "undefined"
|
||||||
assert (
|
assert inner["gid"] == collab.PROBE_GID == 3203
|
||||||
call["outer_act_id"]
|
assert inner["outer_act_id"] == ""
|
||||||
== collab.PROBE_OUTER_ACT_ID
|
assert inner["is_use_outer_act_id"] == 0
|
||||||
== HUYA_DEFAULT_OUTER_ACT_ID
|
assert inner["scene"] == "undefined"
|
||||||
)
|
|
||||||
|
def test_verify_queries_second_path_for_latest_role(self):
|
||||||
|
"""外层返回旧角色时,必须取第二路(outerActId=空)的最新角色。"""
|
||||||
|
order = self._row_with_ck(uid="1199647239697")
|
||||||
|
|
||||||
|
class StaleThenLatestClient:
|
||||||
|
def __init__(self):
|
||||||
|
self.calls: list[dict] = []
|
||||||
|
|
||||||
|
def check_user_bind_game_account(self, **kwargs):
|
||||||
|
self.calls.append(kwargs)
|
||||||
|
if kwargs["outer_act_id"]:
|
||||||
|
return FakeBindResp(nick="冰点", role="软芙乎")
|
||||||
|
return FakeBindResp(nick="冰点", role="唉哟酪酪")
|
||||||
|
|
||||||
|
client = StaleThenLatestClient()
|
||||||
|
|
||||||
|
collab.verify_ck(self.db, self.user, order, client=client)
|
||||||
|
|
||||||
|
outer, inner = client.calls[0], client.calls[1]
|
||||||
|
assert outer["outer_act_id"] == collab.PROBE_OUTER_ACT_ID
|
||||||
|
assert inner["outer_act_id"] == ""
|
||||||
|
assert inner["gid"] == collab.PROBE_GID == 3203
|
||||||
|
assert inner["scene"] == "undefined"
|
||||||
|
# 快照落的是第二路的最新角色,而不是外层旧角色
|
||||||
|
assert order.bind_game_role == "唉哟酪酪"
|
||||||
|
assert order.bind_game_account == "冰点"
|
||||||
|
assert "唉哟酪酪" in order.ck_check_message
|
||||||
|
assert "软芙乎" not in order.ck_check_message
|
||||||
|
|
||||||
def test_verify_marks_invalid_when_status_is_not_200(self):
|
def test_verify_marks_invalid_when_status_is_not_200(self):
|
||||||
order = self._row_with_ck()
|
order = self._row_with_ck()
|
||||||
@@ -1241,7 +1284,7 @@ class TestCollabCkProbe(TestCollabBase):
|
|||||||
# 没 CK 的行保持「未验证」,不能谎报成「已失效」
|
# 没 CK 的行保持「未验证」,不能谎报成「已失效」
|
||||||
assert without_ck.ck_status == "unverified"
|
assert without_ck.ck_status == "unverified"
|
||||||
assert "CK" in result["results"][1]["message"]
|
assert "CK" in result["results"][1]["message"]
|
||||||
assert len(client.calls) == 1 # 没 CK 的行不发请求
|
assert len(client.calls) == 2 # 有 CK 的行两路(外层+内层),没 CK 的行不发请求
|
||||||
|
|
||||||
def test_batch_keeps_interval_between_rows(self, monkeypatch):
|
def test_batch_keeps_interval_between_rows(self, monkeypatch):
|
||||||
"""人工触发也要串行 + 间隔,别把账号送进风控名单。"""
|
"""人工触发也要串行 + 间隔,别把账号送进风控名单。"""
|
||||||
@@ -2134,8 +2177,8 @@ class TestCollabRecharge(TestCollabBase):
|
|||||||
assert (
|
assert (
|
||||||
order.points_check_detail["group_key"] == f"{self.BIND} / {self.ROLE}"
|
order.points_check_detail["group_key"] == f"{self.BIND} / {self.ROLE}"
|
||||||
)
|
)
|
||||||
# 同一 uid 只验一次 CK、只查一次积分
|
# 同一 uid 只验一次 CK(两路查询)、只查一次积分
|
||||||
assert len(client.calls) == 1
|
assert len(client.calls) == 2
|
||||||
assert len(client.score_calls) == 1
|
assert len(client.score_calls) == 1
|
||||||
assert "huya:collab:recharge_check" in [
|
assert "huya:collab:recharge_check" in [
|
||||||
row.action for row in self._audits(first)
|
row.action for row in self._audits(first)
|
||||||
@@ -3136,7 +3179,7 @@ class TestProbeCache(TestCollabBase):
|
|||||||
collab.probe_ck(order)
|
collab.probe_ck(order)
|
||||||
collab.probe_ck(order)
|
collab.probe_ck(order)
|
||||||
|
|
||||||
assert len(calls) == 1
|
assert len(calls) == 2 # 第一次探针两路(外层+内层),第二次命中缓存
|
||||||
collab._probe_cache.clear()
|
collab._probe_cache.clear()
|
||||||
|
|
||||||
def test_different_ck_is_probed_separately(self, monkeypatch):
|
def test_different_ck_is_probed_separately(self, monkeypatch):
|
||||||
@@ -3155,7 +3198,7 @@ class TestProbeCache(TestCollabBase):
|
|||||||
collab.probe_ck(first)
|
collab.probe_ck(first)
|
||||||
collab.probe_ck(second)
|
collab.probe_ck(second)
|
||||||
|
|
||||||
assert len(calls) == 2
|
assert len(calls) == 4 # 两个 CK 各自两路(外层+内层)
|
||||||
collab._probe_cache.clear()
|
collab._probe_cache.clear()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -135,12 +135,20 @@ class _FakeGameRole:
|
|||||||
|
|
||||||
|
|
||||||
class _FakeBindAccountData:
|
class _FakeBindAccountData:
|
||||||
def __init__(self, nick: str, role_name: str):
|
def __init__(
|
||||||
|
self,
|
||||||
|
nick: str,
|
||||||
|
role_name: str,
|
||||||
|
*,
|
||||||
|
is_bind_account: int = 1,
|
||||||
|
is_bind_role: int = 1,
|
||||||
|
is_need_act_check: int = 0,
|
||||||
|
):
|
||||||
self.gameAccount = _FakeGameAccount(nick)
|
self.gameAccount = _FakeGameAccount(nick)
|
||||||
self.gameRole = _FakeGameRole(role_name, "苹果(iOS)", "手Q")
|
self.gameRole = _FakeGameRole(role_name, "苹果(iOS)", "手Q")
|
||||||
self.isBindAcount = 1
|
self.isBindAcount = is_bind_account
|
||||||
self.isBindRole = 1
|
self.isBindRole = is_bind_role
|
||||||
self.isNeedActCheck = 0
|
self.isNeedActCheck = is_need_act_check
|
||||||
self.changBindTime = 0
|
self.changBindTime = 0
|
||||||
|
|
||||||
|
|
||||||
@@ -152,13 +160,22 @@ class _FakeBindResponse:
|
|||||||
msg: str = "",
|
msg: str = "",
|
||||||
nick: str = "微信用户",
|
nick: str = "微信用户",
|
||||||
role_name: str = "吃鸡199706",
|
role_name: str = "吃鸡199706",
|
||||||
|
is_bind_account: int = 1,
|
||||||
|
is_bind_role: int = 1,
|
||||||
|
is_need_act_check: int = 0,
|
||||||
):
|
):
|
||||||
self.status = status
|
self.status = status
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
self.gameName = "和平精英"
|
self.gameName = "和平精英"
|
||||||
self.gameAuthScene = ""
|
self.gameAuthScene = ""
|
||||||
self.changeBindDay = 7
|
self.changeBindDay = 7
|
||||||
self.accountData = _FakeBindAccountData(nick, role_name)
|
self.accountData = _FakeBindAccountData(
|
||||||
|
nick,
|
||||||
|
role_name,
|
||||||
|
is_bind_account=is_bind_account,
|
||||||
|
is_bind_role=is_bind_role,
|
||||||
|
is_need_act_check=is_need_act_check,
|
||||||
|
)
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {
|
||||||
@@ -976,6 +993,38 @@ def test_bind_protocol_prefers_configured_gid_and_keeps_legacy_fallback():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_inner_bind_probe_keeps_gid_and_empties_outer_act_id(monkeypatch):
|
||||||
|
"""官方页面第二路查询必须是 gid=3203 + outerActId='',才能取到角色名。"""
|
||||||
|
calls: list[dict] = []
|
||||||
|
responses = [
|
||||||
|
_FakeBindResponse(role_name="", is_bind_role=0, is_need_act_check=1),
|
||||||
|
_FakeBindResponse(role_name="和平精英角色", is_bind_role=1),
|
||||||
|
]
|
||||||
|
client = _CkProbeClient(None)
|
||||||
|
|
||||||
|
def fake_check(**kwargs):
|
||||||
|
calls.append(kwargs)
|
||||||
|
return responses[len(calls) - 1]
|
||||||
|
|
||||||
|
monkeypatch.setattr(client, "check_user_bind_game_account", fake_check)
|
||||||
|
runner, _marks = _task_runner(monkeypatch, "query_game_name")
|
||||||
|
status, _query = runner._resolve_bind_status(
|
||||||
|
client,
|
||||||
|
UID,
|
||||||
|
COOKIE,
|
||||||
|
b_act_id_int=0,
|
||||||
|
outer_act_id="17096",
|
||||||
|
gid=3203,
|
||||||
|
is_use_outer_act_id=0,
|
||||||
|
scene="undefined",
|
||||||
|
)
|
||||||
|
assert status.accountData.gameRole.roleName == "和平精英角色"
|
||||||
|
assert calls[0]["outer_act_id"] == "17096"
|
||||||
|
assert calls[0]["gid"] == 3203
|
||||||
|
assert calls[1]["outer_act_id"] == ""
|
||||||
|
assert calls[1]["gid"] == 3203
|
||||||
|
|
||||||
|
|
||||||
def test_confirm_bind_uses_latest_har_protocol(monkeypatch):
|
def test_confirm_bind_uses_latest_har_protocol(monkeypatch):
|
||||||
"""确认绑定复用抓包里的 gid=3203 / bActId=0 / outerActId=17096。"""
|
"""确认绑定复用抓包里的 gid=3203 / bActId=0 / outerActId=17096。"""
|
||||||
client = _BindConfirmClient()
|
client = _BindConfirmClient()
|
||||||
@@ -1001,14 +1050,20 @@ def test_confirm_bind_uses_latest_har_protocol(monkeypatch):
|
|||||||
"outer_act_id": "17096",
|
"outer_act_id": "17096",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
assert all(
|
# 通用查询会连打两路:外层 gid+outerActId=17096,内层 gid+outerActId=空。
|
||||||
call["b_act_id"] == 0
|
assert len(client.check_calls) == 4 # 绑定前查一次 + 确认后刷新查一次
|
||||||
and call["gid"] == 3203
|
for call in client.check_calls[0::2]:
|
||||||
and call["outer_act_id"] == "17096"
|
assert call["b_act_id"] == 0
|
||||||
and call["is_use_outer_act_id"] == 0
|
assert call["gid"] == 3203
|
||||||
and call["scene"] == "undefined"
|
assert call["outer_act_id"] == "17096"
|
||||||
for call in client.check_calls
|
assert call["is_use_outer_act_id"] == 0
|
||||||
)
|
assert call["scene"] == "undefined"
|
||||||
|
for call in client.check_calls[1::2]:
|
||||||
|
assert call["b_act_id"] == 0
|
||||||
|
assert call["gid"] == 3203
|
||||||
|
assert call["outer_act_id"] == ""
|
||||||
|
assert call["is_use_outer_act_id"] == 0
|
||||||
|
assert call["scene"] == "undefined"
|
||||||
|
|
||||||
|
|
||||||
def test_get_bind_qr_uses_latest_har_protocol(monkeypatch):
|
def test_get_bind_qr_uses_latest_har_protocol(monkeypatch):
|
||||||
|
|||||||
@@ -30,8 +30,10 @@ from loguru import logger
|
|||||||
from sqlalchemy import func, or_, tuple_
|
from sqlalchemy import func, or_, tuple_
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from core.huya.http_client import query_bind_game_account
|
||||||
|
|
||||||
from ..huya_defaults import (
|
from ..huya_defaults import (
|
||||||
HUYA_DEFAULT_BIND_ACT_ID,
|
HUYA_DEFAULT_BIND_GID,
|
||||||
HUYA_DEFAULT_OUTER_ACT_ID,
|
HUYA_DEFAULT_OUTER_ACT_ID,
|
||||||
HUYA_DEFAULT_SID,
|
HUYA_DEFAULT_SID,
|
||||||
)
|
)
|
||||||
@@ -1412,9 +1414,12 @@ def set_images(
|
|||||||
# CK 探针(S5,只读验证)
|
# CK 探针(S5,只读验证)
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
# 探针参数与 web/backend/huya_defaults.py 的默认活动一致(2026-10-16 真机实测)。
|
# 探针参数与 web/backend/huya_defaults.py 的默认活动一致(2026-11-09 真机实测)。
|
||||||
PROBE_BIND_ACT_ID = int(HUYA_DEFAULT_BIND_ACT_ID)
|
# 新版活动页绑定走 gid=3203、bActId=0;最终角色由通用查询的第二路
|
||||||
|
# (gid + outerActId=空)返回,这里只给出外层活动参数。
|
||||||
|
PROBE_GID = int(HUYA_DEFAULT_BIND_GID)
|
||||||
PROBE_OUTER_ACT_ID = HUYA_DEFAULT_OUTER_ACT_ID
|
PROBE_OUTER_ACT_ID = HUYA_DEFAULT_OUTER_ACT_ID
|
||||||
|
PROBE_SCENE = "undefined" # 与 runner 绑定协议保持一致
|
||||||
PROBE_TIMEOUT_SECONDS = 15.0
|
PROBE_TIMEOUT_SECONDS = 15.0
|
||||||
|
|
||||||
# 探针独占的绑定快照列(每次验证**覆盖写入**,人工不编辑):
|
# 探针独占的绑定快照列(每次验证**覆盖写入**,人工不编辑):
|
||||||
@@ -1572,12 +1577,15 @@ def probe_ck(order: HuyaExternalOrder, *, client: Any | None = None) -> CkProbeR
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
probe_client = client or _build_probe_client()
|
probe_client = client or _build_probe_client()
|
||||||
resp = probe_client.check_user_bind_game_account(
|
resp, _detail = query_bind_game_account(
|
||||||
|
probe_client,
|
||||||
uid=uid,
|
uid=uid,
|
||||||
cookie=cookie,
|
cookie=cookie,
|
||||||
b_act_id=PROBE_BIND_ACT_ID,
|
b_act_id=0,
|
||||||
is_use_outer_act_id=1,
|
gid=PROBE_GID,
|
||||||
outer_act_id=PROBE_OUTER_ACT_ID,
|
outer_act_id=PROBE_OUTER_ACT_ID,
|
||||||
|
is_use_outer_act_id=0,
|
||||||
|
scene=PROBE_SCENE,
|
||||||
timeout=PROBE_TIMEOUT_SECONDS,
|
timeout=PROBE_TIMEOUT_SECONDS,
|
||||||
)
|
)
|
||||||
except Exception as exc: # noqa: BLE001 探针异常=验证不通过,不能让接口 500
|
except Exception as exc: # noqa: BLE001 探针异常=验证不通过,不能让接口 500
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ from typing import TYPE_CHECKING, Any
|
|||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from core.huya.http_client import query_bind_game_account
|
||||||
|
|
||||||
from ..huya_defaults import HUYA_DEFAULT_OUTER_ACT_ID
|
from ..huya_defaults import HUYA_DEFAULT_OUTER_ACT_ID
|
||||||
from ..models import HuyaAccount, HuyaTask
|
from ..models import HuyaAccount, HuyaTask
|
||||||
from .huya_runner_core import HUYA_RECHARGE_SOURCE_ID, HuyaBatchRunnerCore
|
from .huya_runner_core import HUYA_RECHARGE_SOURCE_ID, HuyaBatchRunnerCore
|
||||||
@@ -48,10 +50,6 @@ class BindMixin:
|
|||||||
account_data = bind_status.accountData
|
account_data = bind_status.accountData
|
||||||
return account_data.gameRole.roleName or ""
|
return account_data.gameRole.roleName or ""
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _has_bind_role(bind_status) -> bool:
|
|
||||||
return bool(bind_status and BindMixin._role_name(bind_status))
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _bind_role_result(bind_status) -> dict:
|
def _bind_role_result(bind_status) -> dict:
|
||||||
account_data = bind_status.accountData
|
account_data = bind_status.accountData
|
||||||
@@ -149,57 +147,18 @@ class BindMixin:
|
|||||||
is_use_outer_act_id: int = 1,
|
is_use_outer_act_id: int = 1,
|
||||||
scene: str = "",
|
scene: str = "",
|
||||||
):
|
):
|
||||||
"""按活动页逻辑解析绑定状态,优先返回含角色的状态。"""
|
"""按活动页逻辑解析绑定状态(统一委托 core.huya.http_client 的通用查询)。"""
|
||||||
probe_kwargs: dict[str, Any] = {
|
return query_bind_game_account(
|
||||||
"uid": uid,
|
client,
|
||||||
"cookie": cookie,
|
uid=uid,
|
||||||
"b_act_id": b_act_id_int,
|
cookie=cookie,
|
||||||
"gid": gid,
|
b_act_id=b_act_id_int,
|
||||||
"outer_act_id": outer_act_id,
|
gid=gid,
|
||||||
"is_use_outer_act_id": is_use_outer_act_id,
|
outer_act_id=outer_act_id,
|
||||||
"scene": scene,
|
is_use_outer_act_id=is_use_outer_act_id,
|
||||||
}
|
scene=scene,
|
||||||
if timeout is not None:
|
timeout=timeout,
|
||||||
probe_kwargs["timeout"] = timeout
|
|
||||||
outer_status = client.check_user_bind_game_account(**probe_kwargs)
|
|
||||||
if outer_status is None:
|
|
||||||
return None, {}
|
|
||||||
|
|
||||||
query_result = {
|
|
||||||
"bind_status_source": "outer",
|
|
||||||
"outer_bind_status": outer_status.to_dict(),
|
|
||||||
}
|
|
||||||
if outer_status.status != 200:
|
|
||||||
return outer_status, query_result
|
|
||||||
|
|
||||||
chosen_status = outer_status
|
|
||||||
account_data = outer_status.accountData
|
|
||||||
# 最新抓包协议只用外层查询(gid + outerActId)。旧的内层兜底会带上
|
|
||||||
# gid=0/outerActId=空,被服务端判 501「参数错误」,仅在旧协议下保留。
|
|
||||||
should_check_inner = (
|
|
||||||
not gid
|
|
||||||
and not self._has_bind_role(outer_status)
|
|
||||||
and bool(
|
|
||||||
account_data.isNeedActCheck
|
|
||||||
or not account_data.isBindAcount
|
|
||||||
or not account_data.isBindRole
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if should_check_inner:
|
|
||||||
inner_status = client.check_user_bind_game_account(
|
|
||||||
uid=uid,
|
|
||||||
cookie=cookie,
|
|
||||||
b_act_id=b_act_id_int,
|
|
||||||
is_use_outer_act_id=0,
|
|
||||||
)
|
|
||||||
if inner_status is not None:
|
|
||||||
query_result["inner_bind_status"] = inner_status.to_dict()
|
|
||||||
if inner_status.status == 200 and self._has_bind_role(inner_status):
|
|
||||||
chosen_status = inner_status
|
|
||||||
query_result["bind_status_source"] = "inner"
|
|
||||||
|
|
||||||
query_result["bind_status"] = chosen_status.to_dict()
|
|
||||||
return chosen_status, query_result
|
|
||||||
|
|
||||||
def _probe_bind_status(
|
def _probe_bind_status(
|
||||||
self,
|
self,
|
||||||
|
|||||||
Reference in New Issue
Block a user