feat: initialize aivideo project
This commit is contained in:
22
backend/app/modules/providers/repository.py
Normal file
22
backend/app/modules/providers/repository.py
Normal 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))
|
||||
|
||||
66
backend/app/modules/providers/router.py
Normal file
66
backend/app/modules/providers/router.py
Normal 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))
|
||||
|
||||
35
backend/app/modules/providers/schema.py
Normal file
35
backend/app/modules/providers/schema.py
Normal 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
|
||||
|
||||
112
backend/app/modules/providers/service.py
Normal file
112
backend/app/modules/providers/service.py
Normal 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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user