Files
nfoguard/README.md
T
2025-09-09 09:39:43 -04:00

277 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NFOGuard
*** Alpha in progress things are volatile use at your own risk ***
**NFOGuard** is a lightweight webhook service that locks in the *true import date* of your movies and TV episodes, ensuring that upgrades, renames, or reimports never bubble old media up as “new” in Emby, Jellyfin, or Plex.
It integrates with **Sonarr** and **Radarr**, listens for import/rename/upgrade events, and automatically manages `.nfo` files and filesystem timestamps to keep your library chronology consistent.
---
## ✨ Features
- **Import Date Locking**
Captures the original date a movie or episode was imported and preserves it across upgrades.
- **NFO Management**
Creates and updates `.nfo` files for movies and TV episodes with consistent `<dateadded>` fields.
Optionally adds `<lockdata>` to prevent metadata drift from scrapers.
- **Filesystem Time Fixing**
Updates file and directory modification times (`mtime`) to match the preserved import date.
- **Batching Support**
Groups multiple webhook events (e.g. whole-season downloads) to avoid thrashing.
- **Database Backing**
Uses SQLite to remember previously-seen imports, so dates persist across restarts.
- **Manual Scans**
Exposes endpoints to rescan and reconcile TV or movie libraries on demand.
---
## 🏗 How It Works
1. **Webhooks**
- Add NFOGuard as a webhook in Sonarr and Radarr.
- Supported event types: `Download`, `Upgrade`, `Rename`.
2. **Processing**
- Maps Sonarr/Radarr paths to container paths.
- Looks up IMDb IDs from folder names or payloads.
- Writes `.nfo` files and updates file/dir mtimes.
- Records everything in `media_dates.db`.
3. **Playback Apps**
- Emby/Jellyfin/Plex see consistent `dateadded` values.
- Upgrades dont bubble to the top of “Recently Added.”
---
## 🚀 Quick Start (Docker)
```bash
docker run -d \
--name=NFOGuard \
-p 8080:8080 \
-v /mnt/unionfs/Media:/media:rw \
-v /opt/NFOGuard/data:/app/data \
-e TV_PATHS="/media/TV/tv,/media/TV/tv6" \
-e MOVIE_PATHS="/media/Movies/movies,/media/Movies/movies6" \
ghcr.io/your-org/NFOGuard:latest
⚙️ Environment Variables
Variable Default Description
TV_PATHS /media/tv,/media/tv6 Comma-separated list of TV root paths
MOVIE_PATHS /media/movies,/media/movies6 Comma-separated list of Movie root paths
DB_PATH /app/data/media_dates.db Path to SQLite database
MANAGE_NFO true Write/update NFO files
FIX_DIR_MTIMES true Sync directory/file mtimes to import date
LOCK_METADATA true Add <lockdata> in NFOs
BATCH_DELAY 5.0 Delay before processing batched events
DEBUG false Enable verbose logging
🔌 API Endpoints
### Webhook Endpoints
```bash
# Radarr webhook (automatic processing)
POST /webhook/radarr
# Sonarr webhook (automatic processing)
POST /webhook/sonarr
```
### Manual Processing
```bash
# Manual scan all media
curl -X POST "http://localhost:8080/manual/scan?scan_type=both"
# Manual scan TV only
curl -X POST "http://localhost:8080/manual/scan?scan_type=tv"
# Manual scan movies only
curl -X POST "http://localhost:8080/manual/scan?scan_type=movies"
# Manual scan specific path
curl -X POST "http://localhost:8080/manual/scan?path=/media/movies"
# Bulk update all movies from Radarr database
curl -X POST "http://localhost:8080/bulk/update"
```
### Testing & Validation
```bash
# Test database connections
curl -X POST "http://localhost:8080/test/bulk-update"
# Test movie directory scanning
curl -X POST "http://localhost:8080/test/movie-scan"
# System health check
curl "http://localhost:8080/health"
# Database statistics
curl "http://localhost:8080/stats"
# Batch processing queue status
curl "http://localhost:8080/batch/status"
```
### Debugging & Analysis
```bash
# Debug specific movie import date detection
curl "http://localhost:8080/debug/movie/tt1674782"
# Show complete import history analysis
curl "http://localhost:8080/debug/movie/tt1674782/history"
# Show date priority logic and available sources
curl "http://localhost:8080/debug/movie/tt1674782/priority"
# Debug TMDB API lookup step by step
curl "http://localhost:8080/debug/tmdb/tt1674782"
```
### Response Examples
**Health Check**:
```json
{
"status": "healthy",
"version": "0.5.1",
"database_status": "healthy",
"radarr_database": {"status": "healthy", "movies": 1500}
}
```
**Movie Debug**:
```json
{
"detected_import_date": "2025-07-08T03:30:04+00:00",
"import_source": "radarr:history.import",
"movie_title": "Movie Name"
}
```
**Priority Logic Debug**:
```json
{
"movie_priority": "import_then_digital",
"priority_explanation": "1st: Radarr import history, 2nd: TMDB digital release, 3rd: file mtime",
"date_sources": {
"radarr_import": {"date": "2025-07-08T03:30:04+00:00", "source": "radarr:history.import"},
"digital_release": {"date": "2023-05-15T00:00:00+00:00", "source": "tmdb:digital"}
},
"selected_date": "2025-07-08T03:30:04+00:00"
}
```
## 🐛 Troubleshooting
### Manual Imports Show File Dates Instead of Digital Releases
**Problem**: Movies manually imported show recent file dates like `2025-08-29T12:14:28+00:00`
**Solution**:
1. Enable TMDB integration:
```bash
# Add to your .env file
TMDB_API_KEY=your_tmdb_api_key
PREFER_DIGITAL_OVER_FILE_DATES=true
```
2. Test the priority logic:
```bash
curl "http://localhost:8080/debug/movie/tt0115963/priority"
```
3. Should show digital date selection when reasonable
### "0 Movies Processed" During Manual Scan
**Problem**: Manual scan reports processing 0 movies
**Solution**:
1. Test directory scanning:
```bash
curl -X POST "http://localhost:8080/test/movie-scan"
```
2. Verify paths in your `.env` file match your actual structure:
```bash
# Your structure: /media/Movies/movies/
MOVIE_PATHS=/media/Movies/movies,/media/Movies/movies6
```
3. Ensure movie directories have IMDb tags:
```
Movie Name [imdb-tt1234567] (2023)/
```
### Database Connection Issues
**Problem**: "Radarr database connection failed"
**Solution**:
1. Test database connectivity:
```bash
curl -X POST "http://localhost:8080/test/bulk-update"
```
2. Verify database credentials in `.env`:
```bash
RADARR_DB_HOST=radarr-postgres
RADARR_DB_PASSWORD=your_actual_password
```
### Digital Dates Not Found
**Problem**: `"external_apis": {"tmdb_enabled": false}`
**Solution**:
1. Add TMDB API key to `.env`
2. Restart container: `docker-compose restart`
3. Verify: `curl "http://localhost:8080/debug/movie/tt0115963/priority"`
## 📖 Example Workflow
You add The Blacklist in Sonarr.
Sonarr downloads S01E01 → NFOGuard logs the import date in DB and .nfo.
Months later, a better-quality upgrade replaces the file.
NFOGuard updates the .nfo and mtime, but keeps the original import date.
Emby/Jellyfin/Plex see the file as unchanged in chronology.
Result: no more "old shows" showing up in "Recently Added."
🔍 Logging & Debugging
# Enable verbose logging
DEBUG=true
# Check container logs
docker logs sonarr-nfo-cache
# Debug specific movie import detection
curl http://localhost:8080/debug/movie/tt1674782
# Manual scan with verbose output
curl -X POST "http://localhost:8080/manual/scan?scan_type=movies"
# File logs (inside container)
/app/data/logs/nfoguard.log
⚙️ Environment Variables (v0.2.1+)
Variable Default Description
RADARR_ROOT_FOLDERS (required) What Radarr sees: /mnt/unionfs/Media/Movies/movies
SONARR_ROOT_FOLDERS (required) What Sonarr sees: /mnt/unionfs/Media/TV/tv
DOWNLOAD_PATH_INDICATORS (see example) Paths that indicate downloads vs existing files
MOVIE_PRIORITY import_then_digital Strategy: import_then_digital or digital_then_import
MOVIE_POLL_MODE always When to query APIs: always, if_missing, never
MOVIE_DATE_UPDATE_MODE backfill_only Update behavior: backfill_only or overwrite
📜 License
MIT License do what you want, just dont blame us if your timestamps go timey-wimey.