fix: shorten New-API token names

This commit is contained in:
liumangmang
2026-06-30 16:12:46 +08:00
parent 8bff1c1551
commit 854a640d48
3 changed files with 516 additions and 14 deletions
+56
View File
@@ -1,7 +1,9 @@
"""Upstream HTTP client — ported from monitor_ai98pro_group_rates.py."""
from __future__ import annotations
import hashlib
import json
import re
import time
from typing import Any, Callable, Optional
from urllib.parse import urljoin
@@ -16,6 +18,60 @@ class UpstreamError(RuntimeError):
NEW_API_DEFAULT_QUOTA_PER_UNIT = 500000
# New-API/Nox-API token name 上限(UTF-8 字节)
_NEW_API_TOKEN_NAME_MAX_BYTES = 50
def _utf8_safe_truncate(text: str, max_bytes: int) -> str:
"""按 UTF-8 字节安全截断字符串,不切坏多字节字符。"""
encoded = text.encode("utf-8")
if len(encoded) <= max_bytes:
return text
truncated = encoded[:max_bytes]
# 向后退直到合法 UTF-8 边界
return truncated.decode("utf-8", errors="ignore")
def build_new_api_token_name(
prefix: str,
upstream_id: int | str,
group_id: str,
group_name: str,
) -> str:
"""构造不超过 50 UTF-8 字节的 New-API/Nox-API token 名。
格式:{prefix}-{upstream_id}-{短分组名}-{hash8}
- 短分组名:去除非字母/数字/汉字/_/- 后,UTF-8 安全截断到剩余空间
- hash8sha1("{upstream_id}:{group_id}")[:8],保证同名分组仍能区分
- 若 {prefix}-{upstream_id}-{hash8} 本身超过 50 字节,抛出 ValueError
示例:
SmartUp-7-ClaudeMax智能分组-a1b2c3d4
"""
hash8 = hashlib.sha1(f"{upstream_id}:{group_id}".encode()).hexdigest()[:8]
# 最小骨架:{prefix}-{upstream_id}--{hash8}(含两个分隔符)
skeleton = f"{prefix}-{upstream_id}--{hash8}"
skeleton_bytes = len(skeleton.encode("utf-8"))
if skeleton_bytes > _NEW_API_TOKEN_NAME_MAX_BYTES:
raise ValueError(
f"token name prefix '{prefix}' 过长,骨架 '{skeleton}' 已达 "
f"{skeleton_bytes} 字节(上限 {_NEW_API_TOKEN_NAME_MAX_BYTES}"
)
# 可用于短分组名的字节数
safe_name = re.sub(r"[^a-zA-Z0-9\u4e00-\u9fff_-]", "", group_name or group_id)
# 骨架含一个额外分隔符,留给 group_name 的字节 = max - len(prefix-upid--hash8) - 1
# 即 max - skeleton_bytesskeleton 已包含两个 `-` 和一个 `-` 给 group_name
# 但 skeleton 里 group_name 位置是空的,所以可用字节 = max - skeleton_bytes + 1
# skeleton: prefix-uid--hash8 → prefix-uid-<group>-hash8 多出 group 部分
# 可用字节:_NEW_API_TOKEN_NAME_MAX_BYTES - len(f"{prefix}-{upstream_id}-".encode()) - len(f"-{hash8}".encode())
base_bytes = len(f"{prefix}-{upstream_id}-".encode("utf-8"))
suffix_bytes = len(f"-{hash8}".encode("utf-8"))
group_budget = _NEW_API_TOKEN_NAME_MAX_BYTES - base_bytes - suffix_bytes
short_name = _utf8_safe_truncate(safe_name, group_budget) if group_budget > 0 else ""
return f"{prefix}-{upstream_id}-{short_name}-{hash8}"
def _find_token(value: Any) -> str:
if isinstance(value, str) and value.count(".") >= 2: