From 413c8ad6f6010f8d28882a231d1911819c7f20ee Mon Sep 17 00:00:00 2001 From: SBCrumb Date: Wed, 22 Oct 2025 17:48:29 -0400 Subject: [PATCH] web: status bug fix --- api/web_routes.py | 113 +++++++++++----------------------- nfoguard-web/static/js/app.js | 28 +++++---- 2 files changed, 52 insertions(+), 89 deletions(-) diff --git a/api/web_routes.py b/api/web_routes.py index a3c4be7..d61fb60 100644 --- a/api/web_routes.py +++ b/api/web_routes.py @@ -1362,100 +1362,59 @@ def register_web_routes(app, dependencies): except Exception as e: raise HTTPException(status_code=500, detail=f"Manual scan request failed: {str(e)}") + # Simple scan tracking (since we can't reliably access docker logs from container) + scan_tracking = {"last_scan_time": None, "scanning": False} + + @app.post("/api/scan/track") + async def track_scan_start(): + """Called when a scan is initiated to track timing""" + from datetime import datetime + scan_tracking["last_scan_time"] = datetime.now() + scan_tracking["scanning"] = True + return {"status": "tracked"} + @app.get("/api/scan/status") async def api_scan_status(): - """Check scan status by attempting to detect scan activity""" + """Check scan status using simple time-based tracking""" import urllib.request import urllib.error import json import os import socket - import subprocess - import re from datetime import datetime, timedelta - # Get core container URL to check if it's responsive + # Check if we have a recent scan + if scan_tracking["last_scan_time"]: + time_since_scan = datetime.now() - scan_tracking["last_scan_time"] + + # Assume scan is active for up to 10 minutes after initiation + # This is a reasonable estimate for most scan operations + if time_since_scan < timedelta(minutes=10) and scan_tracking["scanning"]: + minutes_elapsed = int(time_since_scan.total_seconds() / 60) + seconds_elapsed = int(time_since_scan.total_seconds() % 60) + + if minutes_elapsed > 0: + elapsed_str = f"{minutes_elapsed}m {seconds_elapsed}s" + else: + elapsed_str = f"{seconds_elapsed}s" + + return { + "scanning": True, + "message": f"Scan in progress ({elapsed_str} elapsed) - check core logs for details" + } + + # Check if core container is responsive core_host = os.environ.get("CORE_API_HOST", "nfoguard-core") core_port = os.environ.get("CORE_API_PORT", "8080") - try: - # Try to get recent logs from core container to detect scanning activity - # This uses docker logs with timestamp filtering - result = subprocess.run([ - 'docker', 'logs', '--since', '30s', 'nfoguard-core' - ], capture_output=True, text=True, timeout=5) - - if result.returncode == 0: - logs = result.stdout - - # Look for scan activity patterns - scan_patterns = [ - r'Processing TV series: (.+?) \[imdb', - r'INFO: Scanning movies in: (.+)', - r'Processed (\d+) TV series', - r'MANUAL SCAN STARTED: (.+?) scan', - r'MANUAL SCAN COMPLETED: (.+?) scan' - ] - - current_activity = None - scan_active = False - series_count = 0 - - # Parse recent logs for activity - lines = logs.split('\n') - for line in reversed(lines[-50:]): # Check last 50 lines - # Check for completion - if 'MANUAL SCAN COMPLETED' in line: - break - - # Check for start - if 'MANUAL SCAN STARTED' in line: - scan_active = True - match = re.search(r'MANUAL SCAN STARTED: (.+?) scan', line) - if match: - scan_type = match.group(1) - break - - # Check for current processing - if 'Processing TV series:' in line: - match = re.search(r'Processing TV series: (.+?) \[imdb', line) - if match: - current_activity = f"Processing: {match.group(1)}" - scan_active = True - elif 'Scanning movies in:' in line: - match = re.search(r'Scanning movies in: (.+)', line) - if match: - current_activity = f"Scanning movies in: {match.group(1)}" - scan_active = True - elif 'Processed' in line and 'TV series' in line: - match = re.search(r'Processed (\d+) TV series', line) - if match: - series_count = int(match.group(1)) - - if scan_active and current_activity: - message = current_activity - if series_count > 0: - message += f" ({series_count} series processed)" - return {"scanning": True, "message": message} - elif scan_active: - return {"scanning": True, "message": "Scan in progress..."} - else: - return {"scanning": False, "message": "No scan detected"} - - except subprocess.TimeoutExpired: - pass - except subprocess.SubprocessError: - pass - except Exception: - pass - - # Fallback to basic health check try: health_url = f"http://{core_host}:{core_port}/health" req = urllib.request.Request(health_url) with urllib.request.urlopen(req, timeout=5) as response: - return {"scanning": False, "message": "No recent scan activity detected"} + # Mark scanning as false if we reach here and enough time has passed + scan_tracking["scanning"] = False + return {"scanning": False, "message": "No active scan detected"} except (urllib.error.URLError, socket.timeout): return {"scanning": False, "message": "Core container unavailable"} diff --git a/nfoguard-web/static/js/app.js b/nfoguard-web/static/js/app.js index 3038840..b8d1de4 100644 --- a/nfoguard-web/static/js/app.js +++ b/nfoguard-web/static/js/app.js @@ -1443,7 +1443,14 @@ async function handleManualScan(event) { showToast(`✅ Manual scan initiated: ${result.message}`, 'success'); - // Start polling for scan status with log-based detection + // Track scan start time for status monitoring + try { + await apiCall('/api/scan/track', { method: 'POST' }); + } catch (e) { + console.log('Failed to track scan start:', e); + } + + // Start polling for scan status startScanStatusPolling(); } catch (error) { @@ -1486,7 +1493,14 @@ async function handleCustomScan(event) { showToast(`✅ Custom scan initiated: ${result.message}`, 'success'); - // Start polling for scan status with log-based detection + // Track scan start time for status monitoring + try { + await apiCall('/api/scan/track', { method: 'POST' }); + } catch (e) { + console.log('Failed to track scan start:', e); + } + + // Start polling for scan status startScanStatusPolling(); } catch (error) { @@ -1528,10 +1542,7 @@ function updateScanStatus(message, isActive = false) { const statusBanner = document.getElementById('dashboard-scan-status'); const statusText = document.getElementById('dashboard-scan-text'); - console.log('updateScanStatus called:', { message, isActive, statusBanner: !!statusBanner, statusText: !!statusText }); - if (!statusBanner || !statusText) { - console.log('Scan status elements not found, skipping update'); return; } @@ -1540,15 +1551,12 @@ function updateScanStatus(message, isActive = false) { if (isActive) { statusBanner.className = 'scan-status-banner active'; statusBanner.style.display = 'block'; - console.log('Scan status banner activated:', message); } else { statusBanner.className = 'scan-status-banner'; - console.log('Scan status banner deactivated:', message); // Don't hide completely, just mark as inactive setTimeout(() => { if (statusBanner.className === 'scan-status-banner') { statusBanner.style.display = 'none'; - console.log('Scan status banner hidden after timeout'); } }, 3000); } @@ -1556,16 +1564,13 @@ function updateScanStatus(message, isActive = false) { async function checkScanStatus() { try { - console.log('Checking scan status...'); const status = await apiCall('/api/scan/status'); - console.log('Scan status response:', status); if (status.scanning) { updateScanStatus(status.message || 'Scan in progress...', true); // Start polling if not already polling if (!scanStatusInterval) { - console.log('Starting scan status polling from checkScanStatus'); startScanStatusPolling(); } return true; // Continue polling @@ -1602,7 +1607,6 @@ function startScanStatusPolling() { } }, 2000); - console.log('Started scan status polling'); } function stopScanStatusPolling() {