Add post-scan phase progress to watchlist automation card

pull/253/head
Broque Thomas 2 months ago
parent 5b507d897e
commit cdcaa245d1

@ -1508,7 +1508,7 @@ class WatchlistScanner:
logger.error(f"Error fetching similar artists for {watchlist_artist.artist_name}: {e}")
return False
def populate_discovery_pool(self, top_artists_limit: int = 50, albums_per_artist: int = 10, profile_id: int = 1):
def populate_discovery_pool(self, top_artists_limit: int = 50, albums_per_artist: int = 10, profile_id: int = 1, progress_callback=None):
"""
Populate discovery pool with tracks from top similar artists.
Called after watchlist scan completes.
@ -1529,8 +1529,14 @@ class WatchlistScanner:
if skip_pool_population:
logger.info("Discovery pool was populated recently (< 24 hours ago). Skipping pool population.")
logger.info("But still refreshing recent albums cache and curated playlists...")
if progress_callback:
progress_callback('skip', 'Discovery pool recently updated, skipping')
# Still run these even when skipping main pool population
if progress_callback:
progress_callback('phase', 'Caching recent albums...')
self.cache_discovery_recent_albums(profile_id=profile_id)
if progress_callback:
progress_callback('phase', 'Curating playlists...')
self.curate_discovery_playlists(profile_id=profile_id)
return
@ -1556,8 +1562,14 @@ class WatchlistScanner:
if not similar_artists:
logger.info("No similar artists found to populate discovery pool from similar artists")
logger.info("But still caching recent albums from watchlist artists and curating playlists...")
if progress_callback:
progress_callback('skip', 'No similar artists found')
# Still run these even without similar artists - they use watchlist artists
if progress_callback:
progress_callback('phase', 'Caching recent albums...')
self.cache_discovery_recent_albums(profile_id=profile_id)
if progress_callback:
progress_callback('phase', 'Curating playlists...')
self.curate_discovery_playlists(profile_id=profile_id)
return
@ -1568,6 +1580,8 @@ class WatchlistScanner:
for artist_idx, similar_artist in enumerate(similar_artists, 1):
try:
logger.info(f"[{artist_idx}/{len(similar_artists)}] Processing {similar_artist.similar_artist_name} (occurrence: {similar_artist.occurrence_count})")
if progress_callback:
progress_callback('artist', f'{similar_artist.similar_artist_name} ({artist_idx}/{len(similar_artists)})')
# Build list of sources to process for this artist
# iTunes is ALWAYS processed (baseline), Spotify is added if authenticated
@ -1766,6 +1780,8 @@ class WatchlistScanner:
continue
logger.info(f"Discovery pool from similar artists complete: {total_tracks_added} tracks added")
if progress_callback:
progress_callback('success', f'Discovery pool: {total_tracks_added} tracks from {len(similar_artists)} artists')
# Note: Watchlist artist albums are already in discovery pool from the watchlist scan itself
# No need to re-fetch them here to avoid duplicate API calls
@ -1927,10 +1943,14 @@ class WatchlistScanner:
# Cache recent albums for discovery page
logger.info("Caching recent albums for discovery page...")
if progress_callback:
progress_callback('phase', 'Caching recent albums...')
self.cache_discovery_recent_albums(profile_id=profile_id)
# Curate playlists for consistent daily experience
logger.info("Curating discovery playlists...")
if progress_callback:
progress_callback('phase', 'Curating playlists...')
self.curate_discovery_playlists(profile_id=profile_id)
except Exception as e:

@ -24850,35 +24850,66 @@ def _process_watchlist_scan_automatically(automation_id=None):
# Populate discovery pool from similar artists (per-profile)
print("🎵 Starting discovery pool population...")
watchlist_scan_state['current_phase'] = 'populating_discovery_pool'
_update_automation_progress(automation_id, progress=96, phase='Populating discovery pool',
log_line='Building discovery pool from similar artists...', log_type='info')
try:
def _discovery_progress(event_type, message):
if event_type == 'artist':
_update_automation_progress(automation_id, phase=f'Discovery pool: {message}',
log_line=message, log_type='info',
current_item=message)
elif event_type == 'phase':
_update_automation_progress(automation_id, phase=message,
log_line=message, log_type='info')
elif event_type == 'success':
_update_automation_progress(automation_id,
log_line=message, log_type='success')
elif event_type == 'skip':
_update_automation_progress(automation_id,
log_line=message, log_type='info')
for p in all_profiles:
scanner.populate_discovery_pool(profile_id=p['id'])
scanner.populate_discovery_pool(profile_id=p['id'], progress_callback=_discovery_progress)
print("✅ Discovery pool population complete")
except Exception as discovery_error:
print(f"⚠️ Error populating discovery pool: {discovery_error}")
import traceback
traceback.print_exc()
_update_automation_progress(automation_id,
log_line=f'Discovery pool error: {discovery_error}', log_type='error')
# Update ListenBrainz playlists cache
print("🧠 Starting ListenBrainz playlists update...")
watchlist_scan_state['current_phase'] = 'updating_listenbrainz'
_update_automation_progress(automation_id, progress=97, phase='Updating ListenBrainz',
log_line='Fetching ListenBrainz playlists...', log_type='info')
try:
from core.listenbrainz_manager import ListenBrainzManager
lb_manager = ListenBrainzManager(str(get_database().database_path))
lb_result = lb_manager.update_all_playlists()
if lb_result.get('success'):
summary = lb_result.get('summary', {})
updated = summary.get('updated', 0)
total_lb = summary.get('total', 0)
print(f"✅ ListenBrainz update complete: {summary}")
_update_automation_progress(automation_id,
log_line=f'ListenBrainz: {updated}/{total_lb} playlists updated', log_type='success')
else:
print(f"⚠️ ListenBrainz update had issues: {lb_result.get('error', 'Unknown error')}")
_update_automation_progress(automation_id,
log_line=f'ListenBrainz: {lb_result.get("error", "Unknown error")}', log_type='error')
except Exception as lb_error:
print(f"⚠️ Error updating ListenBrainz: {lb_error}")
import traceback
traceback.print_exc()
_update_automation_progress(automation_id,
log_line=f'ListenBrainz error: {lb_error}', log_type='error')
# Update current seasonal playlist (weekly refresh)
print("🎃 Starting seasonal content update...")
watchlist_scan_state['current_phase'] = 'updating_seasonal'
_update_automation_progress(automation_id, progress=98, phase='Updating seasonal content',
log_line='Checking seasonal playlists...', log_type='info')
try:
from core.seasonal_discovery import get_seasonal_discovery_service
seasonal_service = get_seasonal_discovery_service(spotify_client, database)
@ -24888,17 +24919,27 @@ def _process_watchlist_scan_automatically(automation_id=None):
if current_season:
if seasonal_service.should_populate_seasonal_content(current_season, days_threshold=7):
print(f"🎃 Updating {current_season} seasonal content...")
_update_automation_progress(automation_id,
log_line=f'Updating {current_season} seasonal content...', log_type='info')
seasonal_service.populate_seasonal_content(current_season)
seasonal_service.curate_seasonal_playlist(current_season)
print(f"{current_season.capitalize()} seasonal content updated")
_update_automation_progress(automation_id,
log_line=f'{current_season.capitalize()} seasonal content updated', log_type='success')
else:
print(f"⏭️ {current_season.capitalize()} seasonal content recently updated, skipping")
_update_automation_progress(automation_id,
log_line=f'{current_season.capitalize()} seasonal content up to date', log_type='info')
else:
print(" No active season at this time")
_update_automation_progress(automation_id,
log_line='No active season', log_type='info')
except Exception as seasonal_error:
print(f"⚠️ Error updating seasonal content: {seasonal_error}")
import traceback
traceback.print_exc()
_update_automation_progress(automation_id,
log_line=f'Seasonal error: {seasonal_error}', log_type='error')
# Add activity for watchlist scan completion
if total_added_to_wishlist > 0:

Loading…
Cancel
Save