Files
nfoguard/SUMMARY.md
T
sbcrumb 5c7300fc74 update: VERSION to v0.6.4 and add development workflow instructions
- Update VERSION file from 0.6.1 to 0.6.4 to match timezone logging release
- Add development workflow instructions to SUMMARY.md for future updates
- Document Claude Code's authority to write commits and push changes
- Establish version consistency requirements across VERSION, SUMMARY.md, and git tags
2025-09-14 09:51:11 -04:00

12 KiB

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:

<!-- 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 now show the same timezone format
  • Easier Troubleshooting: Timestamps match user's local environment
  • No More Confusion: No need to mentally convert between UTC and local time
  • Production Ready: Robust fallbacks ensure logging works in all environments

📋 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...

# 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...

📝 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.4
Status: Enhanced Production Ready