补齐虎牙宝典活动与商城WSS协议

This commit is contained in:
yml2213
2026-09-01 11:46:40 +08:00
parent eb065a7c77
commit 3aca102741
+140
View File
@@ -31,6 +31,7 @@ from .taf_protocol import TafInputStream, TafOutputStream, TafStruct, TafType
from .wup_protocol import WupRequest, WupResponse from .wup_protocol import WupRequest, WupResponse
SHOP_WS_HOST = "77bc035c-ws.va.huya.com" SHOP_WS_HOST = "77bc035c-ws.va.huya.com"
ACTIVITY_WS_HOST = "d35bf373-ws.va.huya.com"
# 商城端点 baseinfo (conn4, h5_/index.html) — 商城业务 shopMiddleUI 走此通道 # 商城端点 baseinfo (conn4, h5_/index.html) — 商城业务 shopMiddleUI 走此通道
# wsLaunch tReq: lUid=0, sGuid="", sUA="webh5&0.0.1&websocket&&h5_/index.html" # wsLaunch tReq: lUid=0, sGuid="", sUA="webh5&0.0.1&websocket&&h5_/index.html"
SHOP_BASEINFO = "DBYAJiV3ZWJoNSYwLjAuMSZ3ZWJzb2NrZXQmJmg1Xy9pbmRleC5odG1sNgxIVVlBJlpIJjIwNTJGAFYAbHYAhgCWAKgM" SHOP_BASEINFO = "DBYAJiV3ZWJoNSYwLjAuMSZ3ZWJzb2NrZXQmJmg1Xy9pbmRleC5odG1sNgxIVVlBJlpIJjIwNTJGAFYAbHYAhgCWAKgM"
@@ -41,6 +42,20 @@ WSS_BIZ_UA = "web&1.0.0&huya"
WSS_COOKIE_UA = "webh5&0.0.1&websocket&&diypc_52775" WSS_COOKIE_UA = "webh5&0.0.1&websocket&&diypc_52775"
WSS_SHOP_SCENE = 4 WSS_SHOP_SCENE = 4
class _ActivityConfigReq(TafStruct):
def __init__(self, user):
self.user = user
def write_to(self, os: TafOutputStream):
os.write_struct(0, self.user)
os.write_map(1, {})
os.write_string(2, "huya")
os.write_list(3, [])
def read_from(self, _ins):
pass
# seq 按消息类型固定 (HAR 实证,跨两次抓包一致) # seq 按消息类型固定 (HAR 实证,跨两次抓包一致)
SEQ_HEARTBEAT = 0x1D00000D SEQ_HEARTBEAT = 0x1D00000D
SEQ_WSLAUNCH = 0x1D000078 SEQ_WSLAUNCH = 0x1D000078
@@ -341,6 +356,66 @@ class HuyaWssClient:
self.logger("[初始化] 完成 ✓") self.logger("[初始化] 完成 ✓")
return True return True
async def initialize_activity(self, uid: int, guid: str, cookie: str):
"""活动通道初始化:heartbeat -> wsLaunch -> AUTH -> getConfig -> confirm。"""
await self.send_heartbeat()
launch_rsp = await self.call_ws_launch_activity(uid, guid)
if launch_rsp is None:
return False
await self.send_auth(cookie)
await self.call_get_config_activity(uid, cookie)
await self.send_confirm()
await asyncio.sleep(0.1)
return True
async def call_ws_launch_activity(self, uid: int, guid: str = "", timeout: float = 10.0):
ua = WSS_COOKIE_UA
os = TafOutputStream()
os.write_struct_begin(0)
os.write_int64(0, int(uid or 0))
os.write_string(1, guid or "")
os.write_string(2, ua)
os.write_string(3, "HUYA&ZH&2052")
os.write_struct_begin(4)
for i in range(5):
os.write_string(i, "")
os.write_struct_end()
os.write_struct_end()
wup = WupRequest()
wup.setServant("launch")
wup.setFunc("wsLaunch")
wup.setRequestId(-1)
wup.iTimeout = 0
wup.newdata["tReq"] = os.get_bytes()
body = self._encode_rpc_body(wup.encode())
msg = WssMessage(WssCommand.RPC_REQUEST, SEQ_WSLAUNCH, body)
future = asyncio.Future()
self.rpc_queue.append(future)
await self.ws.send(msg.encode())
try:
response = await asyncio.wait_for(future, timeout)
except TimeoutError:
if future in self.rpc_queue:
self.rpc_queue.remove(future)
return None
self._parse_launch_response(response)
return response
async def call_get_config_activity(self, uid: int, cookie: str, timeout: float = 10.0):
user = self._build_activity_user(uid, cookie)
req = _ActivityConfigReq(user)
return await self.call_rpc("mobileui", "getConfig", req, None, timeout=timeout)
@staticmethod
def _build_activity_user(uid: int, cookie: str):
from .activity_structs import ActivityUserId
user = ActivityUserId()
user.lUid = int(uid or 0)
user.sHuYaUA = WSS_COOKIE_UA
user.sCookie = HuyaWssClient._normalize_biz_cookie(cookie)
return user
async def call_ws_launch_shop(self, timeout: float = 10.0): async def call_ws_launch_shop(self, timeout: float = 10.0):
"""商城版 wsLaunch (匿名, 无 lUid/sGuid, 与 conn4 格式一致)""" """商城版 wsLaunch (匿名, 无 lUid/sGuid, 与 conn4 格式一致)"""
ua = "webh5&0.0.1&websocket&&h5_/index.html" ua = "webh5&0.0.1&websocket&&h5_/index.html"
@@ -656,6 +731,71 @@ class HuyaWssClient:
"shopMiddleUI", "getGoodsInfoV5", req, GoodsInfoRsp, timeout=15.0 "shopMiddleUI", "getGoodsInfoV5", req, GoodsInfoRsp, timeout=15.0
) )
async def get_act_info(self, act_id: int):
from .activity_structs import GetActInfoReq, GetActInfoResp
req = GetActInfoReq()
req.actId = int(act_id or 0)
return await self.call_rpc("webActUI", "getActInfo", req, GetActInfoResp)
async def get_act_task_detail(self, uid: int, cookie: str, act_id: int):
from .activity_structs import GetActTaskDetailReq, GetActTaskDetailResp
req = GetActTaskDetailReq()
req.userId = self._build_activity_user(uid, cookie)
req.actId = int(act_id or 0)
return await self.call_rpc("webActUI", "getActTaskDetail", req, GetActTaskDetailResp)
async def get_act_user_task_detail(self, uid: int, cookie: str, act_id: int):
from .activity_structs import GetActUserTaskDetailReq, GetActUserTaskDetailResp
req = GetActUserTaskDetailReq()
req.userId = self._build_activity_user(uid, cookie)
req.actId = int(act_id or 0)
return await self.call_rpc("webActUI", "getActUserTaskDetail", req, GetActUserTaskDetailResp)
async def get_user_score(self, uid: int, cookie: str, sid: int):
from .activity_structs import GetUserScoreReq, GetUserScoreResp
req = GetUserScoreReq()
req.userId = self._build_activity_user(uid, cookie)
req.sid = int(sid or 0)
return await self.call_rpc("webActUI", "getUserScore", req, GetUserScoreResp)
async def get_act_prize_list(self, uid: int, cookie: str, sid: int):
from .activity_structs import GetActPrizeListReq, GetActPrizeListResp
req = GetActPrizeListReq()
req.userId = self._build_activity_user(uid, cookie)
req.sid = int(sid or 0)
return await self.call_rpc("webActUI", "getActPrizeList", req, GetActPrizeListResp)
async def get_act_prize_detail(self, uid: int, cookie: str, sid: int, pid: int):
from .activity_structs import GetActPrizeDetailReq, GetActPrizeDetailResp
req = GetActPrizeDetailReq()
req.userId = self._build_activity_user(uid, cookie)
req.sid = int(sid or 0)
req.pid = int(pid or 0)
return await self.call_rpc("webActUI", "getActPrizeDetail", req, GetActPrizeDetailResp)
async def score_exchange_prize(self, uid: int, cookie: str, sid: int, pid: int):
from .activity_structs import ScoreExchangePrizeReq, ScoreExchangePrizeResp
req = ScoreExchangePrizeReq()
req.userId = self._build_activity_user(uid, cookie)
req.sid = int(sid or 0)
req.pid = int(pid or 0)
return await self.call_rpc("webActUI", "scoreExchangePrize", req, ScoreExchangePrizeResp)
async def get_user_prize_records(self, uid: int, cookie: str, sid: int):
from .activity_structs import GetUserPrizeRecordsReq, GetUserPrizeRecordsResp
req = GetUserPrizeRecordsReq()
req.userId = self._build_activity_user(uid, cookie)
req.sid = int(sid or 0)
return await self.call_rpc("webActUI", "getUserPrizeRecords", req, GetUserPrizeRecordsResp)
async def list_pay_channels( async def list_pay_channels(
self, uid: int, guid: str, cookie: str, spu_id: str, sku_id: int = 0, self, uid: int, guid: str, cookie: str, spu_id: str, sku_id: int = 0,
supplier_id: int = 87401, supplier_id: int = 87401,