dev #66

Merged
sbcrumb merged 20 commits from dev into main 2025-11-02 12:41:59 -05:00
Showing only changes of commit 1916dc2646 - Show all commits
+54 -4
View File
@@ -15,7 +15,8 @@ from utils.async_file_utils import (
async_file_exists,
async_set_file_mtime,
async_batch_nfo_operations,
async_concurrent_episode_processing
async_concurrent_episode_processing,
aiofiles
)
from utils.nfo_patterns import (
create_basic_nfo_structure,
@@ -24,6 +25,7 @@ from utils.nfo_patterns import (
extract_imdb_id_from_text
)
from utils.validation import validate_date_string
from utils.file_utils import VIDEO_EXTENSIONS
class AsyncNFOManager:
@@ -33,6 +35,54 @@ class AsyncNFOManager:
self.manager_brand = manager_brand
self.debug = debug
async def _async_get_target_nfo_path(self, season_dir: Path, season: int, episode: int) -> Path:
"""
Get the target NFO path using video filename matching to prevent concatenation
Args:
season_dir: Path to season directory
season: Season number
episode: Episode number
Returns:
Path to target NFO file (video-matching preferred, generic fallback)
"""
try:
# Find video files in the season directory
video_files = []
if await async_file_exists(season_dir):
import re
try:
entries = await aiofiles.os.listdir(season_dir)
for entry in entries:
entry_path = season_dir / entry
if await aiofiles.os.path.isfile(entry_path):
if entry_path.suffix.lower() in VIDEO_EXTENSIONS:
# Parse episode info from filename
match = re.search(r'[Ss](\d{1,2})[Ee](\d{1,2})', entry)
if match:
s, e = int(match.group(1)), int(match.group(2))
if s == season and e == episode:
# Found matching video file - use its name for NFO
target_nfo = season_dir / f"{entry_path.stem}.nfo"
if self.debug:
_log("DEBUG", f"Video-matching NFO path: {target_nfo.name}")
return target_nfo
except Exception as e:
if self.debug:
_log("WARNING", f"Failed to scan season directory {season_dir}: {e}")
# Fallback to generic filename if no matching video found
target_nfo = season_dir / f"S{season:02d}E{episode:02d}.nfo"
if self.debug:
_log("WARNING", f"No video file found for S{season:02d}E{episode:02d}, using generic: {target_nfo.name}")
return target_nfo
except Exception as e:
_log("ERROR", f"Failed to determine NFO path for S{season:02d}E{episode:02d}: {e}")
# Emergency fallback
return season_dir / f"S{season:02d}E{episode:02d}.nfo"
async def async_parse_imdb_from_path(self, path: Path) -> Optional[str]:
"""
Async extract IMDb ID from directory path or filename
@@ -184,7 +234,7 @@ class AsyncNFOManager:
lock_metadata: bool = True
) -> bool:
"""
Async create episode NFO file
Async create episode NFO file with proper video filename matching
Args:
season_dir: Path to season directory
@@ -199,8 +249,8 @@ class AsyncNFOManager:
True if successful, False otherwise
"""
try:
nfo_filename = f"S{season:02d}E{episode:02d}.nfo"
nfo_path = season_dir / nfo_filename
# Use proper video filename matching to prevent NFO concatenation
nfo_path = await self._async_get_target_nfo_path(season_dir, season, episode)
# Prepare dates
dates = {}