Files
2026-07-13 13:08:41 +08:00

173 lines
5.1 KiB
Python

from pathlib import Path
from typing import List, Optional
from fastapi import APIRouter, File, HTTPException, UploadFile
from pydantic import BaseModel
from templates.preview import FontCheckResponse, check_fonts_in_pptx_handler
from utils.font_uploads import (
FONT_CONTENT_TYPES,
delete_font_upload,
font_upload_to_info,
get_font_upload_url,
list_font_uploads,
persist_upload_file,
)
FONTS_ROUTER = APIRouter(prefix="/fonts", tags=["fonts"])
SUPPORTED_FONT_EXTENSIONS = FONT_CONTENT_TYPES
class FontUploadResponse(BaseModel):
success: bool
font_name: str
font_url: str
font_path: str
message: Optional[str] = None
class FontListResponse(BaseModel):
success: bool
fonts: List[dict]
message: Optional[str] = None
class UploadedFontsResponse(BaseModel):
fonts: List[dict]
def _font_display_name(font_info) -> str:
return (
font_info.family_name
or font_info.full_name
or font_info.normalized_family_name
or Path(font_info.filename).stem
)
def _font_original_name(filename: str) -> str:
path = Path(filename)
stem = path.stem
if "_" in stem and len(stem.rsplit("_", 1)[-1]) == 8:
stem = stem.rsplit("_", 1)[0]
return f"{stem}{path.suffix}"
@FONTS_ROUTER.post("/upload", response_model=FontUploadResponse)
async def upload_font(
font_file: UploadFile = File(
..., description="Font file to upload (.ttf, .otf, .woff, .woff2, .eot)"
)
):
try:
if not font_file.filename:
raise HTTPException(status_code=400, detail="No file name provided")
font_upload, _font_path = await persist_upload_file(font_file)
font_info = await font_upload_to_info(font_upload)
font_name = _font_display_name(font_info)
return FontUploadResponse(
success=True,
font_name=font_name,
font_url=await get_font_upload_url(font_upload),
font_path=font_info.path,
message=f"Font '{font_name}' uploaded successfully",
)
except HTTPException:
raise
except Exception as exc:
print(f"Error uploading font: {exc}")
raise HTTPException(
status_code=500, detail=f"Error uploading font: {exc}"
) from exc
@FONTS_ROUTER.get("/list", response_model=FontListResponse)
async def list_fonts():
try:
response = await list_font_uploads()
fonts = []
for font_info in response.fonts:
file_ext = Path(font_info.filename).suffix.lower()
fonts.append(
{
"id": str(font_info.id),
"filename": font_info.filename,
"font_name": _font_display_name(font_info),
"original_name": _font_original_name(font_info.filename),
"font_url": font_info.url,
"font_path": font_info.path,
"font_type": SUPPORTED_FONT_EXTENSIONS.get(file_ext, "unknown"),
"file_size": font_info.size_bytes,
"family_name": font_info.family_name,
"subfamily_name": font_info.subfamily_name,
"full_name": font_info.full_name,
"postscript_name": font_info.postscript_name,
"normalized_family_name": font_info.normalized_family_name,
"weight_class": font_info.weight_class,
"width_class": font_info.width_class,
"format": font_info.format,
}
)
return FontListResponse(
success=True,
fonts=fonts,
message=f"Found {len(fonts)} font files",
)
except Exception as exc:
print(f"Error listing fonts: {exc}")
raise HTTPException(
status_code=500, detail=f"Error listing fonts: {exc}"
) from exc
@FONTS_ROUTER.get("/uploaded", response_model=UploadedFontsResponse)
async def get_uploaded_fonts():
try:
response = await list_font_uploads()
return UploadedFontsResponse(
fonts=[
{
"id": str(font_info.id),
"name": _font_display_name(font_info),
"url": font_info.url,
}
for font_info in response.fonts
]
)
except Exception as exc:
print(f"Error getting uploaded fonts: {exc}")
raise HTTPException(
status_code=500, detail=f"Error getting uploaded fonts: {exc}"
) from exc
FONTS_ROUTER.post("/check", response_model=FontCheckResponse)(
check_fonts_in_pptx_handler
)
@FONTS_ROUTER.delete("/delete/{filename}")
async def delete_font(filename: str):
try:
deleted = await delete_font_upload(filename)
return {
"success": True,
"message": f"Font '{deleted.filename}' deleted successfully",
}
except HTTPException:
raise
except Exception as exc:
print(f"Error deleting font: {exc}")
raise HTTPException(
status_code=500, detail=f"Error deleting font: {exc}"
) from exc