Files
live-hub-py/core/huya/web_cookie_fields.py
T
yml2213 5dc736516f 补齐网页Cookie缺失字段并接入会话自动预取guid
- 新增 core/huya/web_cookie_fields.py:4 核心设备字段(guid 取自 wsLaunch 会话、
  _qimei_uuid42/__yamid_new/game_did 随机对齐格式)+ qimei 皮肤 + 22 个统计/会话字段
- elite_session 活动通道初始化时若缺网页字段,先 wsLaunch 预取服务端认可 guid,
  补齐 cookie 后重建会话;业务 RPC 统一走补齐后的 cookie
- 实测:账号 id=58(原始 16 字段登录态)checkUserBindGameAccount status=200
  (和平精英已绑定/收麦季)、getUserScore status=200(积分 4880)
- 附补齐方案与浏览器实测来源记录 docs/HUYA_CHAT_缺失字段补齐方案.md
2026-09-01 22:12:58 +08:00

144 lines
4.8 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.
"""虎牙网页 Cookie 缺失字段补齐生成器。
账号 App 登录态只有 16 个 udb_* 认证字段,而活动/商城 WSS 需要完整的网页设备态。
浏览器实测(evidence/browser_cookie_harvest/report.md)确认:
- ``udb_deviceid/udb_guiddata/udb_anobiztoken/udb_anouid`` 由匿名设备态协议
core/huya/anon_device.pymiddle + anonymousLogin)签发;
- ``guid/_qimei_uuid42/__yamid_new/game_did`` 由页面 SDK 脚本写 document.cookie
无服务端签发接口。其中 ``guid`` 与会话强绑定:**wsLaunch 响应返回的新 guid 必须
回写进 cookie**,否则 getConfig 无响应(2026-09-01 实测);
``_qimei_uuid42/__yamid_new/game_did`` 为设备标识,随机值格式对齐即可;
- 其余统计/会话字段(SoundValue/Hm_*/rep_cnt 等)服务端仅记录,可随机生成。
2026-09-01 全链路实测:账号 id=58 补齐后 checkUserBindGameAccount 返回
status=200(和平精英已绑定)、getUserScore 返回 status=200(积分 4880)。
"""
from __future__ import annotations
import secrets
import string
import time
# 统计/会话字段生成规则;9.1 抓包值为样例,格式保持对齐
_FILL_MAP: tuple[tuple[str, str], ...] = (
("SoundValue", "0.50"),
("alphaValue", "0.80"),
("isInLiveRoom", "true"),
("udb_passdata", "3"),
("udb_accdata", "undefined"),
)
def _rand_float() -> str:
import random
return f"{random.random():.17f}"
def fill_web_cookie_fields(
cookie: str,
guid: str,
uid: int | str = 0,
*,
keep_guid: bool = True,
) -> str:
"""补齐网页 Cookie 中缺失的字段。
Args:
cookie: 当前 Cookie(可只有 udb_* 认证字段)。
guid: wsLaunch 响应返回的会话 guid(32hex);缺核心字段时必填。
uid: 虎牙 uid,用于 __yaoldyyuid 等字段。
keep_guid: 已存在 guid 且非空时是否保留(默认 True)。
Returns:
补齐后的 Cookie 字符串(原始字段值不变,仅补缺失项)。
"""
pairs: dict[str, str] = {}
for raw in (cookie or "").split(";"):
item = raw.strip()
if not item or "=" not in item:
continue
key, value = item.split("=", 1)
key = key.strip()
if key:
pairs[key] = value.strip()
def add(key: str, value: str):
if value and key not in pairs:
pairs[key] = value
uid = int(uid or 0)
# 4 个核心设备字段
if guid:
if keep_guid and pairs.get("guid"):
pass # 已有真实 guid 则保留
else:
add("guid", str(guid))
elif "guid" not in pairs:
add("guid", secrets.token_hex(16))
add("_qimei_uuid42", secrets.token_hex(21)) # 42 hex
add("__yamid_new", secrets.token_hex(16).upper()) # 32 hex 大写
alnum = string.ascii_letters + string.digits
import random
add("game_did", "".join(random.choices(alnum, k=30))) # 30 位字母数字
# qimei 皮肤字段
add("_qimei_fingerprint", secrets.token_hex(16))
add("_qimei_h38", secrets.token_hex(19))
# 会话/统计字段
yasmid = _rand_float()
add("__yasmid", yasmid)
add("__yamid_tt1", yasmid)
add("_rep_cnt", str(random.randint(0, 9)))
add("rep_cnt", str(random.randint(0, 9)))
add("h_unt", str(int(time.time())))
if uid:
add("__yaoldyyuid", str(uid))
add("_yasids", "__rootsid%3D" + secrets.token_hex(16).upper())
add("Hm_lvt_51700b6c722f5bb4cf39906a596ea41f", str(int(time.time())))
add("Hm_lpvt_51700b6c722f5bb4cf39906a596ea41f", str(int(time.time())))
add("HMACCOUNT", secrets.token_hex(8).upper())
add("huya_flash_rep_cnt", str(random.randint(1, 400)))
add("huyasp_rep_cnt", str(random.randint(1, 40)))
add("huya_hd_rep_cnt", str(random.randint(1, 40)))
add("huya_web_rep_cnt", str(random.randint(300, 900)))
for key, value in _FILL_MAP:
add(key, value)
return "; ".join(f"{key}={pairs[key]}" for key in pairs)
def missing_web_cookie_fields(cookie: str) -> tuple[str, ...]:
"""返回缺失的网页核心字段(不含统计字段)。"""
from .cookie_utils import cookie_value
core = (
"guid", "_qimei_uuid42", "__yamid_new", "game_did",
"_qimei_fingerprint", "_qimei_h38", "__yasmid", "__yamid_tt1",
"udb_passdata", "_yasids", "HMACCOUNT",
)
return tuple(key for key in core if not cookie_value(cookie, key))
def cookie_fields(cookie: str) -> dict[str, str]:
"""把 Cookie 字符串转 dict(用于测试/调试)。"""
out = {}
for raw in (cookie or "").split(";"):
item = raw.strip()
if not item or "=" not in item:
continue
key, value = item.split("=", 1)
out[key.strip()] = value.strip()
return out
__all__ = [
"cookie_fields",
"fill_web_cookie_fields",
"missing_web_cookie_fields",
]