feat: add Settings tab with provider management and language preferences
CI / Test (Python 3.11) (push) Has been cancelled
CI / Test (Python 3.12) (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Type Check (push) Has been cancelled
CI / Summary (push) Has been cancelled

- 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:
root
2026-03-26 16:12:29 +00:00
parent 3b405f2a42
commit 0c03f4f4a6
15 changed files with 383 additions and 25 deletions
+37 -7
View File
@@ -11,7 +11,12 @@ import hashlib
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Query, Request, Response
from fastapi.templating import Jinja2Templates
from sqlmodel import Session, select
from app.database import get_session
from app.models.settings import AppSettingsTable
from app.routers.router_auth import get_current_user_from_token
from app.models.auth import User
from app.download_manager import DownloadManager
from app.downloaders import (
AnimeSamaDownloader,
@@ -67,6 +72,8 @@ async def search_anime_unified(
lang: str = "vostfr",
include_metadata: bool = False,
html: bool = Query(False),
current_user: User = Depends(get_current_user_from_token),
session: Session = Depends(get_session)
):
"""
Search across all anime providers.
@@ -75,6 +82,11 @@ async def search_anime_unified(
print(f"\n[SEARCH] Starting search for '{q}'. html={html}")
start_time = time.time()
# Get user settings for disabled providers
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 []
results = {}
# 1. Prepare search tasks (Generic + Legacy)
@@ -84,8 +96,9 @@ async def search_anime_unified(
# Generic YAML providers
active_generic = providers_manager.get_active_providers()
for provider in active_generic:
search_tasks.append(provider.search(q))
task_metadata.append({"id": provider.id, "type": "generic"})
if provider.id not in disabled_providers:
search_tasks.append(provider.search(q))
task_metadata.append({"id": provider.id, "type": "generic"})
# Legacy providers
legacy_downloaders = {
@@ -94,8 +107,9 @@ async def search_anime_unified(
"vostfree": VostfreeDownloader(),
}
for pid, dl in legacy_downloaders.items():
search_tasks.append(dl.search_anime(q, lang, include_metadata=False))
task_metadata.append({"id": pid, "type": "legacy"})
if pid not in disabled_providers:
search_tasks.append(dl.search_anime(q, lang, include_metadata=False))
task_metadata.append({"id": pid, "type": "legacy"})
# 2. Run searches in parallel
all_raw_results = await asyncio.gather(*search_tasks, return_exceptions=True)
@@ -163,7 +177,11 @@ async def search_anime_unified(
print("[SEARCH] Returning HTML response")
return templates.TemplateResponse(
"components/anime_search_results.html",
{"request": request, "results": results}
{
"request": request,
"results": results,
"settings": settings_obj
}
)
print("[SEARCH] Returning JSON response")
@@ -181,6 +199,8 @@ async def search_series_unified(
q: str,
lang: str = "vf",
html: bool = Query(False),
current_user: User = Depends(get_current_user_from_token),
session: Session = Depends(get_session)
):
"""
Search across all TV series providers (FS7, etc.)
@@ -191,6 +211,12 @@ async def search_series_unified(
print(f"\n[SERIES SEARCH] Starting search for '{q}' in {lang}. html={html}")
start_time = time.time()
# Get user settings for disabled providers
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 []
results = {}
series_downloaders = {
"fs7": FS7Downloader(),
@@ -200,7 +226,7 @@ async def search_series_unified(
provider_ids = []
for provider_id, provider in get_series_providers().items():
if provider_id in series_downloaders:
if provider_id in series_downloaders and provider_id not in disabled_providers:
downloader = series_downloaders[provider_id]
search_tasks.append(downloader.search_anime(q, lang))
provider_ids.append(provider_id)
@@ -221,7 +247,11 @@ async def search_series_unified(
if html or request.headers.get("HX-Request"):
return templates.TemplateResponse(
"components/series_search_results.html",
{"request": request, "results": results}
{
"request": request,
"results": results,
"settings": settings_obj
}
)
return {"query": q, "lang": lang, "results": results}