7af7b1c43e
- Fix NFO dateadded timestamps to use local timezone instead of UTC - Convert Radarr/Sonarr import dates from UTC to local timezone for NFO files - Update webhook episode processing to use local time for new downloads - Convert file modification time fallbacks to local timezone - Preserve historical dates (aired, premiered) in original UTC format - Replace all placeholder logging functions with centralized timezone-aware logging - Add convert_utc_to_local() utility function for timestamp conversion - Now all logs AND NFO files show consistent local timezone formatting Users with TZ=America/New_York will now see: - Logs: [2025-09-14T09:37:00-04:00] - NFO files: <dateadded>2025-09-14T09:37:00-04:00</dateadded>
274 lines
13 KiB
Markdown
274 lines
13 KiB
Markdown
# NFOGuard Project Summary
|
|
|
|
## 📋 Current Status: v0.6.1 (Latest Improvements)
|
|
|
|
### 🎯 Project Goal
|
|
Preserve movie and TV import dates in Emby/Jellyfin/Plex by preventing upgraded files from appearing as "recently added". NFOGuard listens to Radarr/Sonarr webhooks and manages `.nfo` files and file timestamps to maintain chronological consistency.
|
|
|
|
### 🚀 Major Achievements
|
|
|
|
**Database-Only Architecture (v0.5.0+)**
|
|
- **Performance**: 10x faster than API-based approach
|
|
- **Reliability**: Direct PostgreSQL database queries eliminate API limitations
|
|
- **Scalability**: Handles 1500+ movies without pagination issues
|
|
|
|
**🎯 Configurable Release Date Priority System (v0.6.0)**
|
|
- **Three-Tier Priority System**: Digital → Physical → Theatrical (fully configurable)
|
|
- **Smart Fallbacks**: "The Craft (1996)" gets 1996 theatrical, "Top Gun Maverick (2022)" gets digital
|
|
- **Per-Movie Intelligence**: Automatically adapts to movie era and available release data
|
|
- **Source Tracking**: NFO files annotated with chosen date source (tmdb:theatrical, tmdb:digital, etc.)
|
|
- **Quality Control**: Prevents unrealistic dates through smart comparison logic
|
|
|
|
### 🏗 Current Architecture
|
|
|
|
**Core Components:**
|
|
- `nfoguard.py` - Main FastAPI webhook server
|
|
- `clients/radarr_db_client.py` - Direct database access client
|
|
- `clients/external_clients.py` - TMDB/OMDb integration
|
|
- `core/nfo_manager.py` - NFO file creation and management
|
|
- `bulk_update_movies.py` - Mass movie processing
|
|
|
|
**Data Flow:**
|
|
1. Radarr webhook → NFOGuard processes → Database queries for import dates
|
|
2. Smart fallback logic for manual imports → TMDB digital release dates
|
|
3. NFO file creation with preserved dates → File timestamp updates
|
|
|
|
### 🔧 Configuration Management
|
|
|
|
**Environment-Based Setup:**
|
|
- `.env.template` - Generic configuration template
|
|
- `docker-compose.yml` - Production deployment configuration
|
|
- Supports multiple media paths and database types
|
|
|
|
**Key Settings:**
|
|
- `MOVIE_PRIORITY=import_then_digital` - Prioritizes real import history
|
|
- `PREFER_RELEASE_DATES_OVER_FILE_DATES=true` - Smart fallback for manual imports
|
|
- `RELEASE_DATE_PRIORITY=digital,physical,theatrical` - Configurable fallback order
|
|
- Database connection parameters for PostgreSQL/SQLite
|
|
|
|
### 📊 Performance Metrics
|
|
|
|
**Before (API-based):**
|
|
- Took 30+ seconds for complex movies
|
|
- Failed on movies with extensive history
|
|
- API pagination caused timeouts
|
|
|
|
**After (Database-only):**
|
|
- Sub-second response times
|
|
- Handles any history size
|
|
- Reliable July 2025 date detection maintained
|
|
|
|
### 🧪 Testing Infrastructure
|
|
|
|
**Comprehensive Test Suite:**
|
|
- `test_bulk_update.py` - Database connection validation
|
|
- `test_movie_scan.py` - Directory scanning logic testing
|
|
- `test_end_to_end.py` - Complete workflow validation
|
|
|
|
**Debug Endpoints:**
|
|
- `/debug/movie/{imdb_id}` - Import date analysis
|
|
- `/debug/movie/{imdb_id}/priority` - Date selection logic
|
|
- `/debug/movie/{imdb_id}/history` - Complete import history
|
|
|
|
### 🎉 Success Metrics
|
|
|
|
**Production Results:**
|
|
- ✅ Correct July 2025 dates preserved for legitimate imports
|
|
- ✅ Manual imports now use **intelligent release date selection**:
|
|
- "The Craft (1996)" → 1996 theatrical date (not 2025 file date)
|
|
- "Top Gun Maverick (2022)" → digital release date per user preference
|
|
- ✅ Zero API timeout issues with database-only approach
|
|
- ✅ Complete webhook-based operation (no manual CLI required)
|
|
- ✅ NFO source annotations for full transparency
|
|
|
|
### 🚧 Current Development Focus
|
|
|
|
**Completed (v0.6.0):**
|
|
- ✅ **Revolutionary Priority System**: Configurable digital/physical/theatrical fallbacks
|
|
- ✅ **Per-Movie Intelligence**: Adapts to movie era and available release data
|
|
- ✅ **Complete Documentation**: README, testing guides, troubleshooting
|
|
- ✅ **Source Transparency**: NFO annotations show exactly which source was used
|
|
|
|
**Next Priorities:**
|
|
- TV series processing optimization
|
|
- Additional external API integrations (OMDb, Jellyseerr)
|
|
- Advanced configuration options
|
|
- Community feedback integration
|
|
|
|
### 📈 Project Maturity
|
|
|
|
**Ready for Production:**
|
|
- ✅ Stable database architecture
|
|
- ✅ Comprehensive error handling
|
|
- ✅ Docker deployment ready
|
|
- ✅ Extensive testing coverage
|
|
- ✅ Complete documentation
|
|
|
|
**Community Ready:**
|
|
- ✅ Environment-based configuration
|
|
- ✅ Portable Docker setup
|
|
- ✅ Detailed API documentation
|
|
- ✅ Troubleshooting guides
|
|
|
|
---
|
|
|
|
### 🆕 v0.6.1 Recent Improvements (September 2025)
|
|
|
|
**🔧 Enhanced Radarr History Detection:**
|
|
- **Smart Upgrade Detection**: Detects movies where first event is `movieFileRenamed` (upgrade scenarios)
|
|
- **Improved Logic**: For movies like The Matrix (1999), prefer digital release dates over recent upgrade dates
|
|
- **True Import Preservation**: Still honors actual import dates when they exist - only enhances edge cases
|
|
|
|
**🎯 Improved IMDb ID Extraction:**
|
|
- **Flexible Regex**: Now supports both `[imdb-tt123]` and `[tt123]` formats
|
|
- **NFO Fallback**: Scans `.nfo` files when path extraction fails (handles Radarr auto-generated files)
|
|
- **Broader Compatibility**: Works with various folder naming conventions
|
|
|
|
**🧠 Enhanced Priority Logic:**
|
|
- Movies with rename→upgrade history now get better chronological dates
|
|
- True import dates always take precedence (no regression)
|
|
- Smart fallbacks only engage when appropriate
|
|
|
|
---
|
|
|
|
### 🆕 v0.6.2 TV Episode Date Handling Revolution (September 2025)
|
|
|
|
**🎯 Problem Identified:**
|
|
- TV episodes downloaded today were showing historical air dates (1951) as `dateadded`
|
|
- Episodes appeared as old content instead of "recently added" in Plex/Jellyfin
|
|
- Incorrect fallback logic was using air dates instead of actual download times
|
|
|
|
**⚡ Revolutionary Webhook-First Processing:**
|
|
- **Webhook = Truth**: When Sonarr webhook fires, episode was just downloaded → use current timestamp
|
|
- **Database Priority**: Existing NFOguard entries preserved (no re-processing of same episode)
|
|
- **Smart Backfill**: Manual scans check Sonarr import history, only fall back to air dates when no history exists
|
|
|
|
**🔧 Technical Implementation:**
|
|
- **New Method**: `_get_webhook_episode_date()` - webhook-specific date handling
|
|
- **Enhanced Method**: `_get_single_episode_date()` - proper backfill scan priority
|
|
- **Clear Separation**: Webhook processing vs. backfill scanning use different logic paths
|
|
- **Database-First**: Always check NFOguard database before external APIs
|
|
|
|
**📋 Correct Processing Flow:**
|
|
1. **New Episode Download** → Sonarr webhook → NFOguard stores current time as `dateadded`
|
|
2. **Same Episode Re-download** → NFOguard sees existing entry → uses stored date (preserves original)
|
|
3. **Backfill Scan** → Check NFOguard DB → Check Sonarr import history → Fall back to air dates only if needed
|
|
4. **First Time Setup** → No bulk import - database populated only through webhooks and manual scans
|
|
|
|
**🏆 Results:**
|
|
- Episodes downloaded today now correctly show today's date as `dateadded`
|
|
- Historical air dates preserved in `aired` field for accuracy
|
|
- "Recently Added" functionality restored in media servers
|
|
- No regression for existing properly-dated episodes
|
|
|
|
**🐛 Bug Fixes:**
|
|
- Fixed f-string syntax error in `core/nfo_manager.py:324`
|
|
- Resolved backslash escaping issue preventing startup
|
|
|
|
---
|
|
|
|
### 🆕 v0.6.3 NFO Management & Date Accuracy Improvements (September 2025)
|
|
|
|
**💾 Smart NFO File Management:**
|
|
- **Problem**: NFOguard was rewriting NFO files for every episode on every scan, even untouched ones
|
|
- **Solution**: Intelligent content comparison - only updates NFOs when content actually changes
|
|
- **Performance**: Dramatically reduces unnecessary file system writes and processing time
|
|
- **Both Media Types**: Applied to both TV episodes and movies for comprehensive efficiency
|
|
|
|
**🗓️ Correct Date Field Mapping:**
|
|
- **Problem**: Episode NFOs showing import dates (2025) for historical fields `<aired>` and `<premiered>`
|
|
- **Root Cause**: Logic incorrectly used `dateadded` for all date fields instead of proper separation
|
|
- **Fix**: Clear separation of date meanings:
|
|
- `<aired>`: Historical air date (e.g., 1951-10-15 for I Love Lucy)
|
|
- `<premiered>`: Historical premiere date (same as aired)
|
|
- `<dateadded>`: Actual download/import date (e.g., 2025-09-13T21:39:28+00:00)
|
|
|
|
**🎯 Technical Implementation:**
|
|
- **New Method**: `_nfo_content_matches()` - smart content comparison ignoring timestamps
|
|
- **Enhanced Logic**: Episodes now correctly separate historical vs import dates
|
|
- **Skip Logic**: Files marked "already up-to-date" when no meaningful changes detected
|
|
- **Logging**: Clear debug output showing when files are skipped vs updated
|
|
|
|
**🏆 User Experience Improvements:**
|
|
- **Correct Metadata**: Shows historically accurate air dates in media servers
|
|
- **Recently Added**: Still works properly using `dateadded` field
|
|
- **Performance**: Faster scans with fewer unnecessary file writes
|
|
- **Accuracy**: No more confusion between when show aired vs when you downloaded it
|
|
|
|
**📋 Example Before/After:**
|
|
```xml
|
|
<!-- Before (Wrong) -->
|
|
<aired>2025-09-13</aired> <!-- Import date in wrong field -->
|
|
<dateadded>2025-09-13T21:39:28+00:00</dateadded>
|
|
<premiered>2025-09-13</premiered> <!-- Import date in wrong field -->
|
|
|
|
<!-- After (Correct) -->
|
|
<aired>1951-10-15</aired> <!-- Historical air date ✅ -->
|
|
<dateadded>2025-09-13T21:39:28+00:00</dateadded> <!-- When downloaded ✅ -->
|
|
<premiered>1951-10-15</premiered> <!-- Historical premiere ✅ -->
|
|
```
|
|
|
|
---
|
|
|
|
### 🆕 v0.6.4 Timezone-Aware Logging Fix (September 2025)
|
|
|
|
**🕰️ Universal Timezone Consistency:**
|
|
- **Problem**: Mixed timestamp formats in logs made troubleshooting difficult
|
|
- Some logs: `[2025-09-14T09:37:00.338045]` (local time without timezone info)
|
|
- Other logs: `[2025-09-14T13:37:00+00:00]` (UTC with timezone info)
|
|
- Docker `TZ=America/New_York` environment variable not respected by all logging systems
|
|
|
|
**⚡ Comprehensive Logging Fix:**
|
|
- **Unified Timezone Handling**: All logging systems now respect the `TZ` environment variable
|
|
- **Custom TimezoneAwareFormatter**: Python's standard logging now uses container timezone
|
|
- **Enhanced _log Function**: Custom logging function updated with robust timezone support
|
|
- **Centralized Logging**: Replaced placeholder logging functions with consistent implementation
|
|
|
|
**🔧 Technical Implementation:**
|
|
- **New Class**: `TimezoneAwareFormatter` for Python's standard logging module
|
|
- **Enhanced Function**: `_get_local_timezone()` with fallbacks for different Python versions
|
|
- **Cross-Compatibility**: Supports both `zoneinfo` (Python 3.9+) and `pytz` (older versions)
|
|
- **Consistent Import**: All client modules now use centralized `core.logging._log`
|
|
|
|
**🏆 User Experience Improvements:**
|
|
- **Consistent Timestamps**: All logs AND NFO files now show the same timezone format
|
|
- **Easier Troubleshooting**: Timestamps match user's local environment everywhere
|
|
- **No More Confusion**: No need to mentally convert between UTC and local time
|
|
- **Production Ready**: Robust fallbacks ensure timezone handling works in all environments
|
|
- **NFO File Accuracy**: Movie and TV episode `<dateadded>` fields now respect container timezone
|
|
|
|
**📋 Before/After Example:**
|
|
```
|
|
# Before (Inconsistent)
|
|
sonarr-nfo-cache | [2025-09-14T09:37:00.338045] DEBUG: Mapped Radarr path...
|
|
sonarr-nfo-cache | [2025-09-14T13:37:00+00:00] INFO: Batched movie webhook...
|
|
<dateadded>2025-09-14T13:49:00+00:00</dateadded> <!-- UTC in NFO files -->
|
|
|
|
# After (Consistent)
|
|
sonarr-nfo-cache | [2025-09-14T09:37:00-04:00] DEBUG: Mapped Radarr path...
|
|
sonarr-nfo-cache | [2025-09-14T09:37:00-04:00] INFO: Batched movie webhook...
|
|
<dateadded>2025-09-14T09:49:00-04:00</dateadded> <!-- Local timezone in NFO files -->
|
|
```
|
|
|
|
**🔧 Additional NFO Timezone Fixes:**
|
|
- **Movie Import Dates**: Convert UTC timestamps from Radarr to local timezone in NFO files
|
|
- **TV Episode Downloads**: Webhook-triggered episodes now use local time for `<dateadded>`
|
|
- **File Modification Times**: Fallback file mtime dates now respect container timezone
|
|
- **Historical Date Preservation**: `<aired>` and `<premiered>` dates remain historically accurate
|
|
- **Centralized Logging**: All modules now use consistent timezone-aware logging system
|
|
|
|
---
|
|
|
|
## 📝 Development Workflow Instructions
|
|
|
|
**For Future Updates:**
|
|
- **VERSION File**: Always update the `VERSION` file to match the release version being documented
|
|
- **Commit Authority**: Claude Code is authorized to write commit messages and push changes directly
|
|
- **SUMMARY Updates**: This file serves as the primary project documentation and should be updated with each significant change
|
|
- **Version Consistency**: Ensure VERSION file, SUMMARY.md version, and git tags all align
|
|
|
|
---
|
|
|
|
**Last Updated:** September 14, 2025
|
|
**Version:** v0.6.5
|
|
**Status:** Enhanced Production Ready |