切换虎牙宝典开通任务到WSS会话

This commit is contained in:
yml2213
2026-09-01 12:20:58 +08:00
parent c195430845
commit aab84e0fb5
5 changed files with 175 additions and 4 deletions
+2
View File
@@ -2,6 +2,7 @@
from typing import TYPE_CHECKING
from .elite_session import HuyaEliteWssSession
from .http_client import HuyaHttpClient
from .wss_client import HuyaWssClient
@@ -39,6 +40,7 @@ __all__ = [
"HuyaAppPasswordLogin",
"HuyaAppQrAuthRequiredError",
"HuyaCredentialError",
"HuyaEliteWssSession",
"HuyaHttpClient",
"HuyaLoginError",
"HuyaLoginResult",
+136
View File
@@ -0,0 +1,136 @@
"""虎牙精英宝典的同步 WSS 会话封装。
任务执行器运行在线程中,使用本类把异步 WSS 生命周期限制在一个账号任务内,
避免在每次 RPC 时重复建连,也不把 asyncio 对象跨线程传递。
"""
from __future__ import annotations
import asyncio
import urllib.parse
from collections.abc import Callable
from typing import Literal
from .http_client import HuyaHttpClient, generate_http_baseinfo
from .wss_client import ACTIVITY_WS_HOST, SHOP_BASEINFO, SHOP_WS_HOST, HuyaWssClient
class HuyaEliteWssSession:
"""一个账号、一个通道、一个可复用的同步 WSS 会话。"""
def __init__(
self,
uid: int,
cookie: str,
kind: Literal["activity", "shop"],
logger: Callable[[str], None] | None = None,
host: str | None = None,
):
self.uid = int(uid or 0)
self.cookie = cookie or ""
self.kind = kind
self.logger = logger or (lambda _message: None)
self.loop = asyncio.new_event_loop()
self.client: HuyaWssClient | None = None
self._closed = False
if kind == "activity":
guid = HuyaHttpClient._resolve_cookie_guid(self.cookie)
baseinfo = urllib.parse.unquote(
generate_http_baseinfo(self.uid, guid, "")
)
connect_host = host or ACTIVITY_WS_HOST
origin = "https://zt.huya.com"
else:
baseinfo = SHOP_BASEINFO
connect_host = host or SHOP_WS_HOST
origin = "https://m-shop.yaoguo.com"
self.client = HuyaWssClient(baseinfo=baseinfo, logger=self.logger)
try:
self.loop.run_until_complete(
self.client.connect(host=connect_host, origin=origin, cookie=self.cookie)
)
initialized = self.loop.run_until_complete(
self.client.initialize_activity(self.uid, "", self.cookie)
if kind == "activity"
else self.client.initialize(self.uid, "", self.cookie)
)
if not initialized:
raise RuntimeError(f"虎牙 {kind} WSS 初始化失败")
except Exception:
self.close()
raise
def _run(self, coroutine):
if self._closed or self.client is None:
raise RuntimeError("虎牙 WSS 会话已关闭")
return self.loop.run_until_complete(coroutine)
def close(self):
if self._closed:
return
self._closed = True
if self.client is not None and self.client.ws is not None:
try:
self.loop.run_until_complete(self.client.disconnect())
except Exception: # noqa: BLE001 - cleanup must not mask task result
self.logger("[WSS] 会话清理异常")
self.loop.close()
def __enter__(self):
return self
def __exit__(self, _exc_type, _exc, _tb):
self.close()
def get_act_info(self, act_id: int):
return self._run(self.client.get_act_info(act_id))
def get_act_task_detail(self, uid: int, cookie: str, act_id: int):
return self._run(self.client.get_act_task_detail(uid, cookie, act_id))
def get_act_user_task_detail(self, uid: int, cookie: str, act_id: int):
return self._run(self.client.get_act_user_task_detail(uid, cookie, act_id))
def get_user_score(self, uid: int, cookie: str, sid: int):
return self._run(self.client.get_user_score(uid, cookie, sid))
def get_act_prize_list(self, uid: int, cookie: str, sid: int):
return self._run(self.client.get_act_prize_list(uid, cookie, sid))
def get_act_prize_detail(self, uid: int, cookie: str, sid: int, pid: int):
return self._run(self.client.get_act_prize_detail(uid, cookie, sid, pid))
def score_exchange_prize(self, uid: int, cookie: str, sid: int, pid: int):
return self._run(self.client.score_exchange_prize(uid, cookie, sid, pid))
def get_user_prize_records(self, uid: int, cookie: str, sid: int):
return self._run(self.client.get_user_prize_records(uid, cookie, sid))
def get_goods_info(self, **kwargs):
return self._run(self.client.get_goods_info(**kwargs))
def list_pay_channels(self, **kwargs):
return self._run(self.client.list_pay_channels(**kwargs))
def check_hy_protocol(self, **kwargs):
return self._run(self.client.check_hy_protocol(**kwargs))
def check_user_buy_auth(self, **kwargs):
return self._run(self.client.check_user_buy_auth(**kwargs))
def create_order(self, **kwargs):
return self._run(self.client.create_order(**kwargs))
def pay_order_submit(self, **kwargs):
return self._run(self.client.pay_order_submit(**kwargs))
def order_detail(self, **kwargs):
return self._run(self.client.order_detail(**kwargs))
def query_user_order_list(self, **kwargs):
return self._run(self.client.query_user_order_list(**kwargs))
__all__ = ["HuyaEliteWssSession"]