虎牙人工兑换改用本机浏览器并新增扩展自动注入登录态
移除服务器浏览器方案(容器/Xvfb/noVNC/CDP 会话管理),后端仅下发 兑换材料;新增内置 Chrome/Edge 扩展一键写入 huya.com 登录态, 未安装扩展时回退控制台脚本手动注入,兑换始终由用户手动完成。
This commit is contained in:
@@ -30,7 +30,7 @@ from core.huya import (
|
||||
login_huya_sms,
|
||||
send_huya_sms_code,
|
||||
)
|
||||
from core.huya.cookie_utils import normalize_huya_cookie
|
||||
from core.huya.cookie_utils import browser_login_script, cookie_pairs, normalize_huya_cookie
|
||||
from core.huya.device_fingerprint import account_state_dir as _fp_state_dir
|
||||
from core.huya.device_profile import (
|
||||
_load_db as _load_profile_db,
|
||||
@@ -90,6 +90,7 @@ from ..services.huya_register_runner import (
|
||||
list_success_logs,
|
||||
)
|
||||
from ..services.huya_runner import HuyaBatchRunner, huya_batch_registry
|
||||
from ..services.huya_runner_bind import BindMixin
|
||||
from ..services.huya_service import (
|
||||
HUYA_CONFIG_FIELDS,
|
||||
SUPPORTED_TASK_TYPES,
|
||||
@@ -107,6 +108,36 @@ from ..services.huya_service import (
|
||||
router = APIRouter(prefix="/api/huya", tags=["虎牙"])
|
||||
|
||||
|
||||
@router.post("/accounts/{account_id}/browser-exchange")
|
||||
def create_browser_exchange_kit(
|
||||
account_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current: User = Depends(get_current_user),
|
||||
):
|
||||
"""生成指定账号的本机浏览器人工兑换材料。
|
||||
|
||||
登录态由前端引导用户在自己的 Chrome/Edge 中写入,服务端不托管浏览器会话。
|
||||
"""
|
||||
_require_huya_perm(current, "huya:task")
|
||||
account = _visible_huya_accounts_query(db, current).filter(HuyaAccount.id == account_id).first()
|
||||
if account is None:
|
||||
raise HTTPException(status_code=404, detail="虎牙账号不存在或无权操作")
|
||||
if not account.cookie:
|
||||
raise HTTPException(status_code=400, detail="该账号没有可用 Cookie,请先登录")
|
||||
config = ensure_huya_config(db)
|
||||
target_url = BindMixin._bind_redirect_url({
|
||||
"room_pid": huya_config_value("room_pid", config.room_pid),
|
||||
}) or "https://zt.huya.com/b02faae1/pc/index.html"
|
||||
pairs = dict(cookie_pairs(normalize_huya_cookie(account.cookie)))
|
||||
return {
|
||||
"account_id": account.id,
|
||||
"username": account.username or account.yyuid or "",
|
||||
"target_url": target_url,
|
||||
"cookie_string": "; ".join(f"{key}={value}" for key, value in pairs.items()),
|
||||
"cookie_script": browser_login_script(pairs, target_url),
|
||||
}
|
||||
|
||||
|
||||
def _has_huya_perm(user: User, permission: str) -> bool:
|
||||
"""虎牙新权限兼容旧的 huya:account 大权限。"""
|
||||
return user_has_permission(user, permission) or user_has_permission(
|
||||
@@ -323,6 +354,7 @@ def _account_out(account: HuyaAccount, include_cookie: bool = True) -> HuyaAccou
|
||||
yyuid=account.yyuid or "",
|
||||
username=account.username or "",
|
||||
has_password=bool(account.account_password),
|
||||
has_cookie=bool(account.cookie),
|
||||
nickname=account.nickname or "",
|
||||
cookie=cookie if include_cookie else "",
|
||||
cookie_preview=_fmt_cookie_preview(cookie) if include_cookie else "***",
|
||||
@@ -344,7 +376,7 @@ def _account_out(account: HuyaAccount, include_cookie: bool = True) -> HuyaAccou
|
||||
|
||||
|
||||
def _account_out_light(
|
||||
account: HuyaAccount, *, has_password: bool = False
|
||||
account: HuyaAccount, *, has_password: bool = False, has_cookie: bool = False
|
||||
) -> HuyaAccountOut:
|
||||
"""虎牙账号列表轻量输出,不读取加密字段。"""
|
||||
return HuyaAccountOut(
|
||||
@@ -353,6 +385,7 @@ def _account_out_light(
|
||||
yyuid=account.yyuid or "",
|
||||
username=account.username or "",
|
||||
has_password=has_password,
|
||||
has_cookie=has_cookie,
|
||||
nickname=account.nickname or "",
|
||||
cookie="",
|
||||
cookie_preview="***",
|
||||
@@ -480,6 +513,17 @@ def _huya_password_state_map(db: Session, account_ids: list[int]) -> dict[int, b
|
||||
return {account_id: bool(has_password) for account_id, has_password in rows}
|
||||
|
||||
|
||||
def _huya_cookie_state_map(db: Session, account_ids: list[int]) -> dict[int, bool]:
|
||||
if not account_ids:
|
||||
return {}
|
||||
rows = (
|
||||
db.query(HuyaAccount.id, (HuyaAccount.cookie != "").label("has_cookie"))
|
||||
.filter(HuyaAccount.id.in_(account_ids))
|
||||
.all()
|
||||
)
|
||||
return {account_id: bool(has_cookie) for account_id, has_cookie in rows}
|
||||
|
||||
|
||||
@router.get("/task-types")
|
||||
def task_types(current: User = Depends(require_permission("huya:task"))):
|
||||
"""返回当前规划的虎牙任务类型。"""
|
||||
@@ -531,9 +575,12 @@ def list_accounts(
|
||||
password_map = _huya_password_state_map(
|
||||
db, [account.id for account in accounts]
|
||||
)
|
||||
cookie_map = _huya_cookie_state_map(db, [account.id for account in accounts])
|
||||
result = [
|
||||
_account_out_light(
|
||||
account, has_password=password_map.get(account.id, False)
|
||||
account,
|
||||
has_password=password_map.get(account.id, False),
|
||||
has_cookie=cookie_map.get(account.id, False),
|
||||
)
|
||||
for account in accounts
|
||||
]
|
||||
|
||||
@@ -428,6 +428,7 @@ class HuyaAccountOut(BaseModel):
|
||||
yyuid: str = ""
|
||||
username: str = ""
|
||||
has_password: bool = False
|
||||
has_cookie: bool = False
|
||||
nickname: str = ""
|
||||
cookie: str = ""
|
||||
cookie_preview: str = ""
|
||||
@@ -455,6 +456,7 @@ class HuyaAccountOut(BaseModel):
|
||||
"yyuid": self.yyuid,
|
||||
"username": self.username,
|
||||
"has_password": self.has_password,
|
||||
"has_cookie": self.has_cookie,
|
||||
"nickname": self.nickname,
|
||||
"cookie": self.cookie,
|
||||
"cookie_preview": self.cookie_preview,
|
||||
|
||||
Reference in New Issue
Block a user