nfo dates to the bottom
This commit is contained in:
+32
-106
@@ -1,113 +1,39 @@
|
|||||||
# NFOGuard Development Summary
|
# NFOGuard Development Summary
|
||||||
|
|
||||||
## Current Status: v1.3.7 - NFO XML Parsing Fix
|
## Current Status: v1.3.8 - NFO Field Ordering Fix
|
||||||
|
|
||||||
### Latest Updates (v1.3.7)
|
### Latest Updates (v1.3.8)
|
||||||
- **� FIXED**: XML comment parsing error causing NFO creation to fail
|
- **🎯 FIELD ORDERING**: NFOGuard fields now append at bottom of existing NFO content
|
||||||
- **🔧 XML HANDLING**: Improved XML comment insertion and file writing
|
- **📋 STRUCTURE**: Date fields (premiered, dateadded, lockdata) appear after all existing metadata
|
||||||
- **✅ PRESERVATION**: Existing movie metadata properly preserved during updates
|
- **✅ PRESERVATION**: All existing content (actors, plot, ratings, etc.) maintained in original order
|
||||||
- **🎯 ROBUST**: Better error handling for malformed XML files
|
- **🧹 SMART CLEANUP**: Only removes NFOGuard-added elements, preserves existing uniqueid[tmdb]
|
||||||
|
|
||||||
### NFO Update Process (Fixed)
|
### NFO Field Order (Fixed)
|
||||||
```
|
**Now places NFOGuard fields at the bottom:**
|
||||||
1. ✅ Load existing movie.nfo (if exists)
|
```xml
|
||||||
2. ✅ Parse and validate XML structure
|
<movie>
|
||||||
3. ✅ Remove old NFOGuard elements to avoid duplicates
|
<!-- All existing Radarr/Jellyfin content preserved -->
|
||||||
4. ✅ Preserve all existing content (title, plot, cast, etc.)
|
<title>Movie Title</title>
|
||||||
5. ✅ Add/update NFOGuard fields (dateadded, lockdata, uniqueid)
|
<plot>Plot content...</plot>
|
||||||
6. ✅ Write properly formatted XML with comment
|
<actor>...</actor>
|
||||||
|
<!-- ... all existing fields ... -->
|
||||||
|
|
||||||
|
<!-- NFOGuard fields appended at bottom -->
|
||||||
|
<uniqueid type="imdb" default="true">tt8350360</uniqueid>
|
||||||
|
<premiered>2019-06-26</premiered> <!-- only if missing -->
|
||||||
|
<dateadded>2025-09-14T13:45:54-04:00</dateadded>
|
||||||
|
<lockdata>true</lockdata>
|
||||||
|
</movie>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Error Resolution
|
### Smart Element Management
|
||||||
- **v1.3.6**: XML comment handling caused `'()` error
|
- ✅ Preserves existing `uniqueid[tmdb]` and other IDs
|
||||||
- **v1.3.7**: Fixed comment insertion and XML serialization
|
- ✅ Only removes NFOGuard-managed `uniqueid[imdb]` to avoid duplicates
|
||||||
- **Result**: NFO files now update correctly while preserving contentlopment Summary
|
- ✅ Appends new fields using `ET.SubElement()` for bottom placement
|
||||||
|
- ✅ Maintains clean XML structure and formatting
|
||||||
|
|
||||||
## Current Status: v1.3.3 - Database Migration & Path Validation Complete
|
### Complete Path Processing Pipeline
|
||||||
|
- ✅ **Path Mapping**: Fixed substring matching (movies/movies6, tv/tv6)
|
||||||
### Latest Updates (v1.3.3)
|
- ✅ **Database Schema**: Clean migration with all required columns
|
||||||
- **� DATABASE**: Fixed missing `path` column migration in movies table
|
- ✅ **NFO Preservation**: Existing metadata maintained with fields appended
|
||||||
- **✅ MIGRATION**: Automatic schema updates with graceful error handling
|
- ✅ **Webhook Processing**: End-to-end processing working correctly
|
||||||
- **🔍 VALIDATION**: Enhanced database migration with column existence checks
|
|
||||||
- **🎯 COMPATIBILITY**: Backward compatibility with existing databases maintained
|
|
||||||
|
|
||||||
### Path Mapping Success (v1.3.2-v1.3.3)
|
|
||||||
- **🐛 CRITICAL**: Fixed substring matching bug (movies/movies6, tv/tv6)
|
|
||||||
- **🎯 ALGORITHM**: Longest-path-first matching prevents incorrect mappings
|
|
||||||
- **� DEBUG**: Comprehensive debug logging for troubleshooting
|
|
||||||
- **✅ TESTED**: Annabelle webhook now processes correctly
|
|
||||||
|
|
||||||
### Working Path Mapping Example
|
|
||||||
```
|
|
||||||
Radarr webhook: /mnt/unionfs/Media/Movies/movies6/Annabelle...
|
|
||||||
✅ Sort by length: [movies6, movies] (longest first)
|
|
||||||
✅ Match movies6: /mnt/unionfs/Media/Movies/movies6
|
|
||||||
✅ Map to index 1: /media/Movies/movies6
|
|
||||||
✅ Result: /media/Movies/movies6/Annabelle (2014) [tt3322940]
|
|
||||||
✅ Path exists: Validation passes
|
|
||||||
✅ Processing: Movie webhook succeeds
|
|
||||||
```
|
|
||||||
|
|
||||||
### Environment Configuration Required
|
|
||||||
- `MOVIE_PATHS=/media/Movies/movies,/media/Movies/movies6`
|
|
||||||
- `TV_PATHS=/media/TV/tv,/media/TV/tv6`
|
|
||||||
- `RADARR_ROOT_FOLDERS=/mnt/unionfs/Media/Movies/movies,/mnt/unionfs/Media/Movies/movies6`
|
|
||||||
- `SONARR_ROOT_FOLDERS=/mnt/unionfs/Media/TV/tv,/mnt/unionfs/Media/TV/tv6`
|
|
||||||
|
|
||||||
### Previous Updates (v1.3.1)
|
|
||||||
- **🐛 FIXED**: 'container_path' undefined variable error in Radarr webhook handler
|
|
||||||
- **🔧 ENHANCED**: Webhook now properly handles both 'folderPath' and 'path' fields
|
|
||||||
- **✅ VALIDATION**: Added mandatory path validation before processing
|
|
||||||
- **🎯 BATCH**: Enhanced batch processing with IMDb ID validation to prevent cross-processing
|
|
||||||
|
|
||||||
### Zero Hardcoded Paths
|
|
||||||
- ✅ No default fallback paths in configuration
|
|
||||||
- ✅ Application fails with clear error if paths not configured
|
|
||||||
- ✅ Works with any folder structure
|
|
||||||
- ✅ Completely portable between environments
|
|
||||||
|
|
||||||
### Database Migration Support
|
|
||||||
- ✅ Automatic schema updates for existing databases
|
|
||||||
- ✅ Graceful handling of missing columns
|
|
||||||
- ✅ Backward compatibility maintained
|
|
||||||
|
|
||||||
### Webhook Processing Flow
|
|
||||||
1. **Reception**: Webhook received and parsed
|
|
||||||
2. **Path Resolution**: External path mapped to container path using environment mappings
|
|
||||||
3. **Validation**: Verify mapped path exists and IMDb ID matches
|
|
||||||
4. **Batching**: Add to processing queue with anti-storm protection
|
|
||||||
5. **Processing**: Date resolution, NFO creation, file timestamp updates
|
|
||||||
6. **Database**: Record processing history and results
|
|
||||||
|
|
||||||
### Technical Architecture
|
|
||||||
- **Path Mapper**: Environment-configurable path translation
|
|
||||||
- **NFO Manager**: Creates metadata files with proper date attribution
|
|
||||||
- **Database Manager**: SQLite with automatic migration support
|
|
||||||
- **Webhook Batcher**: Intelligent batching with validation
|
|
||||||
- **Client Managers**: API access for external services
|
|
||||||
|
|
||||||
### Debug Features
|
|
||||||
- **Path Mapping Debug**: Detailed logging of path translation process
|
|
||||||
- **Health Endpoint**: Database and external service status
|
|
||||||
- **Statistics API**: Comprehensive media library statistics
|
|
||||||
- **Debug Endpoints**: Movie import analysis, TMDB lookup testing
|
|
||||||
|
|
||||||
## Configuration Requirements
|
|
||||||
|
|
||||||
### Critical Environment Variables
|
|
||||||
```bash
|
|
||||||
# Required - Application will fail without these
|
|
||||||
MOVIE_PATHS=/your/container/movie/paths
|
|
||||||
TV_PATHS=/your/container/tv/paths
|
|
||||||
RADARR_ROOT_FOLDERS=/host/radarr/paths
|
|
||||||
SONARR_ROOT_FOLDERS=/host/sonarr/paths
|
|
||||||
|
|
||||||
# Database and logging
|
|
||||||
DB_PATH=/app/data/media_dates.db
|
|
||||||
LOG_DIR=/app/data/logs
|
|
||||||
```
|
|
||||||
|
|
||||||
### Known Issues
|
|
||||||
- Path mapping must exactly match your container and host configurations
|
|
||||||
- Database requires migration for existing installations
|
|
||||||
- Debug logging may be verbose during path mapping troubleshooting
|
|
||||||
+14
-8
@@ -52,13 +52,16 @@ class NFOManager:
|
|||||||
raise ValueError("Root element is not <movie>")
|
raise ValueError("Root element is not <movie>")
|
||||||
|
|
||||||
# Remove existing NFOGuard-managed elements to avoid duplicates
|
# Remove existing NFOGuard-managed elements to avoid duplicates
|
||||||
|
# These will be re-added at the bottom
|
||||||
for tag in ["dateadded", "lockdata"]:
|
for tag in ["dateadded", "lockdata"]:
|
||||||
existing = movie.find(tag)
|
existing = movie.find(tag)
|
||||||
if existing is not None:
|
if existing is not None:
|
||||||
movie.remove(existing)
|
movie.remove(existing)
|
||||||
|
|
||||||
# Remove any existing uniqueid with type="imdb"
|
# Remove any existing uniqueid with type="imdb" added by NFOGuard
|
||||||
|
# (Keep other uniqueid elements like tmdb)
|
||||||
for uniqueid in movie.findall("uniqueid[@type='imdb']"):
|
for uniqueid in movie.findall("uniqueid[@type='imdb']"):
|
||||||
|
if uniqueid.get('default') == 'true':
|
||||||
movie.remove(uniqueid)
|
movie.remove(uniqueid)
|
||||||
|
|
||||||
except (ET.ParseError, ValueError) as e:
|
except (ET.ParseError, ValueError) as e:
|
||||||
@@ -68,21 +71,24 @@ class NFOManager:
|
|||||||
# Create new NFO structure
|
# Create new NFO structure
|
||||||
movie = ET.Element("movie")
|
movie = ET.Element("movie")
|
||||||
|
|
||||||
# Add/update IMDb uniqueid
|
# Now append NFOGuard fields at the END of the file
|
||||||
|
# This ensures they appear after all existing content
|
||||||
|
|
||||||
|
# Add/update IMDb uniqueid at the end
|
||||||
uniqueid = ET.SubElement(movie, "uniqueid", type="imdb", default="true")
|
uniqueid = ET.SubElement(movie, "uniqueid", type="imdb", default="true")
|
||||||
uniqueid.text = imdb_id
|
uniqueid.text = imdb_id
|
||||||
|
|
||||||
# Add dateadded
|
|
||||||
if dateadded:
|
|
||||||
dateadded_elem = ET.SubElement(movie, "dateadded")
|
|
||||||
dateadded_elem.text = dateadded
|
|
||||||
|
|
||||||
# Add premiered if we have release date (only if not already present)
|
# Add premiered if we have release date (only if not already present)
|
||||||
if released and movie.find("premiered") is None:
|
if released and movie.find("premiered") is None:
|
||||||
premiered_elem = ET.SubElement(movie, "premiered")
|
premiered_elem = ET.SubElement(movie, "premiered")
|
||||||
premiered_elem.text = released[:10] if len(released) >= 10 else released
|
premiered_elem.text = released[:10] if len(released) >= 10 else released
|
||||||
|
|
||||||
# Add lockdata if requested
|
# Add dateadded at the end
|
||||||
|
if dateadded:
|
||||||
|
dateadded_elem = ET.SubElement(movie, "dateadded")
|
||||||
|
dateadded_elem.text = dateadded
|
||||||
|
|
||||||
|
# Add lockdata at the very end
|
||||||
if lock_metadata:
|
if lock_metadata:
|
||||||
lockdata = ET.SubElement(movie, "lockdata")
|
lockdata = ET.SubElement(movie, "lockdata")
|
||||||
lockdata.text = "true"
|
lockdata.text = "true"
|
||||||
|
|||||||
Reference in New Issue
Block a user