Fix Code Duplication 4: Create media utilities module

- Created src/server/utils/media.py with reusable media file functions
- Functions: check_media_files(), get_media_file_paths(), has_all_images(), count_video_files(), has_video_files()
- Defined standard filename constants: POSTER_FILENAME, LOGO_FILENAME, FANART_FILENAME, NFO_FILENAME
- Defined VIDEO_EXTENSIONS set for media player compatibility
- Refactored src/server/api/nfo.py (7 locations) to use utility functions
- Refactored src/server/services/background_loader_service.py to use utility
- Functions accept both str and Path for compatibility
- Marked Code Duplications 1, 3, 4 as RESOLVED in instructions.md
- Updated Further Considerations as RESOLVED (addressed in Issues 7, 9, 10)
This commit is contained in:
2026-01-24 21:34:43 +01:00
parent 4abaf8def7
commit 46271a9845
6 changed files with 390 additions and 80 deletions

View File

@@ -30,6 +30,7 @@ from src.server.models.nfo import (
NFOMissingSeries,
)
from src.server.utils.dependencies import get_series_app, require_auth
from src.server.utils.media import check_media_files, get_media_file_paths
logger = logging.getLogger(__name__)
@@ -73,31 +74,6 @@ async def get_nfo_service() -> NFOService:
)
def check_media_files(serie_folder: str) -> MediaFilesStatus:
"""Check status of media files for a series.
Args:
serie_folder: Series folder name
Returns:
MediaFilesStatus with file existence info
"""
folder_path = Path(settings.anime_directory) / serie_folder
poster_path = folder_path / "poster.jpg"
logo_path = folder_path / "logo.png"
fanart_path = folder_path / "fanart.jpg"
return MediaFilesStatus(
has_poster=poster_path.exists(),
has_logo=logo_path.exists(),
has_fanart=fanart_path.exists(),
poster_path=str(poster_path) if poster_path.exists() else None,
logo_path=str(logo_path) if logo_path.exists() else None,
fanart_path=str(fanart_path) if fanart_path.exists() else None
)
@router.get("/{serie_id}/check", response_model=NFOCheckResponse)
async def check_nfo(
serie_id: str,
@@ -135,17 +111,35 @@ async def check_nfo(
# Ensure folder name includes year if available
serie_folder = serie.ensure_folder_with_year()
folder_path = Path(settings.anime_directory) / serie_folder
# Check NFO
has_nfo = await nfo_service.check_nfo_exists(serie_folder)
nfo_path = None
if has_nfo:
nfo_path = str(
Path(settings.anime_directory) / serie_folder / "tvshow.nfo"
)
nfo_path = str(folder_path / "tvshow.nfo")
# Check media files
media_files = check_media_files(serie_folder)
# Check media files using utility function
media_status = check_media_files(
folder_path,
check_poster=True,
check_logo=True,
check_fanart=True,
check_nfo=False # Already checked above
)
# Get file paths
file_paths = get_media_file_paths(folder_path)
# Build MediaFilesStatus model
media_files = MediaFilesStatus(
has_poster=media_status.get("poster", False),
has_logo=media_status.get("logo", False),
has_fanart=media_status.get("fanart", False),
poster_path=str(file_paths["poster"]) if file_paths["poster"] else None,
logo_path=str(file_paths["logo"]) if file_paths["logo"] else None,
fanart_path=str(file_paths["fanart"]) if file_paths["fanart"] else None
)
return NFOCheckResponse(
serie_id=serie_id,
@@ -229,7 +223,18 @@ async def create_nfo(
)
# Check media files
media_files = check_media_files(serie_folder)
folder_path = Path(settings.anime_directory) / serie_folder
media_status = check_media_files(folder_path)
file_paths = get_media_file_paths(folder_path)
media_files = MediaFilesStatus(
has_poster=media_status.get("poster", False),
has_logo=media_status.get("logo", False),
has_fanart=media_status.get("fanart", False),
poster_path=str(file_paths["poster"]) if file_paths.get("poster") else None,
logo_path=str(file_paths["logo"]) if file_paths.get("logo") else None,
fanart_path=str(file_paths["fanart"]) if file_paths.get("fanart") else None
)
return NFOCreateResponse(
serie_id=serie_id,
@@ -313,7 +318,18 @@ async def update_nfo(
)
# Check media files
media_files = check_media_files(serie_folder)
folder_path = Path(settings.anime_directory) / serie_folder
media_status = check_media_files(folder_path)
file_paths = get_media_file_paths(folder_path)
media_files = MediaFilesStatus(
has_poster=media_status.get("poster", False),
has_logo=media_status.get("logo", False),
has_fanart=media_status.get("fanart", False),
poster_path=str(file_paths["poster"]) if file_paths.get("poster") else None,
logo_path=str(file_paths["logo"]) if file_paths.get("logo") else None,
fanart_path=str(file_paths["fanart"]) if file_paths.get("fanart") else None
)
return NFOCreateResponse(
serie_id=serie_id,
@@ -449,7 +465,19 @@ async def get_media_status(
detail=f"Series not found: {serie_id}"
)
return check_media_files(serie.folder)
# Build full path and check media files
folder_path = Path(settings.anime_directory) / serie.folder
media_status = check_media_files(folder_path)
file_paths = get_media_file_paths(folder_path)
return MediaFilesStatus(
has_poster=media_status.get("poster", False),
has_logo=media_status.get("logo", False),
has_fanart=media_status.get("fanart", False),
poster_path=str(file_paths["poster"]) if file_paths.get("poster") else None,
logo_path=str(file_paths["logo"]) if file_paths.get("logo") else None,
fanart_path=str(file_paths["fanart"]) if file_paths.get("fanart") else None
)
except HTTPException:
raise
@@ -521,7 +549,19 @@ async def download_media(
download_media=True
)
return check_media_files(serie_folder)
# Build full path and check media files
folder_path = Path(settings.anime_directory) / serie_folder
media_status = check_media_files(folder_path)
file_paths = get_media_file_paths(folder_path)
return MediaFilesStatus(
has_poster=media_status.get("poster", False),
has_logo=media_status.get("logo", False),
has_fanart=media_status.get("fanart", False),
poster_path=str(file_paths["poster"]) if file_paths.get("poster") else None,
logo_path=str(file_paths["logo"]) if file_paths.get("logo") else None,
fanart_path=str(file_paths["fanart"]) if file_paths.get("fanart") else None
)
except HTTPException:
raise
@@ -678,7 +718,20 @@ async def get_missing_nfo(
has_nfo = await nfo_service.check_nfo_exists(serie_folder)
if not has_nfo:
media_files = check_media_files(serie_folder)
# Build full path and check media files
folder_path = Path(settings.anime_directory) / serie_folder
media_status = check_media_files(folder_path)
file_paths = get_media_file_paths(folder_path)
media_files = MediaFilesStatus(
has_poster=media_status.get("poster", False),
has_logo=media_status.get("logo", False),
has_fanart=media_status.get("fanart", False),
poster_path=str(file_paths["poster"]) if file_paths.get("poster") else None,
logo_path=str(file_paths["logo"]) if file_paths.get("logo") else None,
fanart_path=str(file_paths["fanart"]) if file_paths.get("fanart") else None
)
has_media = (
media_files.has_poster
or media_files.has_logo