feat(setup): track unresolved folders for manual key resolution
When SetupService cannot auto-resolve a provider key for an anime folder,
the folder is now tracked in the new 'unresolved_folders' table instead of
being silently skipped. Users can then resolve these via the new API:
- GET /api/setup/unresolved - list unresolved folders with search suggestions
- POST /api/setup/unresolved/{folder}/resolve - provide key to resolve folder
The SetupService.run() now:
- Tracks unresolved folders instead of skipping them
- Re-creates AnimeSeries for previously unresolved folders that are now resolved
- Includes unresolved count in logs
New files:
- src/server/api/setup_endpoints.py - API endpoints for unresolved management
- tests/unit/test_unresolved_folder_service.py - service and model tests
Modified:
- src/server/database/models.py - add UnresolvedFolder model
- src/server/database/service.py - add UnresolvedFolderService
- src/server/services/setup_service.py - track unresolved folders
- src/server/fastapi_app.py - include setup router
This commit is contained in:
@@ -20,7 +20,7 @@ import structlog
|
||||
|
||||
from src.config.settings import settings
|
||||
from src.server.database.connection import get_db_session
|
||||
from src.server.database.service import AnimeSeriesService
|
||||
from src.server.database.service import AnimeSeriesService, UnresolvedFolderService
|
||||
from src.server.utils.dependencies import get_series_app
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
@@ -281,6 +281,7 @@ class SetupService:
|
||||
|
||||
created_count = 0
|
||||
skipped_existing = 0
|
||||
unresolved_count = 0
|
||||
|
||||
try:
|
||||
series_app = get_series_app()
|
||||
@@ -300,6 +301,43 @@ class SetupService:
|
||||
skipped_existing += 1
|
||||
continue
|
||||
|
||||
# Check if already tracked as unresolved
|
||||
existing_unresolved = await UnresolvedFolderService.get_by_folder_name(
|
||||
db, folder_name
|
||||
)
|
||||
if existing_unresolved and existing_unresolved.is_resolved:
|
||||
# Was previously unresolved but now resolved - create the series
|
||||
resolved_key = existing_unresolved.provider_key
|
||||
year = cls._extract_year_from_folder_name(folder_name)
|
||||
title = cls._extract_title_from_folder_name(folder_name)
|
||||
props = cls._get_series_properties(folder)
|
||||
|
||||
series = await AnimeSeriesService.create(
|
||||
db=db,
|
||||
key=resolved_key,
|
||||
name=title,
|
||||
site="https://aniworld.to",
|
||||
folder=folder_name,
|
||||
year=year,
|
||||
loading_status="completed",
|
||||
episodes_loaded=True,
|
||||
logo_loaded=props.logo_loaded,
|
||||
images_loaded=props.images_loaded,
|
||||
has_nfo=props.has_nfo,
|
||||
nfo_path=props.nfo_path,
|
||||
nfo_created_at=props.nfo_created_at,
|
||||
nfo_updated_at=props.nfo_updated_at,
|
||||
)
|
||||
created_count += 1
|
||||
|
||||
# Delete the unresolved tracking now that series is created
|
||||
await UnresolvedFolderService.delete(db, folder_name)
|
||||
continue
|
||||
elif existing_unresolved:
|
||||
# Already tracked as unresolved, skip
|
||||
unresolved_count += 1
|
||||
continue
|
||||
|
||||
# Extract title and year from folder name
|
||||
year = cls._extract_year_from_folder_name(folder_name)
|
||||
title = cls._extract_title_from_folder_name(folder_name)
|
||||
@@ -315,8 +353,24 @@ class SetupService:
|
||||
resolved_key = await cls._resolve_key_via_search(title)
|
||||
|
||||
if not resolved_key:
|
||||
# Track unresolved folder for later manual resolution
|
||||
import json
|
||||
try:
|
||||
series_results = await series_app.search(title)
|
||||
search_result_json = json.dumps(series_results) if series_results else None
|
||||
except Exception:
|
||||
search_result_json = None
|
||||
|
||||
await UnresolvedFolderService.create(
|
||||
db=db,
|
||||
folder_name=folder_name,
|
||||
title=title,
|
||||
year=year,
|
||||
search_attempts=1,
|
||||
last_search_result=search_result_json,
|
||||
)
|
||||
logger.warning(
|
||||
"Could not resolve series key for folder, skipping: %s",
|
||||
"Could not resolve series key for folder, tracking as unresolved: %s",
|
||||
folder_name
|
||||
)
|
||||
continue
|
||||
@@ -357,7 +411,8 @@ class SetupService:
|
||||
logger.info(
|
||||
"Setup complete",
|
||||
created=created_count,
|
||||
skipped_existing=skipped_existing
|
||||
skipped_existing=skipped_existing,
|
||||
unresolved=unresolved_count
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user