mirror of
https://github.com/cnlimiter/codex-register.git
synced 2026-06-28 02:32:02 +08:00
Merge branch 'master' into copilot/codex-auth-f4d0327
This commit is contained in:
@@ -12,6 +12,7 @@ from .payment import router as payment_router
|
||||
from .upload.cpa_services import router as cpa_services_router
|
||||
from .upload.sub2api_services import router as sub2api_services_router
|
||||
from .upload.tm_services import router as tm_services_router
|
||||
from .upload.newapi_services import router as newapi_services_router
|
||||
|
||||
api_router = APIRouter()
|
||||
|
||||
@@ -24,3 +25,4 @@ api_router.include_router(payment_router, prefix="/payment", tags=["payment"])
|
||||
api_router.include_router(cpa_services_router, prefix="/cpa-services", tags=["cpa-services"])
|
||||
api_router.include_router(sub2api_services_router, prefix="/sub2api-services", tags=["sub2api-services"])
|
||||
api_router.include_router(tm_services_router, prefix="/tm-services", tags=["tm-services"])
|
||||
api_router.include_router(newapi_services_router, prefix="/newapi-services", tags=["newapi-services"])
|
||||
|
||||
@@ -21,6 +21,7 @@ from ...core.openai.token_refresh import validate_account_token as do_validate
|
||||
from ...core.upload.cpa_upload import generate_token_json, batch_upload_to_cpa, upload_to_cpa
|
||||
from ...core.upload.team_manager_upload import upload_to_team_manager, batch_upload_to_team_manager
|
||||
from ...core.upload.sub2api_upload import batch_upload_to_sub2api, upload_to_sub2api
|
||||
from ...core.upload.newapi_upload import upload_to_newapi, batch_upload_to_newapi
|
||||
|
||||
from ...core.dynamic_proxy import get_proxy_url_for_task
|
||||
from ...database import crud
|
||||
@@ -155,6 +156,8 @@ class AccountResponse(BaseModel):
|
||||
proxy_used: Optional[str] = None
|
||||
cpa_uploaded: bool = False
|
||||
cpa_uploaded_at: Optional[str] = None
|
||||
newapi_uploaded: bool = False
|
||||
newapi_uploaded_at: Optional[str] = None
|
||||
cookies: Optional[str] = None
|
||||
created_at: Optional[str] = None
|
||||
updated_at: Optional[str] = None
|
||||
@@ -234,6 +237,8 @@ def account_to_response(account: Account) -> AccountResponse:
|
||||
proxy_used=account.proxy_used,
|
||||
cpa_uploaded=account.cpa_uploaded or False,
|
||||
cpa_uploaded_at=account.cpa_uploaded_at.isoformat() if account.cpa_uploaded_at else None,
|
||||
newapi_uploaded=account.newapi_uploaded or False,
|
||||
newapi_uploaded_at=account.newapi_uploaded_at.isoformat() if account.newapi_uploaded_at else None,
|
||||
cookies=account.cookies,
|
||||
created_at=account.created_at.isoformat() if account.created_at else None,
|
||||
updated_at=account.updated_at.isoformat() if account.updated_at else None,
|
||||
@@ -1413,6 +1418,85 @@ async def upload_account_to_tm(account_id: int, request: Optional[UploadTMReques
|
||||
return {"success": success, "message": message}
|
||||
|
||||
|
||||
# ============== NEWAPI 上传 ==============
|
||||
|
||||
class UploadNewapiRequest(BaseModel):
|
||||
service_id: Optional[int] = None
|
||||
|
||||
|
||||
class BatchUploadNewapiRequest(BaseModel):
|
||||
ids: List[int] = []
|
||||
select_all: bool = False
|
||||
status_filter: Optional[str] = None
|
||||
email_service_filter: Optional[str] = None
|
||||
search_filter: Optional[str] = None
|
||||
service_id: Optional[int] = None
|
||||
|
||||
|
||||
@router.post("/batch-upload-newapi")
|
||||
async def batch_upload_accounts_to_newapi(request: BatchUploadNewapiRequest):
|
||||
with get_db() as db:
|
||||
if request.service_id:
|
||||
svc = crud.get_newapi_service_by_id(db, request.service_id)
|
||||
else:
|
||||
svcs = crud.get_newapi_services(db, enabled=True)
|
||||
svc = svcs[0] if svcs else None
|
||||
|
||||
if not svc:
|
||||
raise HTTPException(status_code=400, detail="未找到可用的 NEWAPI 服务,请先在设置中配置")
|
||||
|
||||
api_url = svc.api_url
|
||||
api_key = svc.api_key
|
||||
|
||||
ids = resolve_account_ids(
|
||||
db, request.ids, request.select_all,
|
||||
request.status_filter, request.email_service_filter, request.search_filter
|
||||
)
|
||||
|
||||
results = batch_upload_to_newapi(
|
||||
ids,
|
||||
api_url,
|
||||
api_key,
|
||||
channel_type=svc.channel_type,
|
||||
channel_base_url=svc.channel_base_url,
|
||||
channel_models=svc.channel_models,
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
@router.post("/{account_id}/upload-newapi")
|
||||
async def upload_account_to_newapi(account_id: int, request: Optional[UploadNewapiRequest] = Body(default=None)):
|
||||
service_id = request.service_id if request else None
|
||||
|
||||
with get_db() as db:
|
||||
if service_id:
|
||||
svc = crud.get_newapi_service_by_id(db, service_id)
|
||||
else:
|
||||
svcs = crud.get_newapi_services(db, enabled=True)
|
||||
svc = svcs[0] if svcs else None
|
||||
|
||||
if not svc:
|
||||
raise HTTPException(status_code=400, detail="未找到可用的 NEWAPI 服务,请先在设置中配置")
|
||||
|
||||
account = crud.get_account_by_id(db, account_id)
|
||||
if not account:
|
||||
raise HTTPException(status_code=404, detail="账号不存在")
|
||||
success, message = upload_to_newapi(
|
||||
account,
|
||||
svc.api_url,
|
||||
svc.api_key,
|
||||
channel_type=svc.channel_type,
|
||||
channel_base_url=svc.channel_base_url,
|
||||
channel_models=svc.channel_models,
|
||||
)
|
||||
if success:
|
||||
account.newapi_uploaded = True
|
||||
account.newapi_uploaded_at = datetime.utcnow()
|
||||
db.commit()
|
||||
|
||||
return {"success": success, "message": message}
|
||||
|
||||
|
||||
# ============== Inbox Code ==============
|
||||
|
||||
def _build_inbox_config(db, service_type, email: str) -> dict:
|
||||
|
||||
@@ -115,6 +115,8 @@ class RegistrationTaskCreate(BaseModel):
|
||||
sub2api_service_ids: List[int] = [] # 指定 Sub2API 服务 ID 列表
|
||||
auto_upload_tm: bool = False
|
||||
tm_service_ids: List[int] = [] # 指定 TM 服务 ID 列表
|
||||
auto_upload_newapi: bool = False
|
||||
newapi_service_ids: List[int] = []
|
||||
|
||||
|
||||
class BatchRegistrationRequest(BaseModel):
|
||||
@@ -134,6 +136,8 @@ class BatchRegistrationRequest(BaseModel):
|
||||
sub2api_service_ids: List[int] = []
|
||||
auto_upload_tm: bool = False
|
||||
tm_service_ids: List[int] = []
|
||||
auto_upload_newapi: bool = False
|
||||
newapi_service_ids: List[int] = []
|
||||
|
||||
|
||||
class MockRegistrationCreateRequest(BaseModel):
|
||||
@@ -216,6 +220,8 @@ class OutlookBatchRegistrationRequest(BaseModel):
|
||||
sub2api_service_ids: List[int] = []
|
||||
auto_upload_tm: bool = False
|
||||
tm_service_ids: List[int] = []
|
||||
auto_upload_newapi: bool = False
|
||||
newapi_service_ids: List[int] = []
|
||||
|
||||
|
||||
class OutlookBatchRegistrationResponse(BaseModel):
|
||||
@@ -527,7 +533,7 @@ def _build_email_service_candidates(
|
||||
return candidates
|
||||
|
||||
|
||||
def _run_sync_registration_task(task_uuid: str, email_service_type: str, proxy: Optional[str], email_service_config: Optional[dict], email_service_id: Optional[int] = None, log_prefix: str = "", batch_id: str = "", auto_upload_cpa: bool = False, cpa_service_ids: List[int] = None, auto_upload_sub2api: bool = False, sub2api_service_ids: List[int] = None, auto_upload_tm: bool = False, tm_service_ids: List[int] = None):
|
||||
def _run_sync_registration_task(task_uuid: str, email_service_type: str, proxy: Optional[str], email_service_config: Optional[dict], email_service_id: Optional[int] = None, log_prefix: str = "", batch_id: str = "", auto_upload_cpa: bool = False, cpa_service_ids: List[int] = None, auto_upload_sub2api: bool = False, sub2api_service_ids: List[int] = None, auto_upload_tm: bool = False, tm_service_ids: List[int] = None, auto_upload_newapi: bool = False, newapi_service_ids: List[int] = None):
|
||||
"""
|
||||
在线程池中执行的同步注册任务
|
||||
|
||||
@@ -774,6 +780,43 @@ def _run_sync_registration_task(task_uuid: str, email_service_type: str, proxy:
|
||||
except Exception as tm_err:
|
||||
log_callback(f"[TM] 上传异常: {tm_err}")
|
||||
|
||||
if auto_upload_newapi:
|
||||
try:
|
||||
from ...core.upload.newapi_upload import upload_to_newapi
|
||||
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:
|
||||
_na_ids = newapi_service_ids or []
|
||||
if not _na_ids:
|
||||
_na_ids = [s.id for s in crud.get_newapi_services(db, enabled=True)]
|
||||
if not _na_ids:
|
||||
log_callback("[NEWAPI] 无可用 NEWAPI 服务,跳过上传")
|
||||
for _sid in _na_ids:
|
||||
try:
|
||||
_svc = crud.get_newapi_service_by_id(db, _sid)
|
||||
if not _svc:
|
||||
continue
|
||||
log_callback(f"[NEWAPI] 上传到服务: {_svc.name}")
|
||||
_ok, _msg = upload_to_newapi(
|
||||
saved_account,
|
||||
_svc.api_url,
|
||||
_svc.api_key,
|
||||
channel_type=_svc.channel_type,
|
||||
channel_base_url=_svc.channel_base_url,
|
||||
channel_models=_svc.channel_models,
|
||||
)
|
||||
if _ok:
|
||||
saved_account.newapi_uploaded = True
|
||||
saved_account.newapi_uploaded_at = datetime.utcnow()
|
||||
db.commit()
|
||||
log_callback(f"[NEWAPI] 上传成功: {_svc.name}")
|
||||
else:
|
||||
log_callback(f"[NEWAPI] 上传失败({_svc.name}): {_msg}")
|
||||
except Exception as _e:
|
||||
log_callback(f"[NEWAPI] 异常({_sid}): {_e}")
|
||||
except Exception as na_err:
|
||||
log_callback(f"[NEWAPI] 上传异常: {na_err}")
|
||||
|
||||
# 更新任务状态
|
||||
crud.update_registration_task(
|
||||
db, task_uuid,
|
||||
@@ -831,7 +874,7 @@ def _run_sync_registration_task(task_uuid: str, email_service_type: str, proxy:
|
||||
pass
|
||||
|
||||
|
||||
async def run_registration_task(task_uuid: str, email_service_type: str, proxy: Optional[str], email_service_config: Optional[dict], email_service_id: Optional[int] = None, log_prefix: str = "", batch_id: str = "", auto_upload_cpa: bool = False, cpa_service_ids: List[int] = None, auto_upload_sub2api: bool = False, sub2api_service_ids: List[int] = None, auto_upload_tm: bool = False, tm_service_ids: List[int] = None):
|
||||
async def run_registration_task(task_uuid: str, email_service_type: str, proxy: Optional[str], email_service_config: Optional[dict], email_service_id: Optional[int] = None, log_prefix: str = "", batch_id: str = "", auto_upload_cpa: bool = False, cpa_service_ids: List[int] = None, auto_upload_sub2api: bool = False, sub2api_service_ids: List[int] = None, auto_upload_tm: bool = False, tm_service_ids: List[int] = None, auto_upload_newapi: bool = False, newapi_service_ids: List[int] = None):
|
||||
"""
|
||||
异步执行注册任务
|
||||
|
||||
@@ -864,6 +907,8 @@ async def run_registration_task(task_uuid: str, email_service_type: str, proxy:
|
||||
sub2api_service_ids or [],
|
||||
auto_upload_tm,
|
||||
tm_service_ids or [],
|
||||
auto_upload_newapi,
|
||||
newapi_service_ids or [],
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"线程池执行异常: {task_uuid}, 错误: {e}")
|
||||
@@ -1170,6 +1215,8 @@ async def run_batch_parallel(
|
||||
sub2api_service_ids: List[int] = None,
|
||||
auto_upload_tm: bool = False,
|
||||
tm_service_ids: List[int] = None,
|
||||
auto_upload_newapi: bool = False,
|
||||
newapi_service_ids: List[int] = None,
|
||||
):
|
||||
"""
|
||||
并行模式:所有任务同时提交,Semaphore 控制最大并发数
|
||||
@@ -1189,6 +1236,7 @@ async def run_batch_parallel(
|
||||
auto_upload_cpa=auto_upload_cpa, cpa_service_ids=cpa_service_ids or [],
|
||||
auto_upload_sub2api=auto_upload_sub2api, sub2api_service_ids=sub2api_service_ids or [],
|
||||
auto_upload_tm=auto_upload_tm, tm_service_ids=tm_service_ids or [],
|
||||
auto_upload_newapi=auto_upload_newapi, newapi_service_ids=newapi_service_ids or [],
|
||||
)
|
||||
with get_db() as db:
|
||||
t = crud.get_registration_task(db, uuid)
|
||||
@@ -1239,6 +1287,8 @@ async def run_batch_pipeline(
|
||||
sub2api_service_ids: List[int] = None,
|
||||
auto_upload_tm: bool = False,
|
||||
tm_service_ids: List[int] = None,
|
||||
auto_upload_newapi: bool = False,
|
||||
newapi_service_ids: List[int] = None,
|
||||
):
|
||||
"""
|
||||
流水线模式:每隔 interval 秒启动一个新任务,Semaphore 限制最大并发数
|
||||
@@ -1258,6 +1308,7 @@ async def run_batch_pipeline(
|
||||
auto_upload_cpa=auto_upload_cpa, cpa_service_ids=cpa_service_ids or [],
|
||||
auto_upload_sub2api=auto_upload_sub2api, sub2api_service_ids=sub2api_service_ids or [],
|
||||
auto_upload_tm=auto_upload_tm, tm_service_ids=tm_service_ids or [],
|
||||
auto_upload_newapi=auto_upload_newapi, newapi_service_ids=newapi_service_ids or [],
|
||||
)
|
||||
with get_db() as db:
|
||||
t = crud.get_registration_task(db, uuid)
|
||||
@@ -1332,6 +1383,8 @@ async def run_batch_registration(
|
||||
sub2api_service_ids: List[int] = None,
|
||||
auto_upload_tm: bool = False,
|
||||
tm_service_ids: List[int] = None,
|
||||
auto_upload_newapi: bool = False,
|
||||
newapi_service_ids: List[int] = None,
|
||||
):
|
||||
"""根据 mode 分发到并行或流水线执行"""
|
||||
if mode == "parallel":
|
||||
@@ -1341,6 +1394,7 @@ async def run_batch_registration(
|
||||
auto_upload_cpa=auto_upload_cpa, cpa_service_ids=cpa_service_ids,
|
||||
auto_upload_sub2api=auto_upload_sub2api, sub2api_service_ids=sub2api_service_ids,
|
||||
auto_upload_tm=auto_upload_tm, tm_service_ids=tm_service_ids,
|
||||
auto_upload_newapi=auto_upload_newapi, newapi_service_ids=newapi_service_ids,
|
||||
)
|
||||
else:
|
||||
await run_batch_pipeline(
|
||||
@@ -1350,6 +1404,7 @@ async def run_batch_registration(
|
||||
auto_upload_cpa=auto_upload_cpa, cpa_service_ids=cpa_service_ids,
|
||||
auto_upload_sub2api=auto_upload_sub2api, sub2api_service_ids=sub2api_service_ids,
|
||||
auto_upload_tm=auto_upload_tm, tm_service_ids=tm_service_ids,
|
||||
auto_upload_newapi=auto_upload_newapi, newapi_service_ids=newapi_service_ids,
|
||||
)
|
||||
|
||||
|
||||
@@ -1451,6 +1506,8 @@ async def start_registration(
|
||||
request.sub2api_service_ids,
|
||||
request.auto_upload_tm,
|
||||
request.tm_service_ids,
|
||||
request.auto_upload_newapi,
|
||||
request.newapi_service_ids,
|
||||
)
|
||||
|
||||
return task_to_response(task)
|
||||
@@ -1528,6 +1585,8 @@ async def start_batch_registration(
|
||||
request.sub2api_service_ids,
|
||||
request.auto_upload_tm,
|
||||
request.tm_service_ids,
|
||||
request.auto_upload_newapi,
|
||||
request.newapi_service_ids,
|
||||
)
|
||||
|
||||
return BatchRegistrationResponse(
|
||||
@@ -1925,6 +1984,8 @@ async def run_outlook_batch_registration(
|
||||
sub2api_service_ids: List[int] = None,
|
||||
auto_upload_tm: bool = False,
|
||||
tm_service_ids: List[int] = None,
|
||||
auto_upload_newapi: bool = False,
|
||||
newapi_service_ids: List[int] = None,
|
||||
):
|
||||
"""
|
||||
异步执行 Outlook 批量注册任务,复用通用并发逻辑
|
||||
@@ -1968,6 +2029,8 @@ async def run_outlook_batch_registration(
|
||||
sub2api_service_ids=sub2api_service_ids,
|
||||
auto_upload_tm=auto_upload_tm,
|
||||
tm_service_ids=tm_service_ids,
|
||||
auto_upload_newapi=auto_upload_newapi,
|
||||
newapi_service_ids=newapi_service_ids,
|
||||
)
|
||||
|
||||
|
||||
@@ -2066,6 +2129,8 @@ async def start_outlook_batch_registration(
|
||||
request.sub2api_service_ids,
|
||||
request.auto_upload_tm,
|
||||
request.tm_service_ids,
|
||||
request.auto_upload_newapi,
|
||||
request.newapi_service_ids,
|
||||
)
|
||||
|
||||
return OutlookBatchRegistrationResponse(
|
||||
|
||||
139
src/web/routes/upload/newapi_services.py
Normal file
139
src/web/routes/upload/newapi_services.py
Normal file
@@ -0,0 +1,139 @@
|
||||
"""
|
||||
NEWAPI 服务管理 API 路由
|
||||
"""
|
||||
|
||||
from typing import List, Optional
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ....database import crud
|
||||
from ....database.session import get_db
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class NewapiServiceCreate(BaseModel):
|
||||
name: str
|
||||
api_url: str
|
||||
api_key: str
|
||||
channel_type: int = 57
|
||||
channel_base_url: str = ""
|
||||
channel_models: str = "gpt-5.4,gpt-5,gpt-5-codex,gpt-5-codex-mini,gpt-5.1,gpt-5.1-codex,gpt-5.1-codex-max,gpt-5.1-codex-mini,gpt-5.2,gpt-5.2-codex,gpt-5.3-codex,gpt-5-openai-compact,gpt-5-codex-openai-compact,gpt-5-codex-mini-openai-compact,gpt-5.1-openai-compact,gpt-5.1-codex-openai-compact,gpt-5.1-codex-max-openai-compact,gpt-5.1-codex-mini-openai-compact,gpt-5.2-openai-compact,gpt-5.2-codex-openai-compact,gpt-5.3-codex-openai-compact"
|
||||
enabled: bool = True
|
||||
priority: int = 0
|
||||
|
||||
|
||||
class NewapiServiceUpdate(BaseModel):
|
||||
name: Optional[str] = None
|
||||
api_url: Optional[str] = None
|
||||
api_key: Optional[str] = None
|
||||
channel_type: Optional[int] = None
|
||||
channel_base_url: Optional[str] = None
|
||||
channel_models: Optional[str] = None
|
||||
enabled: Optional[bool] = None
|
||||
priority: Optional[int] = None
|
||||
|
||||
|
||||
class NewapiServiceResponse(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
api_url: str
|
||||
has_key: bool
|
||||
channel_type: int = 57
|
||||
channel_base_url: str = ""
|
||||
channel_models: str = ""
|
||||
enabled: bool
|
||||
priority: int
|
||||
created_at: Optional[str] = None
|
||||
updated_at: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
def _to_response(svc) -> NewapiServiceResponse:
|
||||
return NewapiServiceResponse(
|
||||
id=svc.id,
|
||||
name=svc.name,
|
||||
api_url=svc.api_url,
|
||||
has_key=bool(svc.api_key),
|
||||
channel_type=svc.channel_type if svc.channel_type is not None else 57,
|
||||
channel_base_url=svc.channel_base_url or "",
|
||||
channel_models=svc.channel_models or "",
|
||||
enabled=svc.enabled,
|
||||
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,
|
||||
)
|
||||
|
||||
|
||||
@router.get("", response_model=List[NewapiServiceResponse])
|
||||
async def list_newapi_services(enabled: Optional[bool] = None):
|
||||
with get_db() as db:
|
||||
services = crud.get_newapi_services(db, enabled=enabled)
|
||||
return [_to_response(s) for s in services]
|
||||
|
||||
|
||||
@router.post("", response_model=NewapiServiceResponse)
|
||||
async def create_newapi_service(request: NewapiServiceCreate):
|
||||
with get_db() as db:
|
||||
svc = crud.create_newapi_service(
|
||||
db,
|
||||
name=request.name,
|
||||
api_url=request.api_url,
|
||||
api_key=request.api_key,
|
||||
channel_type=request.channel_type,
|
||||
channel_base_url=request.channel_base_url,
|
||||
channel_models=request.channel_models,
|
||||
enabled=request.enabled,
|
||||
priority=request.priority,
|
||||
)
|
||||
return _to_response(svc)
|
||||
|
||||
|
||||
@router.get("/{service_id}", response_model=NewapiServiceResponse)
|
||||
async def get_newapi_service(service_id: int):
|
||||
with get_db() as db:
|
||||
svc = crud.get_newapi_service_by_id(db, service_id)
|
||||
if not svc:
|
||||
raise HTTPException(status_code=404, detail="NEWAPI 服务不存在")
|
||||
return _to_response(svc)
|
||||
|
||||
|
||||
@router.patch("/{service_id}", response_model=NewapiServiceResponse)
|
||||
async def update_newapi_service(service_id: int, request: NewapiServiceUpdate):
|
||||
with get_db() as db:
|
||||
svc = crud.get_newapi_service_by_id(db, service_id)
|
||||
if not svc:
|
||||
raise HTTPException(status_code=404, detail="NEWAPI 服务不存在")
|
||||
|
||||
update_data = {}
|
||||
if request.name is not None:
|
||||
update_data["name"] = request.name
|
||||
if request.api_url is not None:
|
||||
update_data["api_url"] = request.api_url
|
||||
if request.api_key:
|
||||
update_data["api_key"] = request.api_key
|
||||
if request.enabled is not None:
|
||||
update_data["enabled"] = request.enabled
|
||||
if request.priority is not None:
|
||||
update_data["priority"] = request.priority
|
||||
if request.channel_type is not None:
|
||||
update_data["channel_type"] = request.channel_type
|
||||
if request.channel_base_url is not None:
|
||||
update_data["channel_base_url"] = request.channel_base_url
|
||||
if request.channel_models is not None:
|
||||
update_data["channel_models"] = request.channel_models
|
||||
|
||||
svc = crud.update_newapi_service(db, service_id, **update_data)
|
||||
return _to_response(svc)
|
||||
|
||||
|
||||
@router.delete("/{service_id}")
|
||||
async def delete_newapi_service(service_id: int):
|
||||
with get_db() as db:
|
||||
svc = crud.get_newapi_service_by_id(db, service_id)
|
||||
if not svc:
|
||||
raise HTTPException(status_code=404, detail="NEWAPI 服务不存在")
|
||||
crud.delete_newapi_service(db, service_id)
|
||||
return {"success": True, "message": f"NEWAPI 服务 {svc.name} 已删除"}
|
||||
Reference in New Issue
Block a user