Files
live-hub-py/core/huya/device_profile.py
T
yml2213 0c86e182b0 feat(huya): 零设备 dfpReport 注册链迁入 core/huya 并接入生产登录
- 新增 core/huya/dfp_register: 随机 4146B cw 生成 + 注册响应解析 (t1/t2/t5),
  修复 JSON 模板 %s 数不匹配的 TypeError bug
- app_login 每次 WUP 登录前执行注册链取新 safedeviceid/device_id,
  不再读取画像旧固定值; 注册失败抛 HuyaAppLoginError 终止, 不静默回退旧链
- device_profile 移除固定 SAFEDEVICEID_DEFAULT, 画像只承载 soft 字段
- tools/huya_device_register 同步零设备生成链路 (--gen/--gen-login)
- 新增 tests/test_huya_dfp_register (9 项), 扩展 test_huya_app_login 注册接线 (4 项)
2026-08-27 17:47:53 +08:00

101 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""虎牙多账号设备画像生成与管理。
为每个账号生成并持久化独立的设备身份画像(机型、屏幕、指纹、设备ID等)。
注意:画像只承载 *soft* 设备字段(机型/屏幕/随机指纹/随机 device_id)。
``safedeviceid``RSA action 令牌)与登录帧 ``device_id`` 由
:mod:`core.huya.dfp_register` 在每次 WUP 登录前经新设备注册链实时签发,
不再写入画像,也不再允许任何固定金样本令牌被多账号复用。
"""
from __future__ import annotations
import hashlib
import json
import os
import random
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent.parent
DATA_DIR = ROOT / "data"
PRIMARY_PROFILE_DB = DATA_DIR / "huya_device_profiles.json"
FALLBACK_PROFILE_DB = ROOT / "evidence" / "device_profiles.json"
REAL_MODELS = [
("xiaomi", "M2102J2SC", "M2102J2SC,30,11", (1080, 2120)),
("vivo", "V2370A", "V2370A,34,13", (1080, 2412)),
("oppo", "PFFM20", "PFFM20,34,13", (1080, 2412)),
("honor", "SDY-AN00", "SDY-AN00,31,12", (1080, 2400)),
("samsung", "SM-G9910", "SM-G9910,31,12", (1440, 3200)),
("oneplus", "PGZ110", "PGZ110,34,13", (1080, 2412)),
("redmi", "23049PCD8G", "23049PCD8G,34,13", (1080, 2400)),
("realme", "RMX3366", "RMX3366,34,13", (1080, 2412)),
("iqoo", "V2183A", "V2183A,34,13", (1080, 2400)),
("nubia", "NX729J", "NX729J,33,13", (1080, 2400)),
("motorola", "XT2301-5", "XT2301-5,33,13", (1080, 2400)),
("gionee", "GN9013", "GN9013,29,10", (720, 1560)),
]
HDID = "ed0db8334cadd236c00cadf7e11ab5a5"
APP_VERSION = "13.4.22"
SDK_VERSION = "1.0.80138"
def _rand_sha1_hex() -> str:
return hashlib.sha1(os.urandom(20)).hexdigest()
def generate_profile(model_pick=None) -> dict:
"""生成一套随机设备画像。"""
vendor, model, screen, (w, h) = (
random.choice(REAL_MODELS) if model_pick is None else model_pick
)
return {
"app_version": APP_VERSION,
"sdk_version": SDK_VERSION,
"vendor": vendor,
"model": model,
"os": "android",
"ip": "127.0.0.1",
"fingerprint": _rand_sha1_hex(),
"screen": screen,
"width": str(w),
"height": str(h),
"device_id": _rand_sha1_hex(),
"hdid": HDID,
# 注: 不含 safedeviceid —— 每次登录前由 dfp_register 注册链签发,
# 画像不再持久化固定令牌 (见模块注释)。
}
def _load_db() -> dict:
if PRIMARY_PROFILE_DB.exists():
try:
return json.loads(PRIMARY_PROFILE_DB.read_text("utf-8"))
except Exception:
pass
if FALLBACK_PROFILE_DB.exists():
try:
return json.loads(FALLBACK_PROFILE_DB.read_text("utf-8"))
except Exception:
pass
return {}
def _save_db(db: dict) -> None:
try:
PRIMARY_PROFILE_DB.parent.mkdir(parents=True, exist_ok=True)
PRIMARY_PROFILE_DB.write_text(json.dumps(db, indent=2, ensure_ascii=False), encoding="utf-8")
except Exception:
pass
def get_profile(account: str, force_new: bool = False) -> dict:
"""按账号获取或创建画像(幂等:同账号复用同一套)。"""
db = _load_db()
if not force_new and account in db:
return db[account]
p = generate_profile()
db[account] = p
_save_db(db)
return p