From 632ce32cd1b07c62a1c59033532b00161d18b4a7 Mon Sep 17 00:00:00 2001 From: SBCrumb Date: Thu, 25 Sep 2025 09:00:07 -0400 Subject: [PATCH] fix: Add title enhancement for existing NFO files - Modify extract_nfoguard_dates_from_episode_nfo() to detect missing titles - Add enhance_existing_episode_nfo_with_title() method to update NFOs with titles - Enhance Tier 1 processing to check for missing titles in existing NFO files - Extract titles from filenames and update existing NFOs that lack title elements - Fix NFO filename case to match S01E01.nfo format - Preserves all existing NFO content while adding missing title elements Addresses issue where existing NFO files with NFOGuard metadata were skipping title extraction due to Tier 1 optimization caching. --- core/nfo_manager.py | 53 +++++++++++++++++++++++++++++++++++++++++++-- nfoguard.py | 15 +++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/core/nfo_manager.py b/core/nfo_manager.py index 09c4e29..94ade70 100644 --- a/core/nfo_manager.py +++ b/core/nfo_manager.py @@ -163,7 +163,7 @@ class NFOManager: def extract_nfoguard_dates_from_episode_nfo(self, season_path: Path, season_num: int, episode_num: int) -> Optional[Dict[str, str]]: """Extract NFOGuard-managed dates from existing episode NFO file""" - nfo_filename = f"s{season_num:02d}e{episode_num:02d}.nfo" + nfo_filename = f"S{season_num:02d}E{episode_num:02d}.nfo" nfo_path = season_path / nfo_filename if not nfo_path.exists(): @@ -190,7 +190,11 @@ class NFOManager: if aired_elem is not None and aired_elem.text: result["aired"] = aired_elem.text.strip() - print(f"✅ Found NFOGuard data in episode NFO S{season_num:02d}E{episode_num:02d}: dateadded={result['dateadded']}, aired={result.get('aired', 'None')}") + # Check if title is missing + title_elem = root.find('.//title') + result["has_title"] = title_elem is not None and title_elem.text and title_elem.text.strip() + + print(f"✅ Found NFOGuard data in episode NFO S{season_num:02d}E{episode_num:02d}: dateadded={result['dateadded']}, aired={result.get('aired', 'None')}, has_title={result['has_title']}") return result except (ET.ParseError, Exception) as e: @@ -199,6 +203,51 @@ class NFOManager: return None + def enhance_existing_episode_nfo_with_title(self, season_path: Path, season_num: int, episode_num: int, title: str) -> bool: + """Add title to existing episode NFO file that's missing one""" + nfo_filename = f"S{season_num:02d}E{episode_num:02d}.nfo" + nfo_path = season_path / nfo_filename + + if not nfo_path.exists(): + return False + + try: + tree = ET.parse(nfo_path) + root = tree.getroot() + + # Check if title already exists + existing_title = root.find('.//title') + if existing_title is not None and existing_title.text and existing_title.text.strip(): + return False # Title already exists + + # Add title element (insert near the top, after any existing plot element) + title_elem = ET.Element("title") + title_elem.text = title + + # Find the best position to insert title (after plot if it exists, otherwise at the beginning) + plot_elem = root.find('.//plot') + if plot_elem is not None: + # Insert after plot + plot_index = list(root).index(plot_elem) + root.insert(plot_index + 1, title_elem) + else: + # Insert at the beginning (after any existing title that might be empty) + if existing_title is not None: + title_index = list(root).index(existing_title) + root.remove(existing_title) + root.insert(title_index, title_elem) + else: + root.insert(0, title_elem) + + # Write the updated NFO + tree.write(nfo_path, encoding='utf-8', xml_declaration=True) + print(f"📝 Enhanced existing NFO with title: S{season_num:02d}E{episode_num:02d} - '{title}'") + return True + + except Exception as e: + print(f"⚠️ Error enhancing NFO with title: {e}") + return False + def _parse_nfo_with_tolerance(self, nfo_path: Path): """Parse NFO file with tolerance for URLs appended after XML""" try: diff --git a/nfoguard.py b/nfoguard.py index 6877e8f..50d9ab4 100644 --- a/nfoguard.py +++ b/nfoguard.py @@ -623,6 +623,21 @@ class TVProcessor: source = nfo_data["source"] aired = nfo_data.get("aired") + # Check if NFO is missing title and try to enhance it + if not nfo_data.get("has_title", False): + _log("INFO", f"NFO S{season_num:02d}E{episode_num:02d} missing title, attempting to extract from filename") + filename_title = self._extract_title_from_filename(season_path, season_num, episode_num) + if filename_title: + enhanced = self.nfo_manager.enhance_existing_episode_nfo_with_title( + season_path, season_num, episode_num, filename_title + ) + if enhanced: + _log("INFO", f"✅ Enhanced NFO S{season_num:02d}E{episode_num:02d} with title: '{filename_title}'") + else: + _log("WARNING", f"Failed to enhance NFO S{season_num:02d}E{episode_num:02d} with title") + else: + _log("WARNING", f"Could not extract title from filename for S{season_num:02d}E{episode_num:02d}") + # Update file mtime if enabled (NFO is already correct) if config.fix_dir_mtimes and dateadded: self.nfo_manager.set_file_mtime(episode_file, dateadded)