fix: Store actual movie release dates in database
Local Docker Build (Dev) / build-dev (push) Successful in 4s
Local Docker Build (Dev) / build-dev (push) Successful in 4s
- Movie processor now stores release dates in 'released' field - Added backfill endpoint for existing movies missing release dates - Fixes empty "Movie Released" column in web interface
This commit is contained in:
@@ -1233,6 +1233,101 @@ async def cleanup_orphaned_series(dependencies: dict):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def backfill_movie_release_dates(dependencies: dict):
|
||||||
|
"""Backfill missing release dates for existing movies"""
|
||||||
|
db = dependencies["db"]
|
||||||
|
movie_processor = dependencies["movie_processor"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Get all movies with missing release dates
|
||||||
|
with db.get_connection() as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Find movies where released is NULL but source suggests we found a release date
|
||||||
|
query = """
|
||||||
|
SELECT imdb_id, path, dateadded, source
|
||||||
|
FROM movies
|
||||||
|
WHERE released IS NULL
|
||||||
|
AND (source LIKE '%tmdb%' OR source LIKE '%omdb%' OR source LIKE '%premiered%')
|
||||||
|
ORDER BY last_updated DESC
|
||||||
|
"""
|
||||||
|
cursor.execute(query)
|
||||||
|
movies_to_backfill = cursor.fetchall()
|
||||||
|
|
||||||
|
if not movies_to_backfill:
|
||||||
|
return {
|
||||||
|
"success": True,
|
||||||
|
"message": "No movies found that need release date backfill",
|
||||||
|
"movies_processed": 0,
|
||||||
|
"movies_updated": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
processed_count = 0
|
||||||
|
updated_count = 0
|
||||||
|
|
||||||
|
print(f"🔄 BACKFILL STARTED: Found {len(movies_to_backfill)} movies needing release date backfill")
|
||||||
|
|
||||||
|
for movie in movies_to_backfill:
|
||||||
|
imdb_id = movie['imdb_id']
|
||||||
|
source = movie['source']
|
||||||
|
|
||||||
|
try:
|
||||||
|
print(f"🔍 Processing {imdb_id} (source: {source})")
|
||||||
|
|
||||||
|
# Try to get release date based on the source
|
||||||
|
release_date = None
|
||||||
|
|
||||||
|
if 'tmdb' in source or 'omdb' in source:
|
||||||
|
# Re-fetch digital release date
|
||||||
|
digital_date, _ = movie_processor._get_digital_release_date(imdb_id)
|
||||||
|
if digital_date:
|
||||||
|
release_date = digital_date
|
||||||
|
print(f"✅ Found release date for {imdb_id}: {release_date}")
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Could not re-fetch release date for {imdb_id}")
|
||||||
|
|
||||||
|
elif 'premiered' in source:
|
||||||
|
# Use the dateadded as the release date for premiered sources
|
||||||
|
release_date = movie['dateadded']
|
||||||
|
if hasattr(release_date, 'isoformat'):
|
||||||
|
release_date = release_date.isoformat()
|
||||||
|
print(f"✅ Using premiered date for {imdb_id}: {release_date}")
|
||||||
|
|
||||||
|
# Update the database if we found a release date
|
||||||
|
if release_date:
|
||||||
|
db.upsert_movie_dates(imdb_id, release_date, movie['dateadded'], source, True)
|
||||||
|
updated_count += 1
|
||||||
|
print(f"📝 Updated release date for {imdb_id}")
|
||||||
|
|
||||||
|
processed_count += 1
|
||||||
|
|
||||||
|
# Small delay to avoid overwhelming APIs
|
||||||
|
import time
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error processing {imdb_id}: {e}")
|
||||||
|
processed_count += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"✅ BACKFILL COMPLETED: Processed {processed_count} movies, updated {updated_count} with release dates")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"success": True,
|
||||||
|
"message": f"Backfill completed: processed {processed_count} movies, updated {updated_count} with release dates",
|
||||||
|
"movies_processed": processed_count,
|
||||||
|
"movies_updated": updated_count,
|
||||||
|
"movies_found": len(movies_to_backfill)
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
"success": False,
|
||||||
|
"error": str(e),
|
||||||
|
"message": "Failed to backfill movie release dates"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
# Route Registration
|
# Route Registration
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
@@ -1307,6 +1402,10 @@ def register_routes(app, dependencies: dict):
|
|||||||
async def _cleanup_orphaned_series():
|
async def _cleanup_orphaned_series():
|
||||||
return await cleanup_orphaned_series(dependencies)
|
return await cleanup_orphaned_series(dependencies)
|
||||||
|
|
||||||
|
@app.post("/database/backfill/movie-release-dates")
|
||||||
|
async def _backfill_movie_release_dates():
|
||||||
|
return await backfill_movie_release_dates(dependencies)
|
||||||
|
|
||||||
@app.post("/manual/scan")
|
@app.post("/manual/scan")
|
||||||
async def _manual_scan(background_tasks: BackgroundTasks, path: Optional[str] = None, scan_type: str = "both", scan_mode: str = "smart"):
|
async def _manual_scan(background_tasks: BackgroundTasks, path: Optional[str] = None, scan_type: str = "both", scan_mode: str = "smart"):
|
||||||
return await manual_scan(background_tasks, path, scan_type, scan_mode, dependencies)
|
return await manual_scan(background_tasks, path, scan_type, scan_mode, dependencies)
|
||||||
|
|||||||
@@ -530,7 +530,8 @@ class MovieProcessor:
|
|||||||
# Compare dates - prefer release date if it's reasonable
|
# Compare dates - prefer release date if it's reasonable
|
||||||
if self._should_prefer_release_over_file_date(digital_date, digital_source, released, imdb_id):
|
if self._should_prefer_release_over_file_date(digital_date, digital_source, released, imdb_id):
|
||||||
_log("INFO", f"✅ Movie {imdb_id}: Preferring digital release date {digital_date} over file date")
|
_log("INFO", f"✅ Movie {imdb_id}: Preferring digital release date {digital_date} over file date")
|
||||||
return digital_date, digital_source, released
|
# When using digital release date, store it as both dateadded and released
|
||||||
|
return digital_date, digital_source, digital_date
|
||||||
else:
|
else:
|
||||||
# Convert file date to local timezone for NFO files
|
# Convert file date to local timezone for NFO files
|
||||||
local_file_date = convert_utc_to_local(import_date)
|
local_file_date = convert_utc_to_local(import_date)
|
||||||
@@ -545,7 +546,8 @@ class MovieProcessor:
|
|||||||
return local_import_date, import_source, released
|
return local_import_date, import_source, released
|
||||||
elif digital_date:
|
elif digital_date:
|
||||||
_log("INFO", f"✅ Movie {imdb_id}: Using digital release date {digital_date} from {digital_source}")
|
_log("INFO", f"✅ Movie {imdb_id}: Using digital release date {digital_date} from {digital_source}")
|
||||||
return digital_date, digital_source, released
|
# When using digital release date, store it as both dateadded and released
|
||||||
|
return digital_date, digital_source, digital_date
|
||||||
else:
|
else:
|
||||||
_log("WARNING", f"⚠️ Movie {imdb_id}: No import date OR digital release date found - trying additional fallbacks")
|
_log("WARNING", f"⚠️ Movie {imdb_id}: No import date OR digital release date found - trying additional fallbacks")
|
||||||
|
|
||||||
@@ -553,13 +555,15 @@ class MovieProcessor:
|
|||||||
radarr_premiered = self._get_radarr_nfo_premiered_date(movie_path)
|
radarr_premiered = self._get_radarr_nfo_premiered_date(movie_path)
|
||||||
if radarr_premiered:
|
if radarr_premiered:
|
||||||
_log("INFO", f"✅ Movie {imdb_id}: Using Radarr NFO premiered date {radarr_premiered}")
|
_log("INFO", f"✅ Movie {imdb_id}: Using Radarr NFO premiered date {radarr_premiered}")
|
||||||
return radarr_premiered, "radarr:nfo.premiered", released
|
# When using Radarr NFO premiered date, store it as both dateadded and released
|
||||||
|
return radarr_premiered, "radarr:nfo.premiered", radarr_premiered
|
||||||
|
|
||||||
else: # digital_then_import
|
else: # digital_then_import
|
||||||
# Try digital release first
|
# Try digital release first
|
||||||
digital_date, digital_source = self._get_digital_release_date(imdb_id)
|
digital_date, digital_source = self._get_digital_release_date(imdb_id)
|
||||||
if digital_date:
|
if digital_date:
|
||||||
return digital_date, digital_source, released
|
# When using digital release date, store it as both dateadded and released
|
||||||
|
return digital_date, digital_source, digital_date
|
||||||
|
|
||||||
# Fall back to import history
|
# Fall back to import history
|
||||||
if radarr_movie:
|
if radarr_movie:
|
||||||
|
|||||||
Reference in New Issue
Block a user