feat(setup): add SetupService for anime folder initialization
Extract SetupService class from initialization_service to handle: - Scan data/ folder subdirectories - Extract title and year from folder names (YYYY pattern) - Create AnimeSeries records in database - Resolve provider keys via search (single exact match) Updates _scan_folders_to_database() to delegate to SetupService.run(). Adds comprehensive unit tests for SetupService.
This commit is contained in:
@@ -10,6 +10,7 @@ import structlog
|
||||
from src.config.settings import settings
|
||||
from src.server.database.service import AnimeSeriesService
|
||||
from src.server.services.anime_service import sync_legacy_series_to_db
|
||||
from src.server.services.setup_service import SetupService
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
@@ -259,7 +260,8 @@ async def _load_series_into_memory(progress_service=None) -> None:
|
||||
async def _scan_folders_to_database(progress_service=None) -> int:
|
||||
"""Scan anime folders and create AnimeSeries DB records.
|
||||
|
||||
This function runs during initial setup only. It:
|
||||
This function runs during initial setup only. It delegates to
|
||||
SetupService.run() which handles:
|
||||
1. Iterates subdirectories of anime_directory
|
||||
2. Extracts title/year from folder names (year via (YYYY) pattern)
|
||||
3. Uses provider search to resolve key field when single match found
|
||||
@@ -271,9 +273,6 @@ async def _scan_folders_to_database(progress_service=None) -> int:
|
||||
Returns:
|
||||
int: Number of new series created
|
||||
"""
|
||||
from src.server.database.connection import get_db_session
|
||||
from src.server.utils.dependencies import get_series_app
|
||||
|
||||
logger.info("Scanning anime folders for new series...")
|
||||
|
||||
if not settings.anime_directory or not os.path.isdir(settings.anime_directory):
|
||||
@@ -282,80 +281,12 @@ async def _scan_folders_to_database(progress_service=None) -> int:
|
||||
)
|
||||
return 0
|
||||
|
||||
created_count = 0
|
||||
skipped_existing = 0
|
||||
|
||||
try:
|
||||
series_app = get_series_app()
|
||||
|
||||
async with get_db_session() as db:
|
||||
for folder in settings.anime_directory.iterdir():
|
||||
if not folder.is_dir():
|
||||
continue
|
||||
|
||||
folder_name = folder.name
|
||||
|
||||
# Skip if series already exists in DB
|
||||
existing = await AnimeSeriesService.get_by_folder(db, folder_name)
|
||||
if existing:
|
||||
skipped_existing += 1
|
||||
continue
|
||||
|
||||
# Extract year from folder name using (YYYY) pattern
|
||||
year = None
|
||||
match = re.search(r'\((\d{4})\)', folder_name)
|
||||
if match:
|
||||
year = int(match.group(1))
|
||||
|
||||
# Extract title by removing year suffix
|
||||
title = re.sub(r'\s*\(\d{4}\)\s*$', '', folder_name).strip()
|
||||
|
||||
# Try to resolve key via provider search
|
||||
resolved_key = ""
|
||||
if title:
|
||||
try:
|
||||
results = await series_app.search(title)
|
||||
if len(results) == 1:
|
||||
result_name = results[0].get('name', '').lower()
|
||||
if result_name == title.lower():
|
||||
resolved_key = results[0].get('key', '')
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
"Provider search failed for folder",
|
||||
folder=folder_name,
|
||||
error=str(exc)
|
||||
)
|
||||
|
||||
# Create AnimeSeries record
|
||||
await AnimeSeriesService.create(
|
||||
db=db,
|
||||
key=resolved_key,
|
||||
name=title,
|
||||
site=ANIMEWORLD_URL,
|
||||
folder=folder_name,
|
||||
year=year,
|
||||
)
|
||||
created_count += 1
|
||||
logger.debug(
|
||||
"Created series from folder",
|
||||
folder=folder_name,
|
||||
title=title,
|
||||
year=year,
|
||||
key=resolved_key or "(unresolved)"
|
||||
)
|
||||
|
||||
except Exception as exc:
|
||||
logger.error(
|
||||
"Folder scan failed",
|
||||
error=str(exc),
|
||||
exc_info=True
|
||||
)
|
||||
return created_count
|
||||
# Use SetupService to handle the scanning and creation
|
||||
created_count = await SetupService.run()
|
||||
|
||||
logger.info(
|
||||
"Folder scan complete",
|
||||
created=created_count,
|
||||
skipped_existing=skipped_existing
|
||||
created=created_count
|
||||
)
|
||||
return created_count
|
||||
|
||||
|
||||
Reference in New Issue
Block a user