This commit is contained in:
@@ -15,7 +15,8 @@ from utils.async_file_utils import (
|
|||||||
async_file_exists,
|
async_file_exists,
|
||||||
async_set_file_mtime,
|
async_set_file_mtime,
|
||||||
async_batch_nfo_operations,
|
async_batch_nfo_operations,
|
||||||
async_concurrent_episode_processing
|
async_concurrent_episode_processing,
|
||||||
|
aiofiles
|
||||||
)
|
)
|
||||||
from utils.nfo_patterns import (
|
from utils.nfo_patterns import (
|
||||||
create_basic_nfo_structure,
|
create_basic_nfo_structure,
|
||||||
@@ -24,6 +25,7 @@ from utils.nfo_patterns import (
|
|||||||
extract_imdb_id_from_text
|
extract_imdb_id_from_text
|
||||||
)
|
)
|
||||||
from utils.validation import validate_date_string
|
from utils.validation import validate_date_string
|
||||||
|
from utils.file_utils import VIDEO_EXTENSIONS
|
||||||
|
|
||||||
|
|
||||||
class AsyncNFOManager:
|
class AsyncNFOManager:
|
||||||
@@ -33,6 +35,54 @@ class AsyncNFOManager:
|
|||||||
self.manager_brand = manager_brand
|
self.manager_brand = manager_brand
|
||||||
self.debug = debug
|
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 def async_parse_imdb_from_path(self, path: Path) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Async extract IMDb ID from directory path or filename
|
Async extract IMDb ID from directory path or filename
|
||||||
@@ -184,7 +234,7 @@ class AsyncNFOManager:
|
|||||||
lock_metadata: bool = True
|
lock_metadata: bool = True
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Async create episode NFO file
|
Async create episode NFO file with proper video filename matching
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
season_dir: Path to season directory
|
season_dir: Path to season directory
|
||||||
@@ -199,8 +249,8 @@ class AsyncNFOManager:
|
|||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
nfo_filename = f"S{season:02d}E{episode:02d}.nfo"
|
# Use proper video filename matching to prevent NFO concatenation
|
||||||
nfo_path = season_dir / nfo_filename
|
nfo_path = await self._async_get_target_nfo_path(season_dir, season, episode)
|
||||||
|
|
||||||
# Prepare dates
|
# Prepare dates
|
||||||
dates = {}
|
dates = {}
|
||||||
|
|||||||
Reference in New Issue
Block a user