feat: Add NFO configuration settings (Task 7)

- Added NFOConfig model with TMDB API key, auto-create, media downloads, image size settings
- Created NFO settings section in UI with form fields and validation
- Implemented nfo-config.js module for loading, saving, and testing TMDB connection
- Added TMDB API key validation endpoint (POST /api/config/tmdb/validate)
- Integrated NFO config into AppConfig and ConfigUpdate models
- Added 5 unit tests for NFO config model validation
- Added API test for TMDB validation endpoint
- All 16 config model tests passing, all 10 config API tests passing
- Documented in docs/task7_status.md (100% complete)
This commit is contained in:
2026-01-16 19:33:23 +01:00
parent ecfa8d3c10
commit 120b26b9f7
8 changed files with 635 additions and 0 deletions

View File

@@ -371,3 +371,59 @@ def reset_config(
detail=f"Failed to reset config: {e}"
) from e
@router.post("/tmdb/validate", response_model=Dict[str, Any])
async def validate_tmdb_key(
api_key_data: Dict[str, str], auth: dict = Depends(require_auth)
) -> Dict[str, Any]:
"""Validate TMDB API key by making a test request.
Args:
api_key_data: Dictionary with 'api_key' field
auth: Authentication token (required)
Returns:
Validation result with success status and message
"""
import aiohttp
api_key = api_key_data.get("api_key", "").strip()
if not api_key:
return {
"valid": False,
"message": "API key is required"
}
try:
# Test the API key with a simple configuration request
url = f"https://api.themoviedb.org/3/configuration?api_key={api_key}"
timeout = aiohttp.ClientTimeout(total=10)
async with aiohttp.ClientSession() as session:
async with session.get(url, timeout=timeout) as response:
if response.status == 200:
return {
"valid": True,
"message": "TMDB API key is valid"
}
elif response.status == 401:
return {
"valid": False,
"message": "Invalid API key"
}
else:
return {
"valid": False,
"message": f"TMDB API error: {response.status}"
}
except aiohttp.ClientError as e:
return {
"valid": False,
"message": f"Connection error: {str(e)}"
}
except Exception as e:
return {
"valid": False,
"message": f"Validation error: {str(e)}"
}