Initial upload for secondary development

This commit is contained in:
2026-06-08 19:00:03 +08:00
commit b913b8c78c
81 changed files with 27139 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
from fastapi import APIRouter, Depends
from pydantic import BaseModel
from typing import Optional
import aiosqlite
from database import get_db
router = APIRouter(prefix="/api/settings", tags=["settings"])
EDITABLE_KEYS = [
"ai_base_url", "ai_api_key", "ai_model", "summary_model",
"vision_model", "voice_model", "topic_analysis_prompt",
]
def _mask_key(value: str) -> str:
if not value or len(value) <= 8:
return "*" * len(value) if value else ""
return value[:3] + "*" * (len(value) - 7) + value[-4:]
@router.get("")
async def get_settings(db: aiosqlite.Connection = Depends(get_db)):
result = {}
placeholders = ",".join("?" for _ in EDITABLE_KEYS)
async with db.execute(
f"SELECT key, value FROM app_settings WHERE key IN ({placeholders})",
EDITABLE_KEYS,
) as cur:
rows = await cur.fetchall()
for row in rows:
k, v = row["key"], row["value"]
result[k] = _mask_key(v) if k == "ai_api_key" else v
for k in EDITABLE_KEYS:
if k not in result:
result[k] = ""
return result
class SettingsUpdate(BaseModel):
ai_base_url: Optional[str] = None
ai_api_key: Optional[str] = None
ai_model: Optional[str] = None
summary_model: Optional[str] = None
vision_model: Optional[str] = None
voice_model: Optional[str] = None
topic_analysis_prompt: Optional[str] = None
@router.put("")
async def update_settings(body: SettingsUpdate, db: aiosqlite.Connection = Depends(get_db)):
updates = body.model_dump(exclude_none=True)
for k, v in updates.items():
if k not in EDITABLE_KEYS:
continue
if k == "ai_api_key" and "*" in v:
continue
await db.execute(
"INSERT INTO app_settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = ?",
(k, v, v),
)
await db.commit()
from services.runtime_settings import invalidate_cache
invalidate_cache()
return {"status": "ok"}