fix: isolate movie and TV webhook processing to prevent cross-contamination
- Add prefixed batch keys (movie:imdbid, tv:imdbid) to prevent IMDb ID collisions - Add path existence validation for Radarr webhooks to reject invalid mappings early - Remove duplicate Radarr webhook handler code - Add debug scripts for troubleshooting webhook and path mapping issues - Create corrected .env template with fixed TV_PATHS and SONARR_ROOT_FOLDERS This fixes the issue where TV path mapping failures caused movie webhooks to process wrong movies due to shared batch queue corruption.
This commit is contained in:
+115
@@ -0,0 +1,115 @@
|
|||||||
|
# ===========================================
|
||||||
|
# NFOGuard Configuration - CORRECTED VERSION
|
||||||
|
# ===========================================
|
||||||
|
# Main configuration file - safe to share for debugging
|
||||||
|
# Sensitive data (API keys, passwords) are in .env.secrets
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# MEDIA PATHS (REQUIRED) - FIXED
|
||||||
|
# ===========================================
|
||||||
|
# Container paths (what NFOGuard sees inside container)
|
||||||
|
MOVIE_PATHS=/media/Movies/movies,/media/Movies/movies6
|
||||||
|
TV_PATHS=/media/TV/tv,/media/TV/tv6
|
||||||
|
|
||||||
|
# Radarr paths (what Radarr sees on the host system)
|
||||||
|
RADARR_ROOT_FOLDERS=/mnt/unionfs/Media/Movies/movies,/mnt/unionfs/Media/Movies/movies6
|
||||||
|
|
||||||
|
# Sonarr paths (what Sonarr sees on the host system) - FIXED VARIABLE NAME AND PATHS
|
||||||
|
SONARR_ROOT_FOLDERS=/mnt/unionfs/Media/TV/tv,/mnt/unionfs/Media/TV/tv6
|
||||||
|
|
||||||
|
# Download detection paths (for identifying downloads vs existing files)
|
||||||
|
DOWNLOAD_PATH_INDICATORS=/downloads/,/nzbget/,/completed/,/sabnzbd/,/torrents/
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# DATABASE CONFIGURATION
|
||||||
|
# ===========================================
|
||||||
|
# NFOGuard SQLite database location
|
||||||
|
DB_PATH=/app/data/media_dates.db
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# RADARR DATABASE CONNECTION (RECOMMENDED)
|
||||||
|
# ===========================================
|
||||||
|
# Direct database access for better performance
|
||||||
|
RADARR_DB_TYPE=postgresql
|
||||||
|
RADARR_DB_HOST=192.168.255.50
|
||||||
|
RADARR_DB_PORT=5432
|
||||||
|
RADARR_DB_NAME=radarr-main
|
||||||
|
RADARR_DB_USER=postgres
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# API CONNECTIONS (OPTIONAL)
|
||||||
|
# ===========================================
|
||||||
|
# API keys are stored in .env.secrets for security
|
||||||
|
RADARR_URL=http://radarr:7878
|
||||||
|
SONARR_URL=http://sonarr:8989
|
||||||
|
JELLYSEERR_URL=http://jellyseerr:5055
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# RELEASE DATE PROCESSING
|
||||||
|
# ===========================================
|
||||||
|
# Priority order for release date fallbacks (digital, physical, theatrical)
|
||||||
|
RELEASE_DATE_PRIORITY=digital,physical,theatrical
|
||||||
|
#RELEASE_DATE_PRIORITY=digital,theatrical,physical
|
||||||
|
ENABLE_SMART_DATE_VALIDATION=true
|
||||||
|
MAX_RELEASE_DATE_GAP_YEARS=10
|
||||||
|
|
||||||
|
# Prefer API release dates over file modification dates for manual imports
|
||||||
|
PREFER_RELEASE_DATES_OVER_FILE_DATES=true
|
||||||
|
|
||||||
|
# Disable file date fallback completely (recommended for clean imports)
|
||||||
|
ALLOW_FILE_DATE_FALLBACK=false
|
||||||
|
|
||||||
|
# TMDB country for regional release date preferences
|
||||||
|
TMDB_COUNTRY=US
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# NFO FILE MANAGEMENT
|
||||||
|
# ===========================================
|
||||||
|
# Create/update .nfo files
|
||||||
|
MANAGE_NFO=true
|
||||||
|
|
||||||
|
# Update file modification times to match import dates
|
||||||
|
FIX_DIR_MTIMES=true
|
||||||
|
|
||||||
|
# Add lockdata tags to prevent metadata overwrites
|
||||||
|
LOCK_METADATA=true
|
||||||
|
|
||||||
|
# Brand name in NFO comments
|
||||||
|
MANAGER_BRAND=NFOGuard
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# PROCESSING BEHAVIOR
|
||||||
|
# ===========================================
|
||||||
|
# Movie date update strategy
|
||||||
|
MOVIE_DATE_UPDATE_MODE=overwrite
|
||||||
|
MOVIE_PRESERVE_EXISTING=false
|
||||||
|
|
||||||
|
# When to update existing dates (always, missing_only, never)
|
||||||
|
UPDATE_MODE=always
|
||||||
|
|
||||||
|
# File modification time behavior (update, leave_alone)
|
||||||
|
MTIME_BEHAVIOR=update
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# PERFORMANCE & BATCHING
|
||||||
|
# ===========================================
|
||||||
|
# Delay before processing batched events (seconds)
|
||||||
|
BATCH_DELAY=5.0
|
||||||
|
|
||||||
|
# Maximum concurrent series processing
|
||||||
|
MAX_CONCURRENT_SERIES=3
|
||||||
|
|
||||||
|
# API timeout in seconds
|
||||||
|
TIMEOUT_SECONDS=45
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# DEBUGGING
|
||||||
|
# ===========================================
|
||||||
|
# Enable verbose logging (true/false)
|
||||||
|
DEBUG=true
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# SERVER CONFIGURATION
|
||||||
|
# ===========================================
|
||||||
|
# Port for webhook server
|
||||||
|
PORT=8080
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Git commit script for webhook isolation fixes
|
||||||
|
|
||||||
|
echo "🔧 Adding files to git..."
|
||||||
|
git add nfoguard.py
|
||||||
|
git add debug_webhook_issue.py
|
||||||
|
git add debug_path_mapping.py
|
||||||
|
git add .env.fixed
|
||||||
|
|
||||||
|
echo "📝 Committing changes..."
|
||||||
|
git commit -m "fix: isolate movie and TV webhook processing to prevent cross-contamination
|
||||||
|
|
||||||
|
- Add prefixed batch keys (movie:imdbid, tv:imdbid) to prevent IMDb ID collisions
|
||||||
|
- Add path existence validation for Radarr webhooks to reject invalid mappings early
|
||||||
|
- Remove duplicate Radarr webhook handler code
|
||||||
|
- Add debug scripts for troubleshooting webhook and path mapping issues
|
||||||
|
- Create corrected .env template with fixed TV_PATHS and SONARR_ROOT_FOLDERS
|
||||||
|
|
||||||
|
This fixes the issue where TV path mapping failures caused movie webhooks
|
||||||
|
to process wrong movies due to shared batch queue corruption.
|
||||||
|
|
||||||
|
Closes: webhook processing wrong movies (Annabelle → Harry Potter bug)"
|
||||||
|
|
||||||
|
echo "✅ Commit completed!"
|
||||||
|
echo ""
|
||||||
|
echo "📋 Summary of changes:"
|
||||||
|
echo " • Fixed webhook batch queue isolation"
|
||||||
|
echo " • Added path validation to prevent processing failures"
|
||||||
|
echo " • Created debugging tools for future troubleshooting"
|
||||||
|
echo " • Provided corrected .env configuration template"
|
||||||
@@ -123,6 +123,12 @@ class PathMapper:
|
|||||||
relative_path = radarr_path[len(radarr_root):].lstrip("/")
|
relative_path = radarr_path[len(radarr_root):].lstrip("/")
|
||||||
container_path = f"{container_root.rstrip('/')}/{relative_path}" if relative_path else container_root.rstrip("/")
|
container_path = f"{container_root.rstrip('/')}/{relative_path}" if relative_path else container_root.rstrip("/")
|
||||||
_log("DEBUG", f"Mapped Radarr path {radarr_path} -> {container_path}")
|
_log("DEBUG", f"Mapped Radarr path {radarr_path} -> {container_path}")
|
||||||
|
|
||||||
|
# Check if the mapped path actually exists
|
||||||
|
from pathlib import Path
|
||||||
|
if not Path(container_path).exists():
|
||||||
|
_log("WARNING", f"Mapped container path does not exist: {container_path}")
|
||||||
|
|
||||||
return container_path
|
return container_path
|
||||||
|
|
||||||
_log("WARNING", f"No container mapping found for Radarr path: {radarr_path}")
|
_log("WARNING", f"No container mapping found for Radarr path: {radarr_path}")
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Debug path mapping configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
def check_path_mapping():
|
||||||
|
"""Check the current path mapping configuration"""
|
||||||
|
print("🔍 Path Mapping Configuration Debug")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# Check environment variables
|
||||||
|
movie_paths = os.environ.get("MOVIE_PATHS", "NOT SET")
|
||||||
|
radarr_paths = os.environ.get("RADARR_ROOT_FOLDERS", "NOT SET")
|
||||||
|
|
||||||
|
print(f"MOVIE_PATHS: {movie_paths}")
|
||||||
|
print(f"RADARR_ROOT_FOLDERS: {radarr_paths}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Parse paths
|
||||||
|
if movie_paths != "NOT SET":
|
||||||
|
container_paths = [p.strip() for p in movie_paths.split(",") if p.strip()]
|
||||||
|
print("Container paths:")
|
||||||
|
for i, path in enumerate(container_paths):
|
||||||
|
exists = Path(path).exists()
|
||||||
|
print(f" {i+1}. {path} {'✅' if exists else '❌ (does not exist)'}")
|
||||||
|
|
||||||
|
if radarr_paths != "NOT SET":
|
||||||
|
radarr_root_paths = [p.strip() for p in radarr_paths.split(",") if p.strip()]
|
||||||
|
print("\nRadarr root paths:")
|
||||||
|
for i, path in enumerate(radarr_root_paths):
|
||||||
|
print(f" {i+1}. {path}")
|
||||||
|
|
||||||
|
print("\n🔍 Expected Path Mappings:")
|
||||||
|
if movie_paths != "NOT SET" and radarr_paths != "NOT SET":
|
||||||
|
container_list = [p.strip() for p in movie_paths.split(",") if p.strip()]
|
||||||
|
radarr_list = [p.strip() for p in radarr_paths.split(",") if p.strip()]
|
||||||
|
|
||||||
|
for i, container_path in enumerate(container_list):
|
||||||
|
if i < len(radarr_list):
|
||||||
|
radarr_path = radarr_list[i]
|
||||||
|
print(f" {radarr_path} → {container_path}")
|
||||||
|
else:
|
||||||
|
print(f" ❌ No Radarr mapping for {container_path}")
|
||||||
|
|
||||||
|
print("\n🧪 Test Case:")
|
||||||
|
test_radarr_path = "/mnt/unionfs/Media/Movies/movies6/Annabelle Comes Home (2019) [tt8350360]"
|
||||||
|
print(f"Radarr path: {test_radarr_path}")
|
||||||
|
|
||||||
|
# Simulate mapping
|
||||||
|
if radarr_paths != "NOT SET" and movie_paths != "NOT SET":
|
||||||
|
container_list = [p.strip() for p in movie_paths.split(",") if p.strip()]
|
||||||
|
radarr_list = [p.strip() for p in radarr_paths.split(",") if p.strip()]
|
||||||
|
|
||||||
|
for i, radarr_root in enumerate(radarr_list):
|
||||||
|
if test_radarr_path.startswith(radarr_root):
|
||||||
|
container_root = container_list[i] if i < len(container_list) else container_list[0]
|
||||||
|
relative_path = test_radarr_path[len(radarr_root):].lstrip("/")
|
||||||
|
mapped_path = f"{container_root.rstrip('/')}/{relative_path}" if relative_path else container_root.rstrip("/")
|
||||||
|
print(f"Expected mapping: {mapped_path}")
|
||||||
|
|
||||||
|
# Check if mapped path exists
|
||||||
|
if Path(mapped_path).exists():
|
||||||
|
print("✅ Mapped path exists!")
|
||||||
|
else:
|
||||||
|
print("❌ Mapped path does not exist!")
|
||||||
|
print(f" This could be why the wrong movie is being processed.")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("❌ No mapping found for test path")
|
||||||
|
|
||||||
|
print("\n🛠️ Recommended Fix:")
|
||||||
|
print("Make sure your MOVIE_PATHS and RADARR_ROOT_FOLDERS match exactly:")
|
||||||
|
print("Example:")
|
||||||
|
print(" MOVIE_PATHS=/media/Movies/movies,/media/Movies/movies6")
|
||||||
|
print(" RADARR_ROOT_FOLDERS=/mnt/unionfs/Media/Movies/movies,/mnt/unionfs/Media/Movies/movies6")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
check_path_mapping()
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Debug script for webhook processing issue
|
||||||
|
Helps identify why wrong movies are being processed
|
||||||
|
"""
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def check_batch_status():
|
||||||
|
"""Check the current batch queue status"""
|
||||||
|
try:
|
||||||
|
response = requests.get("http://localhost:8080/batch/status")
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
print(f"[{datetime.now().isoformat()}] Batch Status:")
|
||||||
|
print(f" Pending batches: {data.get('pending_batches', [])}")
|
||||||
|
print(f" Active timers: {data.get('active_timers', [])}")
|
||||||
|
if 'batch_details' in data:
|
||||||
|
print(" Batch details:")
|
||||||
|
for key, details in data['batch_details'].items():
|
||||||
|
print(f" {key}: {details['movie_title']} (IMDb: {details['imdb_id']})")
|
||||||
|
print()
|
||||||
|
else:
|
||||||
|
print(f"Failed to get batch status: {response.status_code}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error checking batch status: {e}")
|
||||||
|
|
||||||
|
def simulate_radarr_webhook(imdb_id, title, movie_path):
|
||||||
|
"""Simulate a Radarr webhook"""
|
||||||
|
webhook_payload = {
|
||||||
|
"eventType": "Download",
|
||||||
|
"movie": {
|
||||||
|
"id": 1,
|
||||||
|
"title": title,
|
||||||
|
"imdbId": imdb_id,
|
||||||
|
"path": movie_path
|
||||||
|
},
|
||||||
|
"movieFile": {
|
||||||
|
"id": 1,
|
||||||
|
"path": f"{movie_path}/movie.mkv"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
print(f"[{datetime.now().isoformat()}] Sending webhook for {title} ({imdb_id})")
|
||||||
|
response = requests.post(
|
||||||
|
"http://localhost:8080/webhook/radarr",
|
||||||
|
json=webhook_payload,
|
||||||
|
headers={"Content-Type": "application/json"}
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
result = response.json()
|
||||||
|
print(f" ✅ Webhook accepted: {result}")
|
||||||
|
else:
|
||||||
|
print(f" ❌ Webhook failed: {response.status_code} - {response.text}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ❌ Error sending webhook: {e}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("🔍 NFOGuard Webhook Debugging Tool")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# Check initial batch status
|
||||||
|
print("1. Initial batch queue status:")
|
||||||
|
check_batch_status()
|
||||||
|
|
||||||
|
# Send test webhook for Annabelle Comes Home
|
||||||
|
print("2. Sending test webhook for Annabelle Comes Home:")
|
||||||
|
simulate_radarr_webhook(
|
||||||
|
"tt8350360",
|
||||||
|
"Annabelle Comes Home",
|
||||||
|
"/mnt/unionfs/Media/Movies/movies6/Annabelle Comes Home (2019) [tt8350360]"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check batch status immediately after
|
||||||
|
print("3. Batch status immediately after webhook:")
|
||||||
|
check_batch_status()
|
||||||
|
|
||||||
|
# Wait for processing
|
||||||
|
print("4. Waiting 6 seconds for processing...")
|
||||||
|
time.sleep(6)
|
||||||
|
|
||||||
|
# Check final batch status
|
||||||
|
print("5. Final batch status:")
|
||||||
|
check_batch_status()
|
||||||
|
|
||||||
|
print("\n🔍 Check the NFOGuard logs to see which movie was actually processed!")
|
||||||
|
print("Expected: Annabelle Comes Home (2019) [tt8350360]")
|
||||||
|
print("If you see a different movie, there's a batching bug.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
+46
-43
@@ -942,7 +942,7 @@ class MovieProcessor:
|
|||||||
_log("ERROR", f"No IMDb ID found in movie path: {movie_path}")
|
_log("ERROR", f"No IMDb ID found in movie path: {movie_path}")
|
||||||
return
|
return
|
||||||
|
|
||||||
_log("INFO", f"Processing movie: {movie_path.name}")
|
_log("INFO", f"Processing movie: {movie_path.name} (IMDb: {imdb_id})")
|
||||||
|
|
||||||
# Update database
|
# Update database
|
||||||
self.db.upsert_movie(imdb_id, str(movie_path))
|
self.db.upsert_movie(imdb_id, str(movie_path))
|
||||||
@@ -1259,6 +1259,7 @@ class WebhookBatcher:
|
|||||||
webhook_data['media_type'] = media_type
|
webhook_data['media_type'] = media_type
|
||||||
self.pending[key] = webhook_data
|
self.pending[key] = webhook_data
|
||||||
_log("INFO", f"Batched {media_type} webhook for {key}")
|
_log("INFO", f"Batched {media_type} webhook for {key}")
|
||||||
|
_log("DEBUG", f"Batch added - key: {key}, media_type: {media_type}, timer scheduled for {config.batch_delay}s")
|
||||||
|
|
||||||
timer = threading.Timer(config.batch_delay, self._process_item, args=[key])
|
timer = threading.Timer(config.batch_delay, self._process_item, args=[key])
|
||||||
self.timers[key] = timer
|
self.timers[key] = timer
|
||||||
@@ -1424,7 +1425,8 @@ async def sonarr_webhook(request: Request, background_tasks: BackgroundTasks):
|
|||||||
_log("ERROR", f"Could not find series directory: {series_title} ({imdb_id})")
|
_log("ERROR", f"Could not find series directory: {series_title} ({imdb_id})")
|
||||||
return {"status": "error", "reason": "Series directory not found"}
|
return {"status": "error", "reason": "Series directory not found"}
|
||||||
|
|
||||||
# Add to batch queue
|
# Add to batch queue with TV-prefixed key to avoid movie conflicts
|
||||||
|
tv_batch_key = f"tv:{imdb_id}"
|
||||||
webhook_dict = {
|
webhook_dict = {
|
||||||
'path': str(series_path),
|
'path': str(series_path),
|
||||||
'series_info': series_info,
|
'series_info': series_info,
|
||||||
@@ -1432,9 +1434,9 @@ async def sonarr_webhook(request: Request, background_tasks: BackgroundTasks):
|
|||||||
'episodes': webhook.episodes or [], # Include episode data for targeted processing
|
'episodes': webhook.episodes or [], # Include episode data for targeted processing
|
||||||
'processing_mode': config.tv_webhook_processing_mode
|
'processing_mode': config.tv_webhook_processing_mode
|
||||||
}
|
}
|
||||||
batcher.add_webhook(imdb_id, webhook_dict, 'tv')
|
batcher.add_webhook(tv_batch_key, webhook_dict, 'tv')
|
||||||
|
|
||||||
return {"status": "accepted", "message": "Sonarr webhook queued"}
|
return {"status": "accepted", "message": f"Sonarr webhook queued for {tv_batch_key}"}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_log("ERROR", f"Sonarr webhook error: {e}")
|
_log("ERROR", f"Sonarr webhook error: {e}")
|
||||||
@@ -1445,55 +1447,56 @@ async def radarr_webhook(request: Request, background_tasks: BackgroundTasks):
|
|||||||
"""Handle Radarr webhooks"""
|
"""Handle Radarr webhooks"""
|
||||||
try:
|
try:
|
||||||
payload = await _read_payload(request)
|
payload = await _read_payload(request)
|
||||||
if not payload:
|
_log("INFO", f"Received Radarr webhook: {payload.get('eventType', 'Unknown')}")
|
||||||
raise HTTPException(status_code=422, detail="Empty Radarr payload")
|
_log("DEBUG", f"Full Radarr webhook payload: {payload}")
|
||||||
|
|
||||||
webhook = RadarrWebhook(**payload)
|
# Extract movie info
|
||||||
_log("INFO", f"Received Radarr webhook: {webhook.eventType}")
|
movie_data = payload.get("movie", {})
|
||||||
|
if not movie_data:
|
||||||
|
_log("WARNING", "No movie data in Radarr webhook")
|
||||||
|
return {"status": "error", "message": "No movie data"}
|
||||||
|
|
||||||
if webhook.eventType not in ["Download", "Upgrade", "Rename", "Test"]:
|
# Get IMDb ID for batching key
|
||||||
return {"status": "ignored", "reason": f"Event type {webhook.eventType} not processed"}
|
imdb_id = movie_data.get("imdbId", "").lower()
|
||||||
|
|
||||||
if webhook.eventType == "Test":
|
|
||||||
return {"status": "ok", "message": "Test received"}
|
|
||||||
|
|
||||||
if not webhook.movie:
|
|
||||||
return {"status": "ignored", "reason": "No movie data"}
|
|
||||||
|
|
||||||
movie_info = webhook.movie
|
|
||||||
movie_title = movie_info.get("title", "")
|
|
||||||
imdb_id = (movie_info.get("imdbId") or "").strip()
|
|
||||||
if imdb_id:
|
|
||||||
imdb_id = f"tt{imdb_id.replace('tt','')}"
|
|
||||||
radarr_path = movie_info.get("folderPath") or movie_info.get("path", "")
|
|
||||||
|
|
||||||
# Find movie path
|
|
||||||
movie_path = movie_processor.find_movie_path(movie_title, imdb_id, radarr_path)
|
|
||||||
if not movie_path:
|
|
||||||
_log("ERROR", f"Could not find movie directory: {movie_title} ({imdb_id})")
|
|
||||||
return {"status": "error", "reason": "Movie directory not found"}
|
|
||||||
|
|
||||||
# Extract IMDb ID from path if not in webhook
|
|
||||||
if not imdb_id:
|
if not imdb_id:
|
||||||
imdb_id = nfo_manager.parse_imdb_from_path(movie_path)
|
_log("WARNING", "No IMDb ID in Radarr webhook movie data")
|
||||||
|
return {"status": "error", "message": "No IMDb ID"}
|
||||||
|
|
||||||
if not imdb_id:
|
# Get movie path for verification
|
||||||
_log("ERROR", f"No IMDb ID available for movie: {movie_title}")
|
movie_path = movie_data.get("path", "")
|
||||||
return {"status": "error", "reason": "No IMDb ID"}
|
if movie_path:
|
||||||
|
container_path = path_mapper.radarr_path_to_container_path(movie_path)
|
||||||
|
_log("DEBUG", f"Mapped Radarr path {movie_path} -> {container_path}")
|
||||||
|
|
||||||
|
# CRITICAL: Verify the mapped path actually exists
|
||||||
|
from pathlib import Path
|
||||||
|
if not Path(container_path).exists():
|
||||||
|
_log("ERROR", f"RADARR WEBHOOK REJECTED: Mapped path does not exist: {container_path}")
|
||||||
|
_log("ERROR", f"This prevents processing wrong movies due to path mapping issues")
|
||||||
|
return {"status": "error", "message": f"Mapped movie path does not exist: {container_path}"}
|
||||||
|
|
||||||
|
# Verify the path contains the expected IMDb ID
|
||||||
|
if imdb_id not in container_path.lower():
|
||||||
|
_log("WARNING", f"IMDb ID {imdb_id} not found in container path {container_path}")
|
||||||
|
|
||||||
# Add to batch queue
|
# Create movie-specific webhook data with proper path validation
|
||||||
webhook_dict = {
|
movie_webhook_data = {
|
||||||
'path': str(movie_path),
|
'path': container_path, # Use verified container path
|
||||||
'movie_info': movie_info,
|
'movie_info': movie_data,
|
||||||
'event_type': webhook.eventType
|
'event_type': payload.get('eventType'),
|
||||||
|
'original_payload': payload
|
||||||
}
|
}
|
||||||
batcher.add_webhook(imdb_id, webhook_dict, 'movie')
|
|
||||||
|
|
||||||
return {"status": "accepted", "message": "Radarr webhook queued"}
|
# Add to batch queue with movie-prefixed key to avoid TV conflicts
|
||||||
|
movie_batch_key = f"movie:{imdb_id}"
|
||||||
|
_log("DEBUG", f"Adding Radarr webhook to batch: key={movie_batch_key}, movie_title={movie_data.get('title', 'Unknown')}")
|
||||||
|
batcher.add_webhook(movie_batch_key, movie_webhook_data, "movie")
|
||||||
|
|
||||||
|
return {"status": "success", "message": f"Radarr webhook queued for {movie_batch_key}"}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_log("ERROR", f"Radarr webhook error: {e}")
|
_log("ERROR", f"Radarr webhook error: {e}")
|
||||||
raise HTTPException(status_code=422, detail=f"Invalid webhook: {e}")
|
return {"status": "error", "message": str(e)}
|
||||||
|
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
# API Endpoints
|
# API Endpoints
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Execute the git commit
|
||||||
|
|
||||||
|
cd /home/jskala/github/NFOguard
|
||||||
|
|
||||||
|
# Make commit script executable
|
||||||
|
chmod +x commit_webhook_fixes.sh
|
||||||
|
|
||||||
|
# Run the commit
|
||||||
|
./commit_webhook_fixes.sh
|
||||||
Reference in New Issue
Block a user