mirror of
https://github.com/cnlimiter/codex-register.git
synced 2026-06-25 17:24:06 +08:00
feat(accounts): 新增 Sub2Api 格式导出功能
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "codex-register-v2"
|
||||
version = "0.1.0"
|
||||
description = "OpenAI/Codex CLI 自动注册系统"
|
||||
version = "1.0,4"
|
||||
description = "OpenAI 自动注册系统 v2"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"curl-cffi>=0.14.0",
|
||||
|
||||
@@ -393,6 +393,82 @@ async def export_accounts_csv(request: BatchExportRequest):
|
||||
)
|
||||
|
||||
|
||||
@router.post("/export/sub2api")
|
||||
async def export_accounts_sub2api(request: BatchExportRequest):
|
||||
"""导出账号为 Sub2Api 格式(每个账号单独一个 JSON 文件,多个打包为 ZIP)"""
|
||||
import io
|
||||
import zipfile
|
||||
|
||||
def make_sub2api_json(acc) -> dict:
|
||||
expires_at = int(acc.expires_at.timestamp()) if acc.expires_at else 0
|
||||
return {
|
||||
"proxies": [],
|
||||
"accounts": [
|
||||
{
|
||||
"name": acc.email,
|
||||
"platform": "openai",
|
||||
"type": "oauth",
|
||||
"credentials": {
|
||||
"access_token": acc.access_token or "",
|
||||
"chatgpt_account_id": acc.account_id or "",
|
||||
"chatgpt_user_id": "",
|
||||
"client_id": acc.client_id or "",
|
||||
"expires_at": expires_at,
|
||||
"expires_in": 863999,
|
||||
"model_mapping": {
|
||||
"gpt-5.1": "gpt-5.1",
|
||||
"gpt-5.1-codex": "gpt-5.1-codex",
|
||||
"gpt-5.1-codex-max": "gpt-5.1-codex-max",
|
||||
"gpt-5.1-codex-mini": "gpt-5.1-codex-mini",
|
||||
"gpt-5.2": "gpt-5.2",
|
||||
"gpt-5.2-codex": "gpt-5.2-codex"
|
||||
},
|
||||
"organization_id": acc.workspace_id or "",
|
||||
"refresh_token": acc.refresh_token or ""
|
||||
},
|
||||
"extra": {},
|
||||
"concurrency": 10,
|
||||
"priority": 1,
|
||||
"rate_multiplier": 1,
|
||||
"auto_pause_on_expired": True
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
with get_db() as db:
|
||||
ids = resolve_account_ids(
|
||||
db, request.ids, request.select_all,
|
||||
request.status_filter, request.email_service_filter, request.search_filter
|
||||
)
|
||||
accounts = db.query(Account).filter(Account.id.in_(ids)).all()
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
|
||||
if len(accounts) == 1:
|
||||
acc = accounts[0]
|
||||
content = json.dumps(make_sub2api_json(acc), ensure_ascii=False, indent=2)
|
||||
filename = f"{acc.email}_sub2api.json"
|
||||
return StreamingResponse(
|
||||
iter([content]),
|
||||
media_type="application/json",
|
||||
headers={"Content-Disposition": f"attachment; filename={filename}"}
|
||||
)
|
||||
|
||||
zip_buffer = io.BytesIO()
|
||||
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zf:
|
||||
for acc in accounts:
|
||||
content = json.dumps(make_sub2api_json(acc), ensure_ascii=False, indent=2)
|
||||
zf.writestr(f"{acc.email}_sub2api.json", content)
|
||||
|
||||
zip_buffer.seek(0)
|
||||
zip_filename = f"sub2api_tokens_{timestamp}.zip"
|
||||
return StreamingResponse(
|
||||
zip_buffer,
|
||||
media_type="application/zip",
|
||||
headers={"Content-Disposition": f"attachment; filename={zip_filename}"}
|
||||
)
|
||||
|
||||
|
||||
@router.post("/export/cpa")
|
||||
async def export_accounts_cpa(request: BatchExportRequest):
|
||||
"""导出账号为 CPA Token JSON 格式(每个账号单独一个 JSON 文件,打包为 ZIP)"""
|
||||
|
||||
@@ -696,7 +696,7 @@ async function exportAccounts(format) {
|
||||
|
||||
// 从 Content-Disposition 获取文件名
|
||||
const disposition = response.headers.get('Content-Disposition');
|
||||
let filename = `accounts_${Date.now()}.${format === 'cpa' ? 'json' : format}`;
|
||||
let filename = `accounts_${Date.now()}.${(format === 'cpa' || format === 'sub2api') ? 'json' : format}`;
|
||||
if (disposition) {
|
||||
const match = disposition.match(/filename=(.+)/);
|
||||
if (match) {
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
<a href="#" class="dropdown-item" data-format="json">导出 JSON</a>
|
||||
<a href="#" class="dropdown-item" data-format="csv">导出 CSV</a>
|
||||
<a href="#" class="dropdown-item" data-format="cpa">导出 CPA 格式</a>
|
||||
<a href="#" class="dropdown-item" data-format="sub2api">导出 Sub2Api 格式</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user