Files
live-hub-py/core/huya/cookie_utils.py
T

97 lines
3.0 KiB
Python

"""虎牙 Cookie 规范化工具。"""
from __future__ import annotations
import json
from collections.abc import Iterable, Mapping
from requests.cookies import RequestsCookieJar
def cookie_pairs(cookie: str) -> list[tuple[str, str]]:
"""把浏览器 Cookie 字符串拆成 key/value 对。"""
pairs: list[tuple[str, str]] = []
for part in (cookie or "").split(";"):
item = part.strip()
if not item or "=" not in item:
continue
key, value = item.split("=", 1)
key = key.strip()
if not key:
continue
pairs.append((key, value.strip()))
return pairs
def normalize_cookie_pairs(pairs: Iterable[tuple[str, str]]) -> str:
"""按 Cookie key 去重,保留最后一次出现的值。"""
ordered_keys: list[str] = []
values: dict[str, str] = {}
for raw_key, raw_value in pairs:
key = str(raw_key).strip()
if not key:
continue
if key not in values:
ordered_keys.append(key)
values[key] = "" if raw_value is None else str(raw_value).strip()
return "; ".join(f"{key}={values[key]}" for key in ordered_keys)
def normalize_huya_cookie(
cookie: str | Mapping[str, str] | RequestsCookieJar | None,
) -> str:
"""把 Cookie 字符串、dict 或 CookieJar 转成去重后的浏览器 Cookie 字符串。"""
if not cookie:
return ""
if isinstance(cookie, str):
return normalize_cookie_pairs(cookie_pairs(cookie))
return normalize_cookie_pairs(
[
(str(key), "" if value is None else str(value))
for key, value in cookie.items()
]
)
def cookie_value(
cookie: str | Mapping[str, str] | RequestsCookieJar | None, key: str
) -> str:
"""从 Cookie 中读取 key;有重复时以最后一次出现为准。"""
if not cookie or not key:
return ""
if isinstance(cookie, str):
pairs = cookie_pairs(cookie)
else:
pairs = list(cookie.items())
value = ""
for item_key, item_value in pairs:
if item_key == key:
value = "" if item_value is None else str(item_value).strip()
return value
def browser_login_script(
pairs: Mapping[str, str],
target_url: str,
*,
domain: str = ".huya.com",
ttl_days: int = 180,
) -> str:
"""生成在用户自己浏览器控制台执行的登录脚本。
脚本把 Cookie 写入指定域后跳转目标页;Cookie 值以 JSON 数组内联,
保证引号、反斜杠等字符安全转义。
"""
payload = json.dumps(
[[key, value] for key, value in pairs.items()], ensure_ascii=False
)
target = json.dumps(target_url, ensure_ascii=False)
ttl_ms = max(1, ttl_days) * 86_400_000
return (
f"(function(){{var c={payload};"
f"var e=new Date(Date.now()+{ttl_ms}).toUTCString();"
f"for(var i=0;i<c.length;i++){{"
f"document.cookie=c[i][0]+'='+c[i][1]+';domain={domain};path=/;expires='+e;"
f"}}location.href={target};}})();"
)