imdb updates
This commit is contained in:
+22
-3
@@ -1,6 +1,6 @@
|
|||||||
# NFOGuard Project Summary
|
# NFOGuard Project Summary
|
||||||
|
|
||||||
## 📋 Current Status: v0.6.0 (In Development)
|
## 📋 Current Status: v0.6.1 (Latest Improvements)
|
||||||
|
|
||||||
### 🎯 Project Goal
|
### 🎯 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.
|
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.
|
||||||
@@ -112,6 +112,25 @@ Preserve movie and TV import dates in Emby/Jellyfin/Plex by preventing upgraded
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### 🆕 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
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
**Last Updated:** September 9, 2025
|
**Last Updated:** September 9, 2025
|
||||||
**Version:** v0.6.0-dev
|
**Version:** v0.6.1-dev
|
||||||
**Status:** Active Development
|
**Status:** Enhanced Production Ready
|
||||||
@@ -249,6 +249,47 @@ class RadarrDbClient:
|
|||||||
_log("ERROR", f"Database query error for movie {movie_id}: {e}")
|
_log("ERROR", f"Database query error for movie {movie_id}: {e}")
|
||||||
|
|
||||||
return None, "radarr:db.no_date_found"
|
return None, "radarr:db.no_date_found"
|
||||||
|
|
||||||
|
def is_first_event_rename_based(self, movie_id: int) -> bool:
|
||||||
|
"""
|
||||||
|
Check if the first event in history is rename-based (not a true import)
|
||||||
|
|
||||||
|
This helps identify movies where:
|
||||||
|
- First event: movieFileRenamed (EventType = 7)
|
||||||
|
- Followed by: downloadFolderImported (EventType = 3) - this is an upgrade
|
||||||
|
|
||||||
|
In such cases, we should prefer release dates over the upgrade date
|
||||||
|
"""
|
||||||
|
query = """
|
||||||
|
SELECT h."EventType" as event_type
|
||||||
|
FROM "History" h
|
||||||
|
WHERE h."MovieId" = %s
|
||||||
|
ORDER BY h."Date" ASC
|
||||||
|
LIMIT 1
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.db_type == "sqlite":
|
||||||
|
query = query.replace("%s", "?")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with self._get_connection() as conn:
|
||||||
|
if self.db_type == "postgresql":
|
||||||
|
cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
||||||
|
else:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute(query, (movie_id,))
|
||||||
|
row = cursor.fetchone()
|
||||||
|
|
||||||
|
if row:
|
||||||
|
event_type = row['event_type'] if self.db_type == "postgresql" else row[0]
|
||||||
|
# EventType 7 = movieFileRenamed
|
||||||
|
return event_type == 7
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
_log("DEBUG", f"Error checking first event type for movie {movie_id}: {e}")
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def get_movie_file_date(self, movie_id: int) -> Optional[str]:
|
def get_movie_file_date(self, movie_id: int) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
@@ -305,11 +346,16 @@ class RadarrDbClient:
|
|||||||
Returns:
|
Returns:
|
||||||
(date_iso, source_description)
|
(date_iso, source_description)
|
||||||
"""
|
"""
|
||||||
# Try history first
|
# Try history first - always check for true import dates
|
||||||
date_iso, source = self.get_earliest_import_date(movie_id)
|
date_iso, source = self.get_earliest_import_date(movie_id)
|
||||||
if date_iso:
|
if date_iso:
|
||||||
return date_iso, source
|
return date_iso, source
|
||||||
|
|
||||||
|
# If no true import found, check if first event is rename-based (upgrade scenario)
|
||||||
|
if self.is_first_event_rename_based(movie_id):
|
||||||
|
_log("INFO", f"Movie {movie_id} has rename-first history with no true import - signaling to prefer release dates")
|
||||||
|
return None, "radarr:db.prefer_release_dates"
|
||||||
|
|
||||||
# Fallback to file date if requested
|
# Fallback to file date if requested
|
||||||
if fallback_to_file_date:
|
if fallback_to_file_date:
|
||||||
file_date = self.get_movie_file_date(movie_id)
|
file_date = self.get_movie_file_date(movie_id)
|
||||||
|
|||||||
+16
-4
@@ -18,8 +18,8 @@ def _log(level: str, msg: str):
|
|||||||
class NFOManager:
|
class NFOManager:
|
||||||
"""Handles creation and updating of NFO files for movies and TV episodes"""
|
"""Handles creation and updating of NFO files for movies and TV episodes"""
|
||||||
|
|
||||||
# Regex patterns
|
# Regex patterns - supports both [imdb-tt123] and [tt123] formats
|
||||||
IMDB_TAG_PATTERN = re.compile(r"\[imdb-(tt\d+)\]", re.IGNORECASE)
|
IMDB_TAG_PATTERN = re.compile(r"\[(?:imdb-)?(tt\d+)\]", re.IGNORECASE)
|
||||||
LONG_NFO_PATTERN = re.compile(r".*-S\d{2}E\d{2}-.*\.nfo$", re.IGNORECASE)
|
LONG_NFO_PATTERN = re.compile(r".*-S\d{2}E\d{2}-.*\.nfo$", re.IGNORECASE)
|
||||||
SHORT_NFO_PATTERN = re.compile(r"^S(\d{2})E(\d{2})\.nfo$", re.IGNORECASE)
|
SHORT_NFO_PATTERN = re.compile(r"^S(\d{2})E(\d{2})\.nfo$", re.IGNORECASE)
|
||||||
|
|
||||||
@@ -28,9 +28,21 @@ class NFOManager:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_imdb_from_path(path: Path) -> Optional[str]:
|
def parse_imdb_from_path(path: Path) -> Optional[str]:
|
||||||
"""Extract IMDb ID from directory or filename"""
|
"""Extract IMDb ID from directory or filename, with .nfo fallback"""
|
||||||
|
# First try path name
|
||||||
match = NFOManager.IMDB_TAG_PATTERN.search(path.name)
|
match = NFOManager.IMDB_TAG_PATTERN.search(path.name)
|
||||||
return match.group(1).lower() if match else None
|
if match:
|
||||||
|
return match.group(1).lower()
|
||||||
|
|
||||||
|
# Fallback: scan .nfo files in directory
|
||||||
|
if path.is_dir():
|
||||||
|
for nfo_file in path.glob("*.nfo"):
|
||||||
|
imdb_id = NFOManager.parse_imdb_from_nfo(nfo_file)
|
||||||
|
if imdb_id:
|
||||||
|
_log("DEBUG", f"Found IMDb ID {imdb_id} in {nfo_file.name}")
|
||||||
|
return imdb_id
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_imdb_from_nfo(nfo_path: Path) -> Optional[str]:
|
def parse_imdb_from_nfo(nfo_path: Path) -> Optional[str]:
|
||||||
|
|||||||
+5
-1
@@ -526,8 +526,12 @@ class MovieProcessor:
|
|||||||
if movie_id:
|
if movie_id:
|
||||||
import_date, import_source = self.radarr.get_movie_import_date(movie_id, fallback_to_file_date=config.allow_file_date_fallback)
|
import_date, import_source = self.radarr.get_movie_import_date(movie_id, fallback_to_file_date=config.allow_file_date_fallback)
|
||||||
|
|
||||||
|
# Check for special case: rename-first scenario (should prefer release dates)
|
||||||
|
if import_source == "radarr:db.prefer_release_dates":
|
||||||
|
_log("INFO", f"Movie {imdb_id} has rename-first history - skipping import, preferring release dates")
|
||||||
|
# Fall through to release date logic below
|
||||||
# Check if we got a real import date or just file date fallback
|
# Check if we got a real import date or just file date fallback
|
||||||
if import_date and import_source != "radarr:db.file.dateAdded":
|
elif import_date and import_source != "radarr:db.file.dateAdded":
|
||||||
return import_date, import_source, released
|
return import_date, import_source, released
|
||||||
|
|
||||||
# Get digital release date for comparison
|
# Get digital release date for comparison
|
||||||
|
|||||||
Reference in New Issue
Block a user