该提交实现了完整的B站渠道插件,包含以下核心功能: 1. 支持B站直播弹幕监听与处理,包含弹幕、SC、礼物等多种直播间事件 2. 支持B站私信的轮询接收与发送 3. 内置WBI签名算法,适配B站API鉴权要求 4. 提供账号配对、黑白名单等弹幕私信权限控制 5. 集成速率限制与防风险机制,降低账号封禁风险 6. 完善的配置管理与状态监控能力
89 lines
2.8 KiB
Python
89 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from yuxi.channel.extensions.bilibili.types import BilibiliAccountConfig
|
|
|
|
|
|
class BilibiliClientManager:
|
|
def __init__(self, account: BilibiliAccountConfig, logger: logging.Logger):
|
|
self._account = account
|
|
self._logger = logger
|
|
self._credential = None
|
|
self._img_key: str | None = None
|
|
self._sub_key: str | None = None
|
|
|
|
@property
|
|
def credential(self):
|
|
if self._credential is None:
|
|
from bilibili_api import Credential
|
|
|
|
self._credential = Credential(
|
|
sessdata=self._account.sessdata,
|
|
bili_jct=self._account.bili_jct,
|
|
buvid3=self._account.buvid3 or "",
|
|
dedeuserid=self._account.dedeuserid,
|
|
)
|
|
return self._credential
|
|
|
|
@property
|
|
def img_key(self) -> str | None:
|
|
return self._img_key
|
|
|
|
@property
|
|
def sub_key(self) -> str | None:
|
|
return self._sub_key
|
|
|
|
async def setup(self) -> None:
|
|
try:
|
|
from bilibili_api import select_client
|
|
|
|
select_client("curl_cffi")
|
|
try:
|
|
from bilibili_api import request_settings
|
|
|
|
request_settings.set("impersonate", "chrome131")
|
|
except Exception:
|
|
pass
|
|
except Exception:
|
|
self._logger.warning("curl_cffi 不可用,回退到 aiohttp")
|
|
try:
|
|
from bilibili_api import select_client
|
|
|
|
select_client("aiohttp")
|
|
except Exception:
|
|
pass
|
|
|
|
await self._fetch_wbi_keys()
|
|
|
|
async def verify_credential(self) -> bool:
|
|
try:
|
|
from bilibili_api import user
|
|
|
|
u = user.User(self.credential)
|
|
info = await u.get_user_info()
|
|
return info is not None
|
|
except Exception as e:
|
|
self._logger.error(f"Cookie 验证失败: {e}")
|
|
return False
|
|
|
|
async def _fetch_wbi_keys(self) -> None:
|
|
try:
|
|
import httpx
|
|
|
|
async with httpx.AsyncClient() as client:
|
|
resp = await client.get(
|
|
"https://api.bilibili.com/x/web-interface/nav",
|
|
cookies=self.credential.get_cookies(),
|
|
)
|
|
data = resp.json()
|
|
wbi_img = data.get("data", {}).get("wbi_img", {})
|
|
img_url = wbi_img.get("img_url", "")
|
|
sub_url = wbi_img.get("sub_url", "")
|
|
if img_url and sub_url:
|
|
self._img_key = img_url.rsplit("/", 1)[-1].split(".")[0]
|
|
self._sub_key = sub_url.rsplit("/", 1)[-1].split(".")[0]
|
|
self._logger.debug("WBI keys 已获取")
|
|
except Exception:
|
|
self._logger.warning("WBI key 获取失败,部分 API 可能不可用")
|