fix(huya): 一号一设备补完 — hydevice 设备参数跟随账号画像 + 画像一致性字段下沉
用户实弹测试暴露两个缺口:
1. Hebe/GUID32 全空: 登录路径走 get_profile, 未经过 account_env 补字段
→ _enrich_profile 下沉到 get_profile (幂等, 存量账号自动补齐)
2. sdid 前缀跨账号同源 (0UnHUgv0_qmfD4KAKlwzh...): env.js 是静态设备仿真
(写死 M2102J2SC), 状态目录隔离只改了'存储', 没改'采集输入'
→ env.js makeEnv(overrides) 支持按画像覆盖 UA/屏幕/机型/Android版本;
runner 接收 device.json; get_huya_sdid(device_hint=画像);
下次登录每账号 hydevice 采集输入=各自绑定机型 → sdid 彻底分家
This commit is contained in:
@@ -9,6 +9,7 @@ from __future__ import annotations
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import json
|
||||
from collections.abc import Mapping
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
@@ -52,7 +53,11 @@ HDID_PREFIX = "__HDID__"
|
||||
|
||||
|
||||
def _run_node_runner(state_dir: Path, app_id: str, timeout: tuple[float, float]) -> tuple[str, str]:
|
||||
"""调用 node runner,返回 (sdid, hdid)。"""
|
||||
"""调用 node runner,返回 (sdid, hdid)。
|
||||
|
||||
若 state_dir/device.json 存在 (账号画像派生的设备覆盖参数), runner 会以该
|
||||
设备身份运行 hydevice → 不同账号的 sdid/40hex hdid 不再同源 (一号一设备)。
|
||||
"""
|
||||
node_bin = shutil.which("node")
|
||||
if not node_bin:
|
||||
raise HuyaFingerprintError("未找到 node 可执行文件(hydevice.js 需要 JS 引擎)")
|
||||
@@ -102,6 +107,37 @@ def _fallback_sdid(session: requests.Session, timeout) -> str:
|
||||
return collect_res.json().get("data", {}).get("sdid", "")
|
||||
|
||||
|
||||
def write_device_hint(state_dir: str | Path, device_info: Mapping) -> Path:
|
||||
"""把账号画像写成 hydevice 设备覆盖参数 (env.js overrides)。
|
||||
|
||||
来源: 画像 model/screen(格式"model,sdkVer,androidVer")/vendor + app 版本。
|
||||
每账号独立 → hydevice 采集输入不同 → 服务端 sdid 不再同前缀。
|
||||
"""
|
||||
state_dir = Path(state_dir)
|
||||
state_dir.mkdir(parents=True, exist_ok=True)
|
||||
screen = str(device_info.get("screen", ""))
|
||||
parts = screen.split(",")
|
||||
android_ver = parts[2] if len(parts) >= 3 else "11"
|
||||
ua = (
|
||||
f"Mozilla/5.0 (Linux; Android {android_ver}; {device_info.get('model', '')} "
|
||||
"Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Version/4.0 Chrome/149.0.7827.159 Mobile Safari/537.36 "
|
||||
f"huya adr/13.4.22/{device_info.get('vendor', 'android')}/30"
|
||||
)
|
||||
hint = {
|
||||
"model": device_info.get("model", ""),
|
||||
"vendor": device_info.get("vendor", "android"),
|
||||
"androidVer": android_ver,
|
||||
"appVer": str(device_info.get("app_version", "13.4.22")),
|
||||
"userAgent": ua,
|
||||
"screenWidth": int(device_info.get("width", 1080) or 1080),
|
||||
"screenHeight": int(device_info.get("height", 2120) or 2120),
|
||||
}
|
||||
path = state_dir / "device.json"
|
||||
path.write_text(json.dumps(hint, ensure_ascii=False), encoding="utf-8")
|
||||
return path
|
||||
|
||||
|
||||
def get_huya_sdid(
|
||||
app_id: str = "5008",
|
||||
state_dir: str | Path | None = None,
|
||||
@@ -109,6 +145,7 @@ def get_huya_sdid(
|
||||
proxies: Mapping | None = None,
|
||||
timeout: tuple[float, float] = DEFAULT_TIMEOUT,
|
||||
allow_fallback: bool = True,
|
||||
device_hint: Mapping | None = None,
|
||||
) -> HuyaSdidResult:
|
||||
"""获取虎牙高信任 sdid;node 链路失败时可选降级为低信任指纹。
|
||||
|
||||
@@ -125,6 +162,9 @@ def get_huya_sdid(
|
||||
if state_dir is None:
|
||||
state_dir = Path(tempfile.gettempdir()) / "huya_fp_state"
|
||||
state_dir = Path(state_dir)
|
||||
if device_hint:
|
||||
# 一号一设备: 账号画像 → hydevice 设备覆盖 (UA/屏幕/机型)
|
||||
write_device_hint(state_dir, device_hint)
|
||||
try:
|
||||
sdid, hdid = _run_node_runner(state_dir, app_id, timeout)
|
||||
if sdid:
|
||||
|
||||
Reference in New Issue
Block a user