feat: initialize aivideo project

This commit is contained in:
2026-04-17 18:33:05 +08:00
commit 14b18d67fe
162 changed files with 26251 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
from sqlalchemy import select
from sqlalchemy.orm import Session
from app.models.entities import ProviderAccount, ProviderModel
class ProvidersRepository:
def __init__(self, db: Session) -> None:
self.db = db
def list_accounts(self):
return self.db.query(ProviderAccount).order_by(ProviderAccount.id.desc())
def get_account(self, account_id: int) -> ProviderAccount | None:
return self.db.scalar(select(ProviderAccount).where(ProviderAccount.id == account_id))
def list_models(self):
return self.db.query(ProviderModel).order_by(ProviderModel.id.desc())
def get_model(self, model_id: int) -> ProviderModel | None:
return self.db.scalar(select(ProviderModel).where(ProviderModel.id == model_id))

View File

@@ -0,0 +1,66 @@
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from app.common.db.session import get_db
from app.common.responses.api_response import success_response
from app.common.security.deps import require_admin_permission
from app.modules.providers.schema import ProviderAccountPayload, ProviderModelPayload
from app.modules.providers.service import ProvidersService
router = APIRouter(prefix="/api/v1/admin", tags=["admin-providers"])
@router.get("/provider-accounts")
def list_provider_accounts(
_=Depends(require_admin_permission()),
db: Session = Depends(get_db),
):
return success_response(ProvidersService(db).list_accounts())
@router.post("/provider-accounts")
def create_provider_account(
payload: ProviderAccountPayload,
_=Depends(require_admin_permission()),
db: Session = Depends(get_db),
):
return success_response(ProvidersService(db).create_account(payload))
@router.put("/provider-accounts/{account_id}")
def update_provider_account(
account_id: int,
payload: ProviderAccountPayload,
_=Depends(require_admin_permission()),
db: Session = Depends(get_db),
):
return success_response(ProvidersService(db).update_account(account_id, payload))
@router.get("/provider-models")
def list_provider_models(
_=Depends(require_admin_permission()),
db: Session = Depends(get_db),
):
return success_response(ProvidersService(db).list_models())
@router.post("/provider-models")
def create_provider_model(
payload: ProviderModelPayload,
_=Depends(require_admin_permission()),
db: Session = Depends(get_db),
):
return success_response(ProvidersService(db).create_model(payload))
@router.put("/provider-models/{model_id}")
def update_provider_model(
model_id: int,
payload: ProviderModelPayload,
_=Depends(require_admin_permission()),
db: Session = Depends(get_db),
):
return success_response(ProvidersService(db).update_model(model_id, payload))

View File

@@ -0,0 +1,35 @@
from pydantic import BaseModel
class ProviderAccountPayload(BaseModel):
provider_code: str
provider_name: str
api_format: str
base_url: str
api_key: str
api_secret: str | None = ""
webhook_secret: str | None = ""
timeout_seconds: int = 120
max_retries: int = 3
status: int = 1
remark: str = ""
class ProviderModelPayload(BaseModel):
provider_account_id: int
model_code: str
model_name: str
request_content_type: str = "application/json"
supports_text_to_video: bool = True
supports_image_to_video: bool = False
supports_video_reference: bool = False
supports_audio_reference: bool = False
supports_generate_audio: bool = False
supports_remix: bool = False
supports_webhook: bool = False
min_duration: int = 4
max_duration: int = 12
default_ratio: str = "16:9"
default_resolution: str = "1280x720"
status: int = 1

View File

@@ -0,0 +1,112 @@
from sqlalchemy.orm import Session
from app.common.errors.app_error import NotFoundAppError
from app.models.entities import ProviderAccount, ProviderModel
from app.modules.providers.repository import ProvidersRepository
class ProvidersService:
def __init__(self, db: Session) -> None:
self.db = db
self.repository = ProvidersRepository(db)
def list_accounts(self) -> list[dict]:
return [self.serialize_account(item) for item in self.repository.list_accounts().all()]
def create_account(self, payload) -> dict:
item = ProviderAccount(
provider_code=payload.provider_code,
provider_name=payload.provider_name,
api_format=payload.api_format,
base_url=payload.base_url,
api_key_encrypted=payload.api_key,
api_secret_encrypted=payload.api_secret,
webhook_secret_encrypted=payload.webhook_secret,
timeout_seconds=payload.timeout_seconds,
max_retries=payload.max_retries,
status=payload.status,
remark=payload.remark,
)
self.db.add(item)
self.db.commit()
self.db.refresh(item)
return self.serialize_account(item)
def update_account(self, account_id: int, payload) -> dict:
item = self.repository.get_account(account_id)
if not item:
raise NotFoundAppError("provider account not found", code=60001)
item.provider_code = payload.provider_code
item.provider_name = payload.provider_name
item.api_format = payload.api_format
item.base_url = payload.base_url
item.api_key_encrypted = payload.api_key
item.api_secret_encrypted = payload.api_secret
item.webhook_secret_encrypted = payload.webhook_secret
item.timeout_seconds = payload.timeout_seconds
item.max_retries = payload.max_retries
item.status = payload.status
item.remark = payload.remark
self.db.commit()
return self.serialize_account(item)
def list_models(self) -> list[dict]:
accounts = {item.id: item for item in self.repository.list_accounts().all()}
return [self.serialize_model(item, accounts) for item in self.repository.list_models().all()]
def create_model(self, payload) -> dict:
item = ProviderModel(**payload.model_dump())
self.db.add(item)
self.db.commit()
self.db.refresh(item)
account = self.repository.get_account(item.provider_account_id)
return self.serialize_model(item, {account.id: account} if account else {})
def update_model(self, model_id: int, payload) -> dict:
item = self.repository.get_model(model_id)
if not item:
raise NotFoundAppError("provider model not found", code=60002)
for key, value in payload.model_dump().items():
setattr(item, key, value)
self.db.commit()
account = self.repository.get_account(item.provider_account_id)
return self.serialize_model(item, {account.id: account} if account else {})
@staticmethod
def serialize_account(item: ProviderAccount) -> dict:
return {
"id": item.id,
"providerCode": item.provider_code,
"providerName": item.provider_name,
"apiFormat": item.api_format,
"baseUrl": item.base_url,
"timeoutSeconds": item.timeout_seconds,
"maxRetries": item.max_retries,
"status": item.status,
"remark": item.remark,
"updatedAt": item.updated_at.isoformat(),
}
@staticmethod
def serialize_model(item: ProviderModel, accounts: dict[int, ProviderAccount]) -> dict:
account = accounts.get(item.provider_account_id)
return {
"id": item.id,
"providerAccountId": item.provider_account_id,
"providerName": account.provider_name if account else "",
"modelCode": item.model_code,
"modelName": item.model_name,
"requestContentType": item.request_content_type,
"supportsTextToVideo": item.supports_text_to_video,
"supportsImageToVideo": item.supports_image_to_video,
"supportsVideoReference": item.supports_video_reference,
"supportsAudioReference": item.supports_audio_reference,
"supportsGenerateAudio": item.supports_generate_audio,
"supportsWebhook": item.supports_webhook,
"minDuration": item.min_duration,
"maxDuration": item.max_duration,
"defaultRatio": item.default_ratio,
"defaultResolution": item.default_resolution,
"status": item.status,
}