mirror of
https://github.com/cnlimiter/codex-register.git
synced 2026-05-12 11:39:57 +08:00
feat: support proxy_url in CPA auth files
This commit is contained in:
@@ -89,17 +89,23 @@ def _post_cpa_auth_file_raw_json(upload_url: str, filename: str, file_content: b
|
||||
)
|
||||
|
||||
|
||||
def generate_token_json(account: Account) -> dict:
|
||||
def generate_token_json(
|
||||
account: Account,
|
||||
include_proxy_url: bool = False,
|
||||
proxy_url: Optional[str] = None,
|
||||
) -> dict:
|
||||
"""
|
||||
生成 CPA 格式的 Token JSON
|
||||
|
||||
Args:
|
||||
account: 账号模型实例
|
||||
include_proxy_url: 是否将账号代理写入 auth file 的 proxy_url 字段
|
||||
proxy_url: 当账号本身没有记录代理时使用的兜底代理 URL
|
||||
|
||||
Returns:
|
||||
CPA 格式的 Token 字典
|
||||
"""
|
||||
return {
|
||||
token_data = {
|
||||
"type": "codex",
|
||||
"email": account.email,
|
||||
"expired": account.expires_at.strftime("%Y-%m-%dT%H:%M:%S+08:00") if account.expires_at else "",
|
||||
@@ -110,6 +116,12 @@ def generate_token_json(account: Account) -> dict:
|
||||
"refresh_token": account.refresh_token or "",
|
||||
}
|
||||
|
||||
resolved_proxy_url = (getattr(account, "proxy_used", None) or proxy_url or "").strip()
|
||||
if include_proxy_url and resolved_proxy_url:
|
||||
token_data["proxy_url"] = resolved_proxy_url
|
||||
|
||||
return token_data
|
||||
|
||||
|
||||
def upload_to_cpa(
|
||||
token_data: dict,
|
||||
@@ -185,15 +197,17 @@ def batch_upload_to_cpa(
|
||||
proxy: str = None,
|
||||
api_url: str = None,
|
||||
api_token: str = None,
|
||||
include_proxy_url: bool = False,
|
||||
) -> dict:
|
||||
"""
|
||||
批量上传账号到 CPA 管理平台
|
||||
|
||||
Args:
|
||||
account_ids: 账号 ID 列表
|
||||
proxy: 可选的代理 URL
|
||||
proxy: 可选的代理 URL(用于 auth file proxy_url 的兜底值)
|
||||
api_url: 指定 CPA API URL(优先于全局配置)
|
||||
api_token: 指定 CPA API Token(优先于全局配置)
|
||||
include_proxy_url: 是否将账号代理写入 auth file 的 proxy_url 字段
|
||||
|
||||
Returns:
|
||||
包含成功/失败统计和详情的字典
|
||||
@@ -231,7 +245,11 @@ def batch_upload_to_cpa(
|
||||
continue
|
||||
|
||||
# 生成 Token JSON
|
||||
token_data = generate_token_json(account)
|
||||
token_data = generate_token_json(
|
||||
account,
|
||||
include_proxy_url=include_proxy_url,
|
||||
proxy_url=proxy,
|
||||
)
|
||||
|
||||
# 上传
|
||||
success, message = upload_to_cpa(token_data, proxy, api_url=api_url, api_token=api_token)
|
||||
|
||||
@@ -527,6 +527,7 @@ def create_cpa_service(
|
||||
api_url: str,
|
||||
api_token: str,
|
||||
enabled: bool = True,
|
||||
include_proxy_url: bool = False,
|
||||
priority: int = 0
|
||||
) -> CpaService:
|
||||
"""创建 CPA 服务配置"""
|
||||
@@ -535,6 +536,7 @@ def create_cpa_service(
|
||||
api_url=api_url,
|
||||
api_token=api_token,
|
||||
enabled=enabled,
|
||||
include_proxy_url=include_proxy_url,
|
||||
priority=priority
|
||||
)
|
||||
db.add(db_service)
|
||||
|
||||
@@ -139,6 +139,7 @@ class CpaService(Base):
|
||||
api_url = Column(String(500), nullable=False) # API URL
|
||||
api_token = Column(Text, nullable=False) # API Token
|
||||
enabled = Column(Boolean, default=True)
|
||||
include_proxy_url = Column(Boolean, default=False) # 是否将账号代理写入 auth file
|
||||
priority = Column(Integer, default=0) # 优先级
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
@@ -111,6 +111,7 @@ class DatabaseSessionManager:
|
||||
("accounts", "subscription_at", "DATETIME"),
|
||||
("accounts", "cookies", "TEXT"),
|
||||
("proxies", "is_default", "BOOLEAN DEFAULT 0"),
|
||||
("cpa_services", "include_proxy_url", "BOOLEAN DEFAULT 0"),
|
||||
]
|
||||
|
||||
# 确保新表存在(create_tables 已处理,此处兜底)
|
||||
|
||||
@@ -724,11 +724,12 @@ class BatchCPAUploadRequest(BaseModel):
|
||||
async def batch_upload_accounts_to_cpa(request: BatchCPAUploadRequest):
|
||||
"""批量上传账号到 CPA"""
|
||||
|
||||
proxy = request.proxy if request.proxy else get_settings().proxy_url
|
||||
proxy = request.proxy
|
||||
|
||||
# 解析指定的 CPA 服务
|
||||
cpa_api_url = None
|
||||
cpa_api_token = None
|
||||
include_proxy_url = False
|
||||
if request.cpa_service_id:
|
||||
with get_db() as db:
|
||||
svc = crud.get_cpa_service_by_id(db, request.cpa_service_id)
|
||||
@@ -736,6 +737,7 @@ async def batch_upload_accounts_to_cpa(request: BatchCPAUploadRequest):
|
||||
raise HTTPException(status_code=404, detail="指定的 CPA 服务不存在")
|
||||
cpa_api_url = svc.api_url
|
||||
cpa_api_token = svc.api_token
|
||||
include_proxy_url = bool(svc.include_proxy_url)
|
||||
|
||||
with get_db() as db:
|
||||
ids = resolve_account_ids(
|
||||
@@ -743,7 +745,13 @@ async def batch_upload_accounts_to_cpa(request: BatchCPAUploadRequest):
|
||||
request.status_filter, request.email_service_filter, request.search_filter
|
||||
)
|
||||
|
||||
results = batch_upload_to_cpa(ids, proxy, api_url=cpa_api_url, api_token=cpa_api_token)
|
||||
results = batch_upload_to_cpa(
|
||||
ids,
|
||||
proxy,
|
||||
api_url=cpa_api_url,
|
||||
api_token=cpa_api_token,
|
||||
include_proxy_url=include_proxy_url,
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
@@ -751,12 +759,13 @@ async def batch_upload_accounts_to_cpa(request: BatchCPAUploadRequest):
|
||||
async def upload_account_to_cpa(account_id: int, request: Optional[CPAUploadRequest] = Body(default=None)):
|
||||
"""上传单个账号到 CPA"""
|
||||
|
||||
proxy = request.proxy if request and request.proxy else get_settings().proxy_url
|
||||
proxy = request.proxy if request else None
|
||||
cpa_service_id = request.cpa_service_id if request else None
|
||||
|
||||
# 解析指定的 CPA 服务
|
||||
cpa_api_url = None
|
||||
cpa_api_token = None
|
||||
include_proxy_url = False
|
||||
if cpa_service_id:
|
||||
with get_db() as db:
|
||||
svc = crud.get_cpa_service_by_id(db, cpa_service_id)
|
||||
@@ -764,6 +773,7 @@ async def upload_account_to_cpa(account_id: int, request: Optional[CPAUploadRequ
|
||||
raise HTTPException(status_code=404, detail="指定的 CPA 服务不存在")
|
||||
cpa_api_url = svc.api_url
|
||||
cpa_api_token = svc.api_token
|
||||
include_proxy_url = bool(svc.include_proxy_url)
|
||||
|
||||
with get_db() as db:
|
||||
account = crud.get_account_by_id(db, account_id)
|
||||
@@ -777,7 +787,11 @@ async def upload_account_to_cpa(account_id: int, request: Optional[CPAUploadRequ
|
||||
}
|
||||
|
||||
# 生成 Token JSON
|
||||
token_data = generate_token_json(account)
|
||||
token_data = generate_token_json(
|
||||
account,
|
||||
include_proxy_url=include_proxy_url,
|
||||
proxy_url=proxy,
|
||||
)
|
||||
|
||||
# 上传
|
||||
success, message = upload_to_cpa(token_data, proxy, api_url=cpa_api_url, api_token=cpa_api_token)
|
||||
|
||||
@@ -418,7 +418,6 @@ def _run_sync_registration_task(task_uuid: str, email_service_type: str, proxy:
|
||||
from ...database.models import Account as AccountModel
|
||||
saved_account = db.query(AccountModel).filter_by(email=result.email).first()
|
||||
if saved_account and saved_account.access_token:
|
||||
token_data = generate_token_json(saved_account)
|
||||
_cpa_ids = cpa_service_ids or []
|
||||
if not _cpa_ids:
|
||||
# 未指定则取所有启用的服务
|
||||
@@ -430,6 +429,10 @@ def _run_sync_registration_task(task_uuid: str, email_service_type: str, proxy:
|
||||
_svc = crud.get_cpa_service_by_id(db, _sid)
|
||||
if not _svc:
|
||||
continue
|
||||
token_data = generate_token_json(
|
||||
saved_account,
|
||||
include_proxy_url=bool(_svc.include_proxy_url),
|
||||
)
|
||||
log_callback(f"[CPA] 上传到服务: {_svc.name}")
|
||||
_ok, _msg = upload_to_cpa(token_data, api_url=_svc.api_url, api_token=_svc.api_token)
|
||||
if _ok:
|
||||
|
||||
@@ -20,6 +20,7 @@ class CpaServiceCreate(BaseModel):
|
||||
api_url: str
|
||||
api_token: str
|
||||
enabled: bool = True
|
||||
include_proxy_url: bool = False
|
||||
priority: int = 0
|
||||
|
||||
|
||||
@@ -28,6 +29,7 @@ class CpaServiceUpdate(BaseModel):
|
||||
api_url: Optional[str] = None
|
||||
api_token: Optional[str] = None
|
||||
enabled: Optional[bool] = None
|
||||
include_proxy_url: Optional[bool] = None
|
||||
priority: Optional[int] = None
|
||||
|
||||
|
||||
@@ -37,6 +39,7 @@ class CpaServiceResponse(BaseModel):
|
||||
api_url: str
|
||||
has_token: bool
|
||||
enabled: bool
|
||||
include_proxy_url: bool
|
||||
priority: int
|
||||
created_at: Optional[str] = None
|
||||
updated_at: Optional[str] = None
|
||||
@@ -57,6 +60,7 @@ def _to_response(svc) -> CpaServiceResponse:
|
||||
api_url=svc.api_url,
|
||||
has_token=bool(svc.api_token),
|
||||
enabled=svc.enabled,
|
||||
include_proxy_url=bool(svc.include_proxy_url),
|
||||
priority=svc.priority,
|
||||
created_at=svc.created_at.isoformat() if svc.created_at else None,
|
||||
updated_at=svc.updated_at.isoformat() if svc.updated_at else None,
|
||||
@@ -83,6 +87,7 @@ async def create_cpa_service(request: CpaServiceCreate):
|
||||
api_url=request.api_url,
|
||||
api_token=request.api_token,
|
||||
enabled=request.enabled,
|
||||
include_proxy_url=request.include_proxy_url,
|
||||
priority=request.priority,
|
||||
)
|
||||
return _to_response(service)
|
||||
@@ -111,6 +116,7 @@ async def get_cpa_service_full(service_id: int):
|
||||
"api_url": service.api_url,
|
||||
"api_token": service.api_token,
|
||||
"enabled": service.enabled,
|
||||
"include_proxy_url": bool(service.include_proxy_url),
|
||||
"priority": service.priority,
|
||||
}
|
||||
|
||||
@@ -133,6 +139,8 @@ async def update_cpa_service(service_id: int, request: CpaServiceUpdate):
|
||||
update_data["api_token"] = request.api_token
|
||||
if request.enabled is not None:
|
||||
update_data["enabled"] = request.enabled
|
||||
if request.include_proxy_url is not None:
|
||||
update_data["include_proxy_url"] = request.include_proxy_url
|
||||
if request.priority is not None:
|
||||
update_data["priority"] = request.priority
|
||||
|
||||
|
||||
Reference in New Issue
Block a user