diff --git a/VERSION b/VERSION index 8abba37..68400d8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.9.8-bulk-date-update +2.9.9-results-fix-skip-tracking diff --git a/core/database_populator.py b/core/database_populator.py index ca0ae0b..55950b6 100644 --- a/core/database_populator.py +++ b/core/database_populator.py @@ -215,7 +215,8 @@ class DatabasePopulator: 'updated': 0, 'skipped': 0, 'errors': 0, - 'duration': 0.0 + 'duration': 0.0, + 'skipped_items': [] # Track what was skipped and why } try: @@ -267,6 +268,7 @@ class DatabasePopulator: try: season_num = episode.get('seasonNumber', 0) episode_num = episode.get('episodeNumber', 0) + episode_title = episode.get('title', 'Unknown') if season_num < 0 or episode_num <= 0: continue @@ -276,12 +278,28 @@ class DatabasePopulator: # Check if episode already exists existing = self.db.get_episode_date(imdb_id, season_num, episode_num) if existing and existing.get('dateadded'): + skip_info = { + 'title': series_title, + 'episode_title': episode_title, + 'season': season_num, + 'episode': episode_num, + 'reason': 'Already in database' + } + stats['skipped_items'].append(skip_info) stats['skipped'] += 1 continue # Only process episodes that have video files has_file = episode.get('hasFile', False) if not has_file: + skip_info = { + 'title': series_title, + 'episode_title': episode_title, + 'season': season_num, + 'episode': episode_num, + 'reason': 'No video file' + } + stats['skipped_items'].append(skip_info) stats['skipped'] += 1 continue @@ -310,6 +328,14 @@ class DatabasePopulator: source = 'sonarr:aired_fallback' elif not dateadded: # No date available + skip_info = { + 'title': series_title, + 'episode_title': episode_title, + 'season': season_num, + 'episode': episode_num, + 'reason': 'No import date from Sonarr history and no air date available' + } + stats['skipped_items'].append(skip_info) stats['skipped'] += 1 continue @@ -333,6 +359,15 @@ class DatabasePopulator: stats['duration'] = time.time() - start_time _log("INFO", f"TV episode population complete: {stats['added']} added, {stats['skipped']} skipped, {stats['errors']} errors in {stats['duration']:.2f}s") + + # Log details of skipped items + if stats['skipped_items']: + _log("INFO", f"Skipped episodes details ({len(stats['skipped_items'])} total):") + for item in stats['skipped_items'][:20]: # Only log first 20 to avoid spam + _log("INFO", f" - {item['title']} S{str(item['season']).zfill(2)}E{str(item['episode']).zfill(2)} ({item.get('episode_title', 'Unknown')}): {item['reason']}") + if len(stats['skipped_items']) > 20: + _log("INFO", f" ... and {len(stats['skipped_items']) - 20} more (see web interface for full list)") + return stats def populate_all(self) -> Dict[str, any]: diff --git a/nfoguard-web/static/index.html b/nfoguard-web/static/index.html index e0b9db2..ee81f62 100644 --- a/nfoguard-web/static/index.html +++ b/nfoguard-web/static/index.html @@ -711,6 +711,6 @@
- + \ No newline at end of file diff --git a/nfoguard-web/static/js/app.js b/nfoguard-web/static/js/app.js index b8b8cf7..130ea2f 100644 --- a/nfoguard-web/static/js/app.js +++ b/nfoguard-web/static/js/app.js @@ -2063,14 +2063,13 @@ function updatePopulateProgress(status) { progressText.textContent = 'Complete!'; } - // Show results (API returns movies/tv directly, not nested in result) + // Show results (API returns movies/tv with nested stats) if (resultsDiv && (status.movies || status.tv)) { - const result = status; // Use status directly, not status.result let html = '

Population Results

'; // Movies - if (result.movies) { - const m = result.movies; + if (status.movies && status.movies.stats) { + const m = status.movies.stats; html += '
'; html += '
Movies
'; html += ''; + // Show skipped items if any + if (m.skipped_items && m.skipped_items.length > 0) { + html += '
Skipped Movies (' + m.skipped_items.length + ')
'; + } html += '
'; } // TV Episodes - if (result.tv) { - const tv = result.tv; + if (status.tv && status.tv.stats) { + const tv = status.tv.stats; html += '
'; html += '
TV Shows
'; html += ''; + // Show skipped items if any + if (tv.skipped_items && tv.skipped_items.length > 0) { + html += '
Skipped Episodes (' + tv.skipped_items.length + ')
'; + } html += '
'; } - // Total duration - if (result.total_duration) { - html += `

Total Duration: ${result.total_duration.toFixed(2)}s

`; - } - resultsDiv.innerHTML = html; resultsDiv.style.display = 'block'; }