# 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 --- **Last Updated:** September 13, 2025 **Version:** v0.6.2-dev **Status:** Enhanced Production Ready