上传账号列表到 Codex2API 平台。
(accounts: List[Account], api_url: str, admin_key: str)
| 39 | |
| 40 | |
| 41 | def upload_to_codex2api(accounts: List[Account], api_url: str, admin_key: str) -> Tuple[bool, str]: |
| 42 | """上传账号列表到 Codex2API 平台。""" |
| 43 | if not accounts: |
| 44 | return False, "无可上传的账号" |
| 45 | if not api_url: |
| 46 | return False, "Codex2API URL 未配置" |
| 47 | if not admin_key: |
| 48 | return False, "Codex2API Admin Key 未配置" |
| 49 | |
| 50 | entries = build_codex2api_import_entries(accounts) |
| 51 | if not entries: |
| 52 | return False, "所有账号均缺少 refresh_token / access_token,无法上传" |
| 53 | |
| 54 | payload = json.dumps(entries, ensure_ascii=False, indent=2).encode("utf-8") |
| 55 | filename = f"codex2api_import_{datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%SZ')}.json" |
| 56 | mime = CurlMime() |
| 57 | mime.addpart( |
| 58 | name="file", |
| 59 | data=payload, |
| 60 | filename=filename, |
| 61 | content_type="application/json", |
| 62 | ) |
| 63 | mime.addpart(name="format", data=b"json") |
| 64 | |
| 65 | url = normalize_codex2api_url(api_url) + "/api/admin/accounts/import" |
| 66 | headers = { |
| 67 | "X-Admin-Key": admin_key, |
| 68 | } |
| 69 | |
| 70 | try: |
| 71 | response = cffi_requests.post( |
| 72 | url, |
| 73 | multipart=mime, |
| 74 | headers=headers, |
| 75 | proxies=None, |
| 76 | timeout=60, |
| 77 | impersonate="chrome110", |
| 78 | ) |
| 79 | if response.status_code in (200, 201): |
| 80 | try: |
| 81 | data = response.json() |
| 82 | except Exception: |
| 83 | data = None |
| 84 | if isinstance(data, dict): |
| 85 | message = data.get("message") |
| 86 | if message: |
| 87 | return True, message |
| 88 | return True, f"成功上传 {len(entries)} 个账号到 Codex2API" |
| 89 | |
| 90 | error_msg = f"上传失败: HTTP {response.status_code}" |
| 91 | try: |
| 92 | detail = response.json() |
| 93 | if isinstance(detail, dict): |
| 94 | error_msg = detail.get("error") or detail.get("message") or error_msg |
| 95 | except Exception: |
| 96 | error_msg = f"{error_msg} - {response.text[:200]}" |
| 97 | return False, error_msg |
| 98 | except Exception as e: |
no test coverage detected