feat: add Settings tab with provider management and language preferences
- Implemented AppSettings model and table using SQLModel. - Created Settings router with endpoints for preferences and provider toggling. - Added Settings tab to the UI with real-time health status of providers. - Integrated language and provider filtering into anime and series search logic. - Updated templates to respect user-defined settings.
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
"""Application settings routes for Ohm Stream Downloader API"""
|
||||
import json
|
||||
from typing import List, Dict, Any
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, Response
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from app.database import get_session
|
||||
from app.models.auth import User, UserTable
|
||||
from app.models.settings import AppSettings, AppSettingsTable, AppSettingsUpdate
|
||||
from app.routers.router_auth import get_current_user_from_token
|
||||
from app.providers import get_anime_providers, get_series_providers
|
||||
from app.providers_manager import providers_manager
|
||||
|
||||
router = APIRouter(prefix="/api/settings", tags=["settings"])
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
|
||||
@router.get("", response_model=AppSettings)
|
||||
async def get_settings(
|
||||
current_user: User = Depends(get_current_user_from_token),
|
||||
session: Session = Depends(get_session)
|
||||
):
|
||||
"""Get current application settings for the user"""
|
||||
statement = select(AppSettingsTable).where(AppSettingsTable.user_id == current_user.id)
|
||||
settings_obj = session.exec(statement).first()
|
||||
|
||||
if not settings_obj:
|
||||
# Create default settings if they don't exist
|
||||
settings_obj = AppSettingsTable(user_id=current_user.id)
|
||||
session.add(settings_obj)
|
||||
session.commit()
|
||||
session.refresh(settings_obj)
|
||||
|
||||
return AppSettings(
|
||||
default_lang=settings_obj.default_lang,
|
||||
theme=settings_obj.theme,
|
||||
disabled_providers=settings_obj.disabled_providers
|
||||
)
|
||||
|
||||
|
||||
@router.patch("", response_model=AppSettings)
|
||||
async def update_settings(
|
||||
update_data: AppSettingsUpdate,
|
||||
response: Response,
|
||||
current_user: User = Depends(get_current_user_from_token),
|
||||
session: Session = Depends(get_session)
|
||||
):
|
||||
"""Update application settings for the user"""
|
||||
statement = select(AppSettingsTable).where(AppSettingsTable.user_id == current_user.id)
|
||||
settings_obj = session.exec(statement).first()
|
||||
|
||||
if not settings_obj:
|
||||
settings_obj = AppSettingsTable(user_id=current_user.id)
|
||||
session.add(settings_obj)
|
||||
|
||||
if update_data.default_lang is not None:
|
||||
settings_obj.default_lang = update_data.default_lang
|
||||
if update_data.theme is not None:
|
||||
settings_obj.theme = update_data.theme
|
||||
if update_data.disabled_providers is not None:
|
||||
settings_obj.disabled_providers = update_data.disabled_providers
|
||||
|
||||
session.add(settings_obj)
|
||||
session.commit()
|
||||
session.refresh(settings_obj)
|
||||
|
||||
response.headers["HX-Trigger"] = json.dumps({"show-toast": {"message": "Paramètres enregistrés", "type": "success"}})
|
||||
|
||||
return AppSettings(
|
||||
default_lang=settings_obj.default_lang,
|
||||
theme=settings_obj.theme,
|
||||
disabled_providers=settings_obj.disabled_providers
|
||||
)
|
||||
|
||||
|
||||
@router.get("/providers/availability")
|
||||
async def get_providers_availability(
|
||||
current_user: User = Depends(get_current_user_from_token),
|
||||
session: Session = Depends(get_session)
|
||||
):
|
||||
"""Get list of providers with their availability and enabled status"""
|
||||
# Get user settings
|
||||
statement = select(AppSettingsTable).where(AppSettingsTable.user_id == current_user.id)
|
||||
settings_obj = session.exec(statement).first()
|
||||
disabled_providers = settings_obj.disabled_providers if settings_obj else []
|
||||
|
||||
# Get health status
|
||||
health_status = providers_manager.get_all_status()
|
||||
|
||||
# Combine anime and series providers
|
||||
all_providers = {**get_anime_providers(), **get_series_providers()}
|
||||
|
||||
result = []
|
||||
for pid, info in all_providers.items():
|
||||
status_info = health_status.get(pid, {"status": "unknown"})
|
||||
result.append({
|
||||
"id": pid,
|
||||
"name": info["name"],
|
||||
"icon": info.get("icon", "🎬"),
|
||||
"status": status_info["status"],
|
||||
"enabled": pid not in disabled_providers,
|
||||
"error": status_info.get("error")
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@router.post("/providers/{provider_id}/toggle")
|
||||
async def toggle_provider(
|
||||
provider_id: str,
|
||||
response: Response,
|
||||
current_user: User = Depends(get_current_user_from_token),
|
||||
session: Session = Depends(get_session)
|
||||
):
|
||||
"""Toggle a provider's enabled/disabled status"""
|
||||
statement = select(AppSettingsTable).where(AppSettingsTable.user_id == current_user.id)
|
||||
settings_obj = session.exec(statement).first()
|
||||
|
||||
if not settings_obj:
|
||||
settings_obj = AppSettingsTable(user_id=current_user.id)
|
||||
session.add(settings_obj)
|
||||
|
||||
disabled = settings_obj.disabled_providers
|
||||
if provider_id in disabled:
|
||||
disabled.remove(provider_id)
|
||||
enabled = True
|
||||
else:
|
||||
disabled.append(provider_id)
|
||||
enabled = False
|
||||
|
||||
settings_obj.disabled_providers = disabled
|
||||
session.add(settings_obj)
|
||||
session.commit()
|
||||
|
||||
status_text = "activé" if enabled else "désactivé"
|
||||
response.headers["HX-Trigger"] = json.dumps({"show-toast": {"message": f"Fournisseur {provider_id} {status_text}", "type": "success"}})
|
||||
|
||||
return {"id": provider_id, "enabled": enabled}
|
||||
|
||||
|
||||
@router.get("/ui")
|
||||
async def get_settings_ui(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_user_from_token),
|
||||
session: Session = Depends(get_session)
|
||||
):
|
||||
"""Return the settings UI fragment for HTMX"""
|
||||
# Reuse existing endpoints logic
|
||||
settings = await get_settings(current_user, session)
|
||||
providers = await get_providers_availability(current_user, session)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"components/settings_section.html",
|
||||
{
|
||||
"request": request,
|
||||
"settings": settings,
|
||||
"providers": providers
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user