fix: queue background loading after folder resolve; extract year from NFO
This commit is contained in:
@@ -14,7 +14,9 @@ from pydantic import BaseModel, Field
|
|||||||
|
|
||||||
from src.server.database.connection import get_db_session
|
from src.server.database.connection import get_db_session
|
||||||
from src.server.database.service import AnimeSeriesService, UnresolvedFolderService
|
from src.server.database.service import AnimeSeriesService, UnresolvedFolderService
|
||||||
|
from src.server.services.background_loader_service import BackgroundLoaderService
|
||||||
from src.server.utils.dependencies import (
|
from src.server.utils.dependencies import (
|
||||||
|
get_background_loader_service,
|
||||||
get_database_session,
|
get_database_session,
|
||||||
get_series_app,
|
get_series_app,
|
||||||
require_auth,
|
require_auth,
|
||||||
@@ -150,6 +152,7 @@ async def resolve_unresolved_folder(
|
|||||||
folder_name: str,
|
folder_name: str,
|
||||||
request: ResolveFolderRequest,
|
request: ResolveFolderRequest,
|
||||||
db=Depends(get_database_session),
|
db=Depends(get_database_session),
|
||||||
|
background_loader: BackgroundLoaderService = Depends(get_background_loader_service),
|
||||||
) -> ResolveFolderResponse:
|
) -> ResolveFolderResponse:
|
||||||
"""Resolve an unresolved folder by providing the correct provider key.
|
"""Resolve an unresolved folder by providing the correct provider key.
|
||||||
|
|
||||||
@@ -215,6 +218,26 @@ async def resolve_unresolved_folder(
|
|||||||
folder_name, request.provider_key, series.id
|
folder_name, request.provider_key, series.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Queue background loading task for episodes, NFO, and images
|
||||||
|
try:
|
||||||
|
await background_loader.add_series_loading_task(
|
||||||
|
key=request.provider_key,
|
||||||
|
folder=folder_name,
|
||||||
|
name=unresolved.title,
|
||||||
|
year=unresolved.year,
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
"Queued background loading for resolved folder: %s (key=%s)",
|
||||||
|
folder_name,
|
||||||
|
request.provider_key
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(
|
||||||
|
"Failed to queue background loading for resolved folder %s: %s",
|
||||||
|
folder_name,
|
||||||
|
e
|
||||||
|
)
|
||||||
|
|
||||||
return ResolveFolderResponse(
|
return ResolveFolderResponse(
|
||||||
status="success",
|
status="success",
|
||||||
message=f"Successfully resolved and added series: {unresolved.title}",
|
message=f"Successfully resolved and added series: {unresolved.title}",
|
||||||
|
|||||||
@@ -350,11 +350,16 @@ class NfoScanService:
|
|||||||
return "created"
|
return "created"
|
||||||
|
|
||||||
# NFO exists — check if it needs updating
|
# NFO exists — check if it needs updating
|
||||||
updated = await self._update_nfo_if_needed(key, folder, series_data, nfo_path)
|
updated, year = await self._update_nfo_if_needed(key, folder, series_data, nfo_path)
|
||||||
if updated:
|
if updated:
|
||||||
await self._update_series_nfo_flag(key, has_nfo=True, nfo_path=nfo_path)
|
await self._update_series_nfo_flag(key, has_nfo=True, nfo_path=nfo_path, year=year)
|
||||||
return "updated"
|
return "updated"
|
||||||
|
|
||||||
|
# NFO is valid but series may still be missing year — try to extract from NFO
|
||||||
|
if year is not None and series_data.get("year") is None:
|
||||||
|
logger.info("Extracted year %d from NFO for %s — updating database", year, key)
|
||||||
|
await self._update_series_nfo_flag(key, has_nfo=True, nfo_path=nfo_path, year=year)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def _create_nfo(
|
async def _create_nfo(
|
||||||
@@ -421,7 +426,7 @@ class NfoScanService:
|
|||||||
folder: str,
|
folder: str,
|
||||||
series_data: Dict[str, Any],
|
series_data: Dict[str, Any],
|
||||||
nfo_path: str,
|
nfo_path: str,
|
||||||
) -> bool:
|
) -> tuple[bool, Optional[int]]:
|
||||||
"""Load existing NFO, check for missing fields, fill and rewrite.
|
"""Load existing NFO, check for missing fields, fill and rewrite.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -431,13 +436,13 @@ class NfoScanService:
|
|||||||
nfo_path: Full path to the existing NFO file
|
nfo_path: Full path to the existing NFO file
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if NFO was updated, False if no changes were needed.
|
Tuple of (True if NFO was updated, extracted year from NFO or None).
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
except ImportError:
|
except ImportError:
|
||||||
logger.warning("lxml not available — cannot update existing NFO files")
|
logger.warning("lxml not available — cannot update existing NFO files")
|
||||||
return False
|
return False, None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tree = etree.parse(nfo_path)
|
tree = etree.parse(nfo_path)
|
||||||
@@ -445,7 +450,17 @@ class NfoScanService:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.warning("Failed to parse existing NFO for %s: %s — will regenerate", key, exc)
|
logger.warning("Failed to parse existing NFO for %s: %s — will regenerate", key, exc)
|
||||||
# Corrupt or unreadable NFO — regenerate from TMDB
|
# Corrupt or unreadable NFO — regenerate from TMDB
|
||||||
return await self._regenerate_nfo(key, folder, series_data, nfo_path)
|
updated = await self._regenerate_nfo(key, folder, series_data, nfo_path)
|
||||||
|
return updated, None
|
||||||
|
|
||||||
|
# Extract year from NFO if present
|
||||||
|
year: Optional[int] = None
|
||||||
|
year_elem = root.find("year")
|
||||||
|
if year_elem is not None and year_elem.text and year_elem.text.strip():
|
||||||
|
try:
|
||||||
|
year = int(year_elem.text.strip())
|
||||||
|
except ValueError:
|
||||||
|
logger.debug("Invalid year value in NFO for %s: %s", key, year_elem.text)
|
||||||
|
|
||||||
# Check for missing or empty critical fields
|
# Check for missing or empty critical fields
|
||||||
critical_fields = ["title", "plot", "premiered", "tmdbid"]
|
critical_fields = ["title", "plot", "premiered", "tmdbid"]
|
||||||
@@ -458,7 +473,7 @@ class NfoScanService:
|
|||||||
|
|
||||||
if not missing_fields:
|
if not missing_fields:
|
||||||
logger.debug("NFO for %s is complete — no update needed", key)
|
logger.debug("NFO for %s is complete — no update needed", key)
|
||||||
return False
|
return False, year
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"NFO for %s is missing fields %s — attempting to fill from TMDB",
|
"NFO for %s is missing fields %s — attempting to fill from TMDB",
|
||||||
@@ -470,16 +485,16 @@ class NfoScanService:
|
|||||||
tmdb_id = series_data.get("tmdb_id")
|
tmdb_id = series_data.get("tmdb_id")
|
||||||
if not tmdb_id:
|
if not tmdb_id:
|
||||||
logger.warning("Cannot update NFO for %s: no tmdb_id", key)
|
logger.warning("Cannot update NFO for %s: no tmdb_id", key)
|
||||||
return False
|
return False, year
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tmdb_data = await self._fetch_tmdb_data(tmdb_id)
|
tmdb_data = await self._fetch_tmdb_data(tmdb_id)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.warning("Failed to fetch TMDB data for %s: %s", key, exc)
|
logger.warning("Failed to fetch TMDB data for %s: %s", key, exc)
|
||||||
return False
|
return False, year
|
||||||
|
|
||||||
if not tmdb_data:
|
if not tmdb_data:
|
||||||
return False
|
return False, year
|
||||||
|
|
||||||
nfo_model = tmdb_to_nfo_model(
|
nfo_model = tmdb_to_nfo_model(
|
||||||
tmdb_data,
|
tmdb_data,
|
||||||
@@ -504,7 +519,7 @@ class NfoScanService:
|
|||||||
"missing_fields": missing_fields,
|
"missing_fields": missing_fields,
|
||||||
})
|
})
|
||||||
|
|
||||||
return True
|
return True, year
|
||||||
|
|
||||||
async def _regenerate_nfo(
|
async def _regenerate_nfo(
|
||||||
self,
|
self,
|
||||||
@@ -626,13 +641,15 @@ class NfoScanService:
|
|||||||
key: str,
|
key: str,
|
||||||
has_nfo: bool,
|
has_nfo: bool,
|
||||||
nfo_path: str,
|
nfo_path: str,
|
||||||
|
year: Optional[int] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Update the has_nfo flag and nfo_path in the database.
|
"""Update the has_nfo flag, nfo_path, and optionally year in the database.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Series key (primary identifier)
|
key: Series key (primary identifier)
|
||||||
has_nfo: Whether the series now has an NFO file
|
has_nfo: Whether the series now has an NFO file
|
||||||
nfo_path: Path to the NFO file
|
nfo_path: Path to the NFO file
|
||||||
|
year: Optional year extracted from NFO to save to DB
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from src.server.database.connection import get_db_session
|
from src.server.database.connection import get_db_session
|
||||||
@@ -647,6 +664,10 @@ class NfoScanService:
|
|||||||
if series.nfo_created_at is None:
|
if series.nfo_created_at is None:
|
||||||
series.nfo_created_at = now
|
series.nfo_created_at = now
|
||||||
series.nfo_updated_at = now
|
series.nfo_updated_at = now
|
||||||
|
# Update year if series has no year and we have one from NFO
|
||||||
|
if year is not None and series.year is None:
|
||||||
|
series.year = year
|
||||||
|
logger.info("Updated year to %d for series: %s", year, key)
|
||||||
await db.flush()
|
await db.flush()
|
||||||
logger.debug("Updated NFO flag for series: %s", key)
|
logger.debug("Updated NFO flag for series: %s", key)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
Reference in New Issue
Block a user