This commit is contained in:
2025-09-14 14:19:39 -04:00
parent a9c90d2939
commit f5ae8c7768
5 changed files with 90 additions and 37 deletions
+3
View File
@@ -111,6 +111,9 @@ TIMEOUT_SECONDS=45
# Enable verbose logging (true/false) # Enable verbose logging (true/false)
DEBUG=true DEBUG=true
# Enable path mapping debug output (true/false)
PATH_DEBUG=false
# =========================================== # ===========================================
# SERVER CONFIGURATION # SERVER CONFIGURATION
# =========================================== # ===========================================
+48 -34
View File
@@ -1,43 +1,57 @@
# NFOGuard Development Summary # NFOGuard Development Summary
## Current Status: v1.4.4 - TV Webhooks Working! 🎉 ## Current Status: v1.4.6 - Flexible Debug Controls!
### Latest Updates (v1.4.4) ### Latest Updates (v1.4.6)
- **✅ SUCCESS**: TV webhook path mapping now working correctly! - **🎛️ FLEXIBLE DEBUGGING**: Added `PATH_DEBUG` environment variable for path mapping debug control
- **🎯 FIXED**: Six Feet Under processing correctly (no more cross-processing) - **🧹 PRODUCTION READY**: Can now disable path debug while keeping general logging
- **📺 WORKING**: Episode batch processing and database storage functional - **⚙️ GRANULAR CONTROL**: Separate debug controls for different system components
- **🔧 MINOR**: Fixed remaining path typo in tv6 configuration - **✅ CONFIGURABLE**: Debug output now completely controllable via .env settings
### Working TV Webhook Flow ### New Debug Control System
```
✅ Webhook received: Six Feet Under
✅ Path mapping: /mnt/unionfs/Media/TV/tv → /media/TV/tv
✅ Series lookup: Found exact IMDb match (ID: 588)
✅ Episode processing: S01E03 processed successfully
✅ Database: Episode entry saved with timestamp
✅ Result: 1/1 episodes processed
```
### Final Configuration Fix
**Your .env should have:**
```bash ```bash
# All paths working correctly: # General application debugging (webhooks, processing, etc.)
MOVIE_PATHS=/media/Movies/movies,/media/Movies/movies6 DEBUG=true
TV_PATHS=/media/TV/tv,/media/TV/tv6
RADARR_ROOT_FOLDERS=/mnt/unionfs/Media/Movies/movies,/mnt/unionfs/Media/Movies/movies6 # Path mapping debugging (verbose path translation output)
SONARR_ROOT_FOLDERS=/mnt/unionfs/Media/TV/tv,/mnt/unionfs/Media/TV/tv6 PATH_DEBUG=false
``` ```
### Complete System Status ### Debug Output Examples
-**Movie Webhooks**: Working perfectly with path mapping
-**TV Webhooks**: Working perfectly with path mapping
-**NFO Management**: All media types preserve content and append fields
-**Database**: Clean schema with proper episode tracking
-**Path Mapping**: Both movies/movies6 and tv/tv6 handled correctly
### Minor Notes **With PATH_DEBUG=false (Production):**
- ⚠️ TVDB API warnings are normal (not all series support TVDB lookup) ```
- ✅ Episode processing completes successfully regardless INFO: Received Radarr webhook: Download
- ✅ IMDb-based series matching works reliably INFO: Batched movie webhook for movie:tt3322940
INFO: Processing movie: Annabelle (2014) [tt3322940]
INFO: Completed processing movie: Annabelle (2014) [tt3322940]
```
## 🎬📺 NFOGuard is now fully functional for both movies and TV shows! 🎉 **With PATH_DEBUG=true (Troubleshooting):**
```
PATH_DEBUG: PathMapper initialized with:
PATH_DEBUG: radarr_roots: ['/mnt/unionfs/Media/Movies/movies', '/mnt/unionfs/Media/Movies/movies6']
PATH_DEBUG: radarr_path_to_container_path input: /mnt/unionfs/Media/Movies/movies6/Annabelle...
PATH_DEBUG: Checking radarr_root[1]: /mnt/unionfs/Media/Movies/movies6
PATH_DEBUG: Match found! Index 1
PATH_DEBUG: Mapped to: /media/Movies/movies6/Annabelle (2014) [tt3322940]
```
### Recommended Production Settings
```bash
# Optimal for production monitoring:
DEBUG=true # Keep application logging for monitoring
PATH_DEBUG=false # Disable verbose path mapping output
# Minimal logging for high-performance:
DEBUG=false # Disable all debug output
PATH_DEBUG=false # Disable path mapping debug
```
### Debug Scenarios
- **✅ Production**: `DEBUG=true, PATH_DEBUG=false` - Monitor without noise
- **🔧 Troubleshooting**: `DEBUG=true, PATH_DEBUG=true` - Full diagnostics
- **🚀 High Performance**: `DEBUG=false, PATH_DEBUG=false` - Minimal logging
- **🎯 Path Issues**: `DEBUG=false, PATH_DEBUG=true` - Focus on path mapping only
## 🎛️ NFOGuard now offers complete control over debug output levels! 🎛️
+1 -1
View File
@@ -1 +1 @@
1.4.5 1.4.7
+36
View File
@@ -17,41 +17,77 @@ class PathMapper:
self.movie_paths = [path.strip() for path in config.movie_paths.split(',') if path.strip()] self.movie_paths = [path.strip() for path in config.movie_paths.split(',') if path.strip()]
self.tv_paths = [path.strip() for path in config.tv_paths.split(',') if path.strip()] self.tv_paths = [path.strip() for path in config.tv_paths.split(',') if path.strip()]
# Check if path debugging is enabled
self.path_debug = os.getenv('PATH_DEBUG', 'false').lower() == 'true'
if self.path_debug:
print(f"PATH_DEBUG: PathMapper initialized with:")
print(f"PATH_DEBUG: radarr_roots: {self.radarr_roots}")
print(f"PATH_DEBUG: sonarr_roots: {self.sonarr_roots}")
print(f"PATH_DEBUG: movie_paths: {self.movie_paths}")
print(f"PATH_DEBUG: tv_paths: {self.tv_paths}")
def sonarr_path_to_container_path(self, sonarr_path: str) -> str: def sonarr_path_to_container_path(self, sonarr_path: str) -> str:
"""Convert Sonarr path to container path using environment mappings""" """Convert Sonarr path to container path using environment mappings"""
if self.path_debug:
print(f"PATH_DEBUG: sonarr_path_to_container_path input: {sonarr_path}")
print(f"PATH_DEBUG: sonarr_roots: {self.sonarr_roots}")
print(f"PATH_DEBUG: tv_paths: {self.tv_paths}")
# Sort roots by length (longest first) to avoid substring matching issues # Sort roots by length (longest first) to avoid substring matching issues
indexed_roots = [(i, root) for i, root in enumerate(self.sonarr_roots)] indexed_roots = [(i, root) for i, root in enumerate(self.sonarr_roots)]
indexed_roots.sort(key=lambda x: len(x[1]), reverse=True) indexed_roots.sort(key=lambda x: len(x[1]), reverse=True)
# Try to match against configured Sonarr root folders (longest first) # Try to match against configured Sonarr root folders (longest first)
for original_index, sonarr_root in indexed_roots: for original_index, sonarr_root in indexed_roots:
if self.path_debug:
print(f"PATH_DEBUG: Checking sonarr_root[{original_index}]: {sonarr_root}")
if sonarr_path.startswith(sonarr_root + '/') or sonarr_path == sonarr_root: if sonarr_path.startswith(sonarr_root + '/') or sonarr_path == sonarr_root:
if self.path_debug:
print(f"PATH_DEBUG: Match found! Index {original_index}")
# Map to corresponding TV path # Map to corresponding TV path
if original_index < len(self.tv_paths): if original_index < len(self.tv_paths):
container_root = self.tv_paths[original_index] container_root = self.tv_paths[original_index]
relative_path = sonarr_path[len(sonarr_root):].lstrip('/') relative_path = sonarr_path[len(sonarr_root):].lstrip('/')
result = str(Path(container_root) / relative_path) if relative_path else container_root result = str(Path(container_root) / relative_path) if relative_path else container_root
if self.path_debug:
print(f"PATH_DEBUG: Mapped to: {result}")
return result return result
if self.path_debug:
print(f"PATH_DEBUG: No match found, returning original: {sonarr_path}")
# No fallback - if path mapping fails, return original and let validation catch it # No fallback - if path mapping fails, return original and let validation catch it
return sonarr_path return sonarr_path
def radarr_path_to_container_path(self, radarr_path: str) -> str: def radarr_path_to_container_path(self, radarr_path: str) -> str:
"""Convert Radarr path to container path using environment mappings""" """Convert Radarr path to container path using environment mappings"""
if self.path_debug:
print(f"PATH_DEBUG: radarr_path_to_container_path input: {radarr_path}")
print(f"PATH_DEBUG: radarr_roots: {self.radarr_roots}")
print(f"PATH_DEBUG: movie_paths: {self.movie_paths}")
# Sort roots by length (longest first) to avoid substring matching issues # Sort roots by length (longest first) to avoid substring matching issues
indexed_roots = [(i, root) for i, root in enumerate(self.radarr_roots)] indexed_roots = [(i, root) for i, root in enumerate(self.radarr_roots)]
indexed_roots.sort(key=lambda x: len(x[1]), reverse=True) indexed_roots.sort(key=lambda x: len(x[1]), reverse=True)
# Try to match against configured Radarr root folders (longest first) # Try to match against configured Radarr root folders (longest first)
for original_index, radarr_root in indexed_roots: for original_index, radarr_root in indexed_roots:
if self.path_debug:
print(f"PATH_DEBUG: Checking radarr_root[{original_index}]: {radarr_root}")
if radarr_path.startswith(radarr_root + '/') or radarr_path == radarr_root: if radarr_path.startswith(radarr_root + '/') or radarr_path == radarr_root:
if self.path_debug:
print(f"PATH_DEBUG: Match found! Index {original_index}")
# Map to corresponding movie path # Map to corresponding movie path
if original_index < len(self.movie_paths): if original_index < len(self.movie_paths):
container_root = self.movie_paths[original_index] container_root = self.movie_paths[original_index]
relative_path = radarr_path[len(radarr_root):].lstrip('/') relative_path = radarr_path[len(radarr_root):].lstrip('/')
result = str(Path(container_root) / relative_path) if relative_path else container_root result = str(Path(container_root) / relative_path) if relative_path else container_root
if self.path_debug:
print(f"PATH_DEBUG: Mapped to: {result}")
return result return result
if self.path_debug:
print(f"PATH_DEBUG: No match found, returning original: {radarr_path}")
# No fallback - if path mapping fails, return original and let validation catch it # No fallback - if path mapping fails, return original and let validation catch it
return radarr_path return radarr_path
+2 -2
View File
@@ -1392,7 +1392,7 @@ start_time = datetime.now(timezone.utc)
# Initialize components # Initialize components
db = NFOGuardDatabase(config.db_path) db = NFOGuardDatabase(config.db_path)
nfo_manager = NFOManager(config.manager_brand) nfo_manager = NFOManager(config.manager_brand)
path_mapper = PathMapper() path_mapper = PathMapper(config) # FIXED: Pass config to PathMapper
tv_processor = TVProcessor(db, nfo_manager, path_mapper) tv_processor = TVProcessor(db, nfo_manager, path_mapper)
movie_processor = MovieProcessor(db, nfo_manager, path_mapper) movie_processor = MovieProcessor(db, nfo_manager, path_mapper)
batcher = WebhookBatcher() batcher = WebhookBatcher()
@@ -1683,7 +1683,7 @@ async def debug_movie_import_date(imdb_id: str):
"movie_digital_release": movie_obj.get("digitalRelease"), "movie_digital_release": movie_obj.get("digitalRelease"),
"movie_in_cinemas": movie_obj.get("inCinemas"), "movie_in_cinemas": movie_obj.get("inCinemas"),
"movie_physical_release": movie_obj.get("physicalRelease"), "movie_physical_release": movie_obj.get("physicalRelease"),
"movie_folder_path": movie_obj.get("folderPath") "movie_folder_path": movie_obj.get("folderPath")
} }
} }
else: else: