From 8f368783fedcd32d027332ebce9bd39e3bb0cf88 Mon Sep 17 00:00:00 2001 From: bcxc Date: Fri, 3 Apr 2026 00:51:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=9C=A8SUB2API=E4=B8=AD?= =?UTF-8?q?=E9=92=88=E5=AF=B9=E8=B4=A6=E5=8F=B7=E7=AE=A1=E7=90=86=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E5=88=86=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/config.py | 1 + frontend/src/pages/Settings.tsx | 1 + platforms/chatgpt/sub2api_upload.py | 31 +++++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/api/config.py b/api/config.py index 110dd03..605cb20 100644 --- a/api/config.py +++ b/api/config.py @@ -61,6 +61,7 @@ CONFIG_KEYS = [ "cpa_cleanup_register_delay_seconds", "sub2api_api_url", "sub2api_api_key", + "sub2api_group_ids", "team_manager_url", "team_manager_key", "codex_proxy_url", diff --git a/frontend/src/pages/Settings.tsx b/frontend/src/pages/Settings.tsx index df1cf65..9c41d2c 100644 --- a/frontend/src/pages/Settings.tsx +++ b/frontend/src/pages/Settings.tsx @@ -203,6 +203,7 @@ const TAB_ITEMS = [ fields: [ { key: 'sub2api_api_url', label: 'API URL', placeholder: 'https://your-sub2api.example.com' }, { key: 'sub2api_api_key', label: 'API Key', secret: true }, + { key: 'sub2api_group_ids', label: '分组 ID', placeholder: '多个分组用英文逗号分隔,例如 2,4,8' }, ], }, { diff --git a/platforms/chatgpt/sub2api_upload.py b/platforms/chatgpt/sub2api_upload.py index 0ed880e..a1d80a6 100644 --- a/platforms/chatgpt/sub2api_upload.py +++ b/platforms/chatgpt/sub2api_upload.py @@ -29,6 +29,30 @@ def _get_config_value(key: str) -> str: return "" +def _parse_group_ids(raw: Any, fallback: list[int] | None = None) -> list[int]: + candidates: list[Any] + if isinstance(raw, str): + candidates = [part.strip() for part in raw.split(",")] + elif isinstance(raw, (list, tuple, set)): + candidates = list(raw) + elif raw is None: + candidates = [] + else: + candidates = [raw] + + values: list[int] = [] + for item in candidates: + text = str(item or "").strip() + if not text: + continue + try: + values.append(int(text)) + except ValueError: + continue + + return values or list(fallback or DEFAULT_GROUP_IDS) + + def _decode_jwt_payload(token: str) -> dict[str, Any]: try: parts = str(token or "").split(".") @@ -101,7 +125,7 @@ def _build_sub2api_account_payload(account, group_ids: list[int] | None = None) "id_token": id_token, }, "extra": {"email": email}, - "group_ids": group_ids or DEFAULT_GROUP_IDS, + "group_ids": _parse_group_ids(group_ids), "concurrency": 10, "priority": 1, "auto_pause_on_expired": True, @@ -117,13 +141,16 @@ def upload_to_sub2api( """上传单个账号到 Sub2API 管理后台。""" api_url = str(api_url or _get_config_value("sub2api_api_url")).strip() api_key = str(api_key or _get_config_value("sub2api_api_key")).strip() + resolved_group_ids = _parse_group_ids( + _get_config_value("sub2api_group_ids") if group_ids is None else group_ids + ) if not api_url: return False, "Sub2API API URL 未配置" if not api_key: return False, "Sub2API API Key 未配置" - payload = _build_sub2api_account_payload(account, group_ids=group_ids) + payload = _build_sub2api_account_payload(account, group_ids=resolved_group_ids) url = f"{api_url.rstrip('/')}/api/v1/admin/accounts" headers = { "Content-Type": "application/json",