mirror of
https://github.com/cnlimiter/codex-register.git
synced 2026-07-09 06:21:23 +08:00
refactor(routes): #13 优化 Sub2API 导出格式为合并数组
This commit is contained in:
@@ -412,44 +412,40 @@ async def export_accounts_csv(request: BatchExportRequest):
|
|||||||
|
|
||||||
@router.post("/export/sub2api")
|
@router.post("/export/sub2api")
|
||||||
async def export_accounts_sub2api(request: BatchExportRequest):
|
async def export_accounts_sub2api(request: BatchExportRequest):
|
||||||
"""导出账号为 Sub2Api 格式(每个账号单独一个 JSON 文件,多个打包为 ZIP)"""
|
"""导出账号为 Sub2Api 格式(所有选中账号合并到一个 JSON 的 accounts 数组中)"""
|
||||||
import io
|
|
||||||
import zipfile
|
|
||||||
|
|
||||||
def make_sub2api_json(acc) -> dict:
|
def make_account_entry(acc) -> dict:
|
||||||
expires_at = int(acc.expires_at.timestamp()) if acc.expires_at else 0
|
expires_at = int(acc.expires_at.timestamp()) if acc.expires_at else 0
|
||||||
return {
|
return {
|
||||||
"proxies": [],
|
"name": acc.email,
|
||||||
"accounts": [
|
"platform": "openai",
|
||||||
{
|
"type": "oauth",
|
||||||
"name": acc.email,
|
"credentials": {
|
||||||
"platform": "openai",
|
"access_token": acc.access_token or "",
|
||||||
"type": "oauth",
|
"chatgpt_account_id": acc.account_id or "",
|
||||||
"credentials": {
|
"chatgpt_user_id": "",
|
||||||
"access_token": acc.access_token or "",
|
"client_id": acc.client_id or "",
|
||||||
"chatgpt_account_id": acc.account_id or "",
|
"expires_at": expires_at,
|
||||||
"chatgpt_user_id": "",
|
"expires_in": 863999,
|
||||||
"client_id": acc.client_id or "",
|
"model_mapping": {
|
||||||
"expires_at": expires_at,
|
"gpt-5.1": "gpt-5.1",
|
||||||
"expires_in": 863999,
|
"gpt-5.1-codex": "gpt-5.1-codex",
|
||||||
"model_mapping": {
|
"gpt-5.1-codex-max": "gpt-5.1-codex-max",
|
||||||
"gpt-5.1": "gpt-5.1",
|
"gpt-5.1-codex-mini": "gpt-5.1-codex-mini",
|
||||||
"gpt-5.1-codex": "gpt-5.1-codex",
|
"gpt-5.2": "gpt-5.2",
|
||||||
"gpt-5.1-codex-max": "gpt-5.1-codex-max",
|
"gpt-5.2-codex": "gpt-5.2-codex",
|
||||||
"gpt-5.1-codex-mini": "gpt-5.1-codex-mini",
|
"gpt-5.3": "gpt-5.3",
|
||||||
"gpt-5.2": "gpt-5.2",
|
"gpt-5.3-codex": "gpt-5.3-codex",
|
||||||
"gpt-5.2-codex": "gpt-5.2-codex"
|
"gpt-5.4": "gpt-5.4"
|
||||||
},
|
},
|
||||||
"organization_id": acc.workspace_id or "",
|
"organization_id": acc.workspace_id or "",
|
||||||
"refresh_token": acc.refresh_token or ""
|
"refresh_token": acc.refresh_token or ""
|
||||||
},
|
},
|
||||||
"extra": {},
|
"extra": {},
|
||||||
"concurrency": 10,
|
"concurrency": 10,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"rate_multiplier": 1,
|
"rate_multiplier": 1,
|
||||||
"auto_pause_on_expired": True
|
"auto_pause_on_expired": True
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
with get_db() as db:
|
with get_db() as db:
|
||||||
@@ -460,29 +456,21 @@ async def export_accounts_sub2api(request: BatchExportRequest):
|
|||||||
accounts = db.query(Account).filter(Account.id.in_(ids)).all()
|
accounts = db.query(Account).filter(Account.id.in_(ids)).all()
|
||||||
|
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
payload = {
|
||||||
|
"proxies": [],
|
||||||
|
"accounts": [make_account_entry(acc) for acc in accounts]
|
||||||
|
}
|
||||||
|
content = json.dumps(payload, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
if len(accounts) == 1:
|
if len(accounts) == 1:
|
||||||
acc = accounts[0]
|
filename = f"{accounts[0].email}_sub2api.json"
|
||||||
content = json.dumps(make_sub2api_json(acc), ensure_ascii=False, indent=2)
|
else:
|
||||||
filename = f"{acc.email}_sub2api.json"
|
filename = f"sub2api_tokens_{timestamp}.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(
|
return StreamingResponse(
|
||||||
zip_buffer,
|
iter([content]),
|
||||||
media_type="application/zip",
|
media_type="application/json",
|
||||||
headers={"Content-Disposition": f"attachment; filename={zip_filename}"}
|
headers={"Content-Disposition": f"attachment; filename={filename}"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user