Fix Hydrabase endpoint gaps, M3U default, and soul_id mapping
Filled all missing Hydrabase fallthrough gates across 6 endpoints (artist album tracks, iTunes album, discover album, Spotify track, both similar artists), added track_number/disc_number to Track dataclass, fixed get_album_tracks to send soul_id instead of text query, mapped soul_id field from Hydrabase responses across all search methods, updated 7 frontend call sites to pass album name/artist params, and fixed M3U export defaulting to enabled when users never turned it on.
This commit is contained in:
parent
aa176fdf9a
commit
49c769ff5c
4 changed files with 244 additions and 87 deletions
|
|
@ -160,7 +160,7 @@ class HydrabaseClient:
|
|||
for item in results[:limit]:
|
||||
try:
|
||||
tracks.append(Track(
|
||||
id=str(item.get('id', '')),
|
||||
id=str(item.get('soul_id', item.get('id', ''))),
|
||||
name=item.get('name', ''),
|
||||
artists=item.get('artists', []),
|
||||
album=item.get('album', ''),
|
||||
|
|
@ -186,7 +186,7 @@ class HydrabaseClient:
|
|||
for item in results[:limit]:
|
||||
try:
|
||||
artists.append(Artist(
|
||||
id=str(item.get('id', '')),
|
||||
id=str(item.get('soul_id', item.get('id', ''))),
|
||||
name=item.get('name', ''),
|
||||
popularity=item.get('popularity', 0),
|
||||
genres=item.get('genres', []),
|
||||
|
|
@ -209,7 +209,7 @@ class HydrabaseClient:
|
|||
for item in results[:limit]:
|
||||
try:
|
||||
albums.append(Album(
|
||||
id=str(item.get('id', '')),
|
||||
id=str(item.get('soul_id', item.get('id', ''))),
|
||||
name=item.get('name', ''),
|
||||
artists=item.get('artists', []),
|
||||
release_date=self._normalize_release_date(item.get('release_date', '')),
|
||||
|
|
@ -234,7 +234,7 @@ class HydrabaseClient:
|
|||
for item in results[:limit]:
|
||||
try:
|
||||
albums.append(Album(
|
||||
id=str(item.get('id', '')),
|
||||
id=str(item.get('soul_id', item.get('id', ''))),
|
||||
name=item.get('name', ''),
|
||||
artists=item.get('artists', []),
|
||||
release_date=self._normalize_release_date(item.get('release_date', '')),
|
||||
|
|
@ -247,9 +247,9 @@ class HydrabaseClient:
|
|||
logger.debug(f"Skipping malformed Hydrabase discography album: {e}")
|
||||
return albums
|
||||
|
||||
def get_album_tracks(self, album_query: str, limit: int = 50) -> List[Track]:
|
||||
"""Fetch tracks for an album from Hydrabase using the album_tracks type."""
|
||||
results = self._send_and_recv('album_tracks', album_query)
|
||||
def get_album_tracks(self, album_id: str, limit: int = 50) -> List[Track]:
|
||||
"""Fetch tracks for an album from Hydrabase by soul_id."""
|
||||
results = self._send_and_recv('album_tracks', album_id)
|
||||
if not results:
|
||||
return []
|
||||
|
||||
|
|
@ -257,7 +257,7 @@ class HydrabaseClient:
|
|||
for item in results[:limit]:
|
||||
try:
|
||||
tracks.append(Track(
|
||||
id=str(item.get('id', '')),
|
||||
id=str(item.get('soul_id', item.get('id', ''))),
|
||||
name=item.get('name', ''),
|
||||
artists=item.get('artists', []),
|
||||
album=item.get('album', ''),
|
||||
|
|
@ -266,7 +266,9 @@ class HydrabaseClient:
|
|||
preview_url=item.get('preview_url'),
|
||||
external_urls=item.get('external_urls'),
|
||||
image_url=item.get('image_url'),
|
||||
release_date=self._normalize_release_date(item.get('release_date', ''))
|
||||
release_date=self._normalize_release_date(item.get('release_date', '')),
|
||||
track_number=item.get('track_number'),
|
||||
disc_number=item.get('disc_number'),
|
||||
))
|
||||
except Exception as e:
|
||||
logger.debug(f"Skipping malformed Hydrabase album track: {e}")
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ class Track:
|
|||
external_urls: Optional[Dict[str, str]] = None
|
||||
image_url: Optional[str] = None
|
||||
release_date: Optional[str] = None
|
||||
track_number: Optional[int] = None
|
||||
disc_number: Optional[int] = None
|
||||
|
||||
@classmethod
|
||||
def from_itunes_track(cls, track_data: Dict[str, Any], clean_artist_name: Optional[str] = None) -> 'Track':
|
||||
|
|
|
|||
274
web_server.py
274
web_server.py
|
|
@ -2289,7 +2289,7 @@ def save_playlist_m3u():
|
|||
force = data.get('force', False)
|
||||
|
||||
# Check if M3U export is enabled (unless force=True from manual Export button)
|
||||
if not force and not config_manager.get('m3u_export.enabled', True):
|
||||
if not force and not config_manager.get('m3u_export.enabled', False):
|
||||
return jsonify({"status": "success", "message": "M3U export disabled in settings", "skipped": True})
|
||||
|
||||
if not m3u_content:
|
||||
|
|
@ -5850,32 +5850,41 @@ def get_similar_artists_stream(artist_name):
|
|||
|
||||
print(f"📦 Found {len(similar_artist_names)} similar artists from MusicMap")
|
||||
|
||||
# Initialize Spotify client
|
||||
if not spotify_client or not spotify_client.is_authenticated():
|
||||
yield f"data: {json.dumps({'error': 'Spotify not authenticated'})}\n\n"
|
||||
return
|
||||
# Determine metadata source
|
||||
use_hydrabase = _is_hydrabase_active()
|
||||
|
||||
# Get the searched artist's Spotify ID to exclude them
|
||||
if not use_hydrabase:
|
||||
if not spotify_client or not spotify_client.is_authenticated():
|
||||
yield f"data: {json.dumps({'error': 'Spotify not authenticated'})}\n\n"
|
||||
return
|
||||
|
||||
# Get the searched artist's ID to exclude them
|
||||
searched_artist_id = None
|
||||
try:
|
||||
searched_results = spotify_client.search_artists(artist_name, limit=1)
|
||||
if use_hydrabase:
|
||||
searched_results = hydrabase_client.search_artists(artist_name, limit=1)
|
||||
else:
|
||||
searched_results = spotify_client.search_artists(artist_name, limit=1)
|
||||
if searched_results and len(searched_results) > 0:
|
||||
searched_artist_id = searched_results[0].id
|
||||
print(f"🎯 Searched artist Spotify ID: {searched_artist_id}")
|
||||
print(f"🎯 Searched artist ID: {searched_artist_id}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Could not get searched artist ID: {e}")
|
||||
|
||||
# Match each artist to Spotify one by one and stream results
|
||||
# Match each artist one by one and stream results
|
||||
max_artists = 20
|
||||
matched_count = 0
|
||||
seen_artist_ids = set() # Track seen artist IDs to prevent duplicates
|
||||
|
||||
for artist_name_to_match in similar_artist_names[:max_artists]:
|
||||
try:
|
||||
print(f"🔍 Matching to Spotify: {artist_name_to_match}")
|
||||
print(f"🔍 Matching: {artist_name_to_match}")
|
||||
|
||||
# Search Spotify for the artist
|
||||
results = spotify_client.search_artists(artist_name_to_match, limit=1)
|
||||
# Search for the artist via active metadata source
|
||||
if use_hydrabase:
|
||||
results = hydrabase_client.search_artists(artist_name_to_match, limit=1)
|
||||
else:
|
||||
results = spotify_client.search_artists(artist_name_to_match, limit=1)
|
||||
|
||||
if results and len(results) > 0:
|
||||
spotify_artist = results[0]
|
||||
|
|
@ -5988,34 +5997,43 @@ def get_similar_artists(artist_name):
|
|||
|
||||
print(f"📦 Found {len(similar_artist_names)} similar artists from MusicMap")
|
||||
|
||||
# Initialize Spotify client
|
||||
if not spotify_client or not spotify_client.is_authenticated():
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Spotify not authenticated"
|
||||
}), 401
|
||||
# Determine metadata source
|
||||
use_hydrabase = _is_hydrabase_active()
|
||||
|
||||
# Get the searched artist's Spotify ID to exclude them
|
||||
if not use_hydrabase:
|
||||
if not spotify_client or not spotify_client.is_authenticated():
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Spotify not authenticated"
|
||||
}), 401
|
||||
|
||||
# Get the searched artist's ID to exclude them
|
||||
searched_artist_id = None
|
||||
try:
|
||||
searched_results = spotify_client.search_artists(artist_name, limit=1)
|
||||
if use_hydrabase:
|
||||
searched_results = hydrabase_client.search_artists(artist_name, limit=1)
|
||||
else:
|
||||
searched_results = spotify_client.search_artists(artist_name, limit=1)
|
||||
if searched_results and len(searched_results) > 0:
|
||||
searched_artist_id = searched_results[0].id
|
||||
print(f"🎯 Searched artist Spotify ID: {searched_artist_id}")
|
||||
print(f"🎯 Searched artist ID: {searched_artist_id}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Could not get searched artist ID: {e}")
|
||||
|
||||
# Match each artist to Spotify (limit to first 20 for performance)
|
||||
# Match each artist (limit to first 20 for performance)
|
||||
matched_artists = []
|
||||
max_artists = 20
|
||||
seen_artist_ids = set() # Track seen artist IDs to prevent duplicates
|
||||
|
||||
for artist_name_to_match in similar_artist_names[:max_artists]:
|
||||
try:
|
||||
print(f"🔍 Matching to Spotify: {artist_name_to_match}")
|
||||
print(f"🔍 Matching: {artist_name_to_match}")
|
||||
|
||||
# Search Spotify for the artist
|
||||
results = spotify_client.search_artists(artist_name_to_match, limit=1)
|
||||
# Search for the artist via active metadata source
|
||||
if use_hydrabase:
|
||||
results = hydrabase_client.search_artists(artist_name_to_match, limit=1)
|
||||
else:
|
||||
results = spotify_client.search_artists(artist_name_to_match, limit=1)
|
||||
|
||||
if results and len(results) > 0:
|
||||
spotify_artist = results[0]
|
||||
|
|
@ -6314,9 +6332,50 @@ def _resolve_db_album_id(album_id, artist_id=None):
|
|||
def get_artist_album_tracks(artist_id, album_id):
|
||||
"""Get tracks for specific album formatted for download missing tracks modal"""
|
||||
try:
|
||||
# Try Hydrabase first when active and album name provided
|
||||
if _is_hydrabase_active():
|
||||
album_name = request.args.get('name', '')
|
||||
album_artist = request.args.get('artist', '')
|
||||
try:
|
||||
hydra_tracks = hydrabase_client.get_album_tracks(album_id, limit=50)
|
||||
if hydra_tracks:
|
||||
album_info = {
|
||||
'id': album_id,
|
||||
'name': album_name or hydra_tracks[0].album or '',
|
||||
'image_url': None,
|
||||
'images': [],
|
||||
'release_date': '',
|
||||
'album_type': 'album',
|
||||
'total_tracks': len(hydra_tracks)
|
||||
}
|
||||
formatted_tracks = []
|
||||
for t in hydra_tracks:
|
||||
artist_list = t.artists if isinstance(t.artists, list) else [t.artists] if t.artists else []
|
||||
formatted_tracks.append({
|
||||
'id': t.id,
|
||||
'name': t.name,
|
||||
'artists': [a if isinstance(a, str) else a for a in artist_list],
|
||||
'duration_ms': t.duration_ms,
|
||||
'track_number': t.track_number or 0,
|
||||
'disc_number': t.disc_number or 1,
|
||||
'explicit': False,
|
||||
'preview_url': t.preview_url,
|
||||
'external_urls': t.external_urls or {},
|
||||
'uri': '',
|
||||
'album': album_info
|
||||
})
|
||||
print(f"✅ Hydrabase returned {len(formatted_tracks)} tracks for album: {album_info['name']}")
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'album': album_info,
|
||||
'tracks': formatted_tracks
|
||||
})
|
||||
except Exception as e:
|
||||
logger.warning(f"Hydrabase album_tracks failed for '{album_id}', falling back to Spotify: {e}")
|
||||
|
||||
if not spotify_client or not spotify_client.is_authenticated():
|
||||
return jsonify({"error": "Spotify not authenticated"}), 401
|
||||
|
||||
|
||||
print(f"🎵 Fetching tracks for album: {album_id} by artist: {artist_id}")
|
||||
|
||||
# Get album information first
|
||||
|
|
@ -17710,39 +17769,37 @@ def get_album_tracks(album_id):
|
|||
"""Fetches full track details for a specific album."""
|
||||
use_hydrabase = _is_hydrabase_active()
|
||||
|
||||
# Try Hydrabase first when active and album name provided
|
||||
# Try Hydrabase first when active — look up by album soul_id
|
||||
if use_hydrabase:
|
||||
album_name = request.args.get('name', '')
|
||||
album_artist = request.args.get('artist', '')
|
||||
if album_name:
|
||||
try:
|
||||
query = f"{album_artist} {album_name}".strip() if album_artist else album_name
|
||||
hydra_tracks = hydrabase_client.get_album_tracks(query, limit=50)
|
||||
if hydra_tracks:
|
||||
track_items = []
|
||||
for t in hydra_tracks:
|
||||
artist_list = t.artists if isinstance(t.artists, list) else [t.artists] if t.artists else []
|
||||
track_items.append({
|
||||
'name': t.name,
|
||||
'track_number': getattr(t, 'track_number', 0) or 0,
|
||||
'disc_number': getattr(t, 'disc_number', 1) or 1,
|
||||
'duration_ms': t.duration_ms,
|
||||
'id': t.id,
|
||||
'artists': [{'name': a} if isinstance(a, str) else a for a in artist_list],
|
||||
'uri': ''
|
||||
})
|
||||
return jsonify({
|
||||
'id': album_id,
|
||||
'name': album_name,
|
||||
'artists': [{'name': album_artist}] if album_artist else [],
|
||||
'release_date': '',
|
||||
'total_tracks': len(track_items),
|
||||
'album_type': 'album',
|
||||
'images': [],
|
||||
'tracks': track_items
|
||||
try:
|
||||
hydra_tracks = hydrabase_client.get_album_tracks(album_id, limit=50)
|
||||
if hydra_tracks:
|
||||
track_items = []
|
||||
for t in hydra_tracks:
|
||||
artist_list = t.artists if isinstance(t.artists, list) else [t.artists] if t.artists else []
|
||||
track_items.append({
|
||||
'name': t.name,
|
||||
'track_number': t.track_number or 0,
|
||||
'disc_number': t.disc_number or 1,
|
||||
'duration_ms': t.duration_ms,
|
||||
'id': t.id,
|
||||
'artists': [{'name': a} if isinstance(a, str) else a for a in artist_list],
|
||||
'uri': ''
|
||||
})
|
||||
except Exception as e:
|
||||
logger.warning(f"Hydrabase album_tracks failed for '{album_name}', falling back to Spotify: {e}")
|
||||
return jsonify({
|
||||
'id': album_id,
|
||||
'name': album_name or hydra_tracks[0].album or '',
|
||||
'artists': [{'name': album_artist}] if album_artist else [],
|
||||
'release_date': '',
|
||||
'total_tracks': len(track_items),
|
||||
'album_type': 'album',
|
||||
'images': [],
|
||||
'tracks': track_items
|
||||
})
|
||||
except Exception as e:
|
||||
logger.warning(f"Hydrabase album_tracks failed for '{album_id}', falling back to Spotify: {e}")
|
||||
|
||||
if not spotify_client or not spotify_client.is_authenticated():
|
||||
return jsonify({"error": "Spotify not authenticated."}), 401
|
||||
|
|
@ -17780,6 +17837,30 @@ def get_album_tracks(album_id):
|
|||
@app.route('/api/spotify/track/<track_id>', methods=['GET'])
|
||||
def get_spotify_track(track_id):
|
||||
"""Fetches full track details including album data for a specific track."""
|
||||
# Try Hydrabase first when active and track name provided
|
||||
if _is_hydrabase_active():
|
||||
track_name = request.args.get('name', '')
|
||||
track_artist = request.args.get('artist', '')
|
||||
if track_name:
|
||||
try:
|
||||
query = f"{track_artist} {track_name}".strip() if track_artist else track_name
|
||||
hydra_tracks = hydrabase_client.search_tracks(query, limit=1)
|
||||
if hydra_tracks:
|
||||
t = hydra_tracks[0]
|
||||
artist_list = t.artists if isinstance(t.artists, list) else [t.artists] if t.artists else []
|
||||
return jsonify({
|
||||
'id': t.id,
|
||||
'name': t.name,
|
||||
'artists': [{'name': a} if isinstance(a, str) else a for a in artist_list],
|
||||
'album': {'name': t.album, 'images': [{'url': t.image_url}] if t.image_url else []},
|
||||
'duration_ms': t.duration_ms,
|
||||
'preview_url': t.preview_url,
|
||||
'external_urls': t.external_urls or {},
|
||||
'popularity': t.popularity,
|
||||
})
|
||||
except Exception as e:
|
||||
logger.warning(f"Hydrabase track lookup failed for '{track_name}', falling back to Spotify: {e}")
|
||||
|
||||
if not spotify_client or not spotify_client.is_authenticated():
|
||||
return jsonify({"error": "Spotify not authenticated."}), 401
|
||||
try:
|
||||
|
|
@ -17911,6 +17992,39 @@ def search_itunes_tracks():
|
|||
def get_itunes_album_tracks(album_id):
|
||||
"""Fetches full track details for a specific iTunes album."""
|
||||
try:
|
||||
# Try Hydrabase first when active — look up by album soul_id
|
||||
if _is_hydrabase_active():
|
||||
album_name = request.args.get('name', '')
|
||||
album_artist = request.args.get('artist', '')
|
||||
try:
|
||||
hydra_tracks = hydrabase_client.get_album_tracks(album_id, limit=50)
|
||||
if hydra_tracks:
|
||||
track_items = []
|
||||
for t in hydra_tracks:
|
||||
artist_list = t.artists if isinstance(t.artists, list) else [t.artists] if t.artists else []
|
||||
track_items.append({
|
||||
'name': t.name,
|
||||
'track_number': t.track_number or 0,
|
||||
'disc_number': t.disc_number or 1,
|
||||
'duration_ms': t.duration_ms,
|
||||
'id': t.id,
|
||||
'artists': [{'name': a} if isinstance(a, str) else a for a in artist_list],
|
||||
'uri': ''
|
||||
})
|
||||
return jsonify({
|
||||
'id': album_id,
|
||||
'name': album_name or hydra_tracks[0].album or '',
|
||||
'artists': [{'name': album_artist}] if album_artist else [],
|
||||
'release_date': '',
|
||||
'total_tracks': len(track_items),
|
||||
'album_type': 'album',
|
||||
'images': [],
|
||||
'tracks': track_items,
|
||||
'source': 'hydrabase'
|
||||
})
|
||||
except Exception as e:
|
||||
logger.warning(f"Hydrabase album_tracks failed for '{album_id}', falling back to iTunes: {e}")
|
||||
|
||||
from core.itunes_client import iTunesClient
|
||||
|
||||
itunes_client = iTunesClient()
|
||||
|
|
@ -17946,9 +18060,42 @@ def get_itunes_album_tracks(album_id):
|
|||
def get_discover_album(source, album_id):
|
||||
"""
|
||||
Source-agnostic album endpoint for discover page.
|
||||
Fetches album from the appropriate source (spotify or itunes).
|
||||
Fetches album from the appropriate source (spotify, itunes, or hydrabase when active).
|
||||
"""
|
||||
try:
|
||||
# Try Hydrabase first when active — look up by album soul_id
|
||||
if _is_hydrabase_active():
|
||||
album_name = request.args.get('name', '')
|
||||
album_artist = request.args.get('artist', '')
|
||||
try:
|
||||
hydra_tracks = hydrabase_client.get_album_tracks(album_id, limit=50)
|
||||
if hydra_tracks:
|
||||
track_items = []
|
||||
for t in hydra_tracks:
|
||||
artist_list = t.artists if isinstance(t.artists, list) else [t.artists] if t.artists else []
|
||||
track_items.append({
|
||||
'name': t.name,
|
||||
'track_number': t.track_number or 0,
|
||||
'disc_number': t.disc_number or 1,
|
||||
'duration_ms': t.duration_ms,
|
||||
'id': t.id,
|
||||
'artists': [{'name': a} if isinstance(a, str) else a for a in artist_list],
|
||||
'uri': ''
|
||||
})
|
||||
return jsonify({
|
||||
'id': album_id,
|
||||
'name': album_name or hydra_tracks[0].album or '',
|
||||
'artists': [{'name': album_artist}] if album_artist else [],
|
||||
'release_date': '',
|
||||
'total_tracks': len(track_items),
|
||||
'album_type': 'album',
|
||||
'images': [],
|
||||
'tracks': track_items,
|
||||
'source': 'hydrabase'
|
||||
})
|
||||
except Exception as e:
|
||||
logger.warning(f"Hydrabase album_tracks failed for '{album_id}', falling back to {source}: {e}")
|
||||
|
||||
if source == 'spotify':
|
||||
if not spotify_client or not spotify_client.is_authenticated():
|
||||
return jsonify({"error": "Spotify not authenticated."}), 401
|
||||
|
|
@ -28231,19 +28378,18 @@ def import_album_match():
|
|||
spotify_tracks = None
|
||||
album_info = None
|
||||
|
||||
# Try Hydrabase first when active and album_name available
|
||||
if _is_hydrabase_active() and album_name:
|
||||
# Try Hydrabase first when active — look up by album soul_id
|
||||
if _is_hydrabase_active():
|
||||
try:
|
||||
query = f"{album_artist} {album_name}".strip() if album_artist else album_name
|
||||
hydra_tracks = hydrabase_client.get_album_tracks(query, limit=50)
|
||||
hydra_tracks = hydrabase_client.get_album_tracks(album_id, limit=50)
|
||||
if hydra_tracks:
|
||||
spotify_tracks = []
|
||||
for t in hydra_tracks:
|
||||
artist_list = t.artists if isinstance(t.artists, list) else [t.artists] if t.artists else []
|
||||
spotify_tracks.append({
|
||||
'name': t.name,
|
||||
'track_number': getattr(t, 'track_number', 0) or 0,
|
||||
'disc_number': getattr(t, 'disc_number', 1) or 1,
|
||||
'track_number': t.track_number or 0,
|
||||
'disc_number': t.disc_number or 1,
|
||||
'duration_ms': t.duration_ms,
|
||||
'id': t.id,
|
||||
'artists': [{'name': a} if isinstance(a, str) else a for a in artist_list],
|
||||
|
|
@ -28251,7 +28397,7 @@ def import_album_match():
|
|||
})
|
||||
album_info = {
|
||||
'id': album_id,
|
||||
'name': album_name,
|
||||
'name': album_name or hydra_tracks[0].album or '',
|
||||
'artist': album_artist,
|
||||
'artists': [album_artist] if album_artist else [],
|
||||
'release_date': '',
|
||||
|
|
@ -28259,7 +28405,7 @@ def import_album_match():
|
|||
'image_url': None,
|
||||
'genres': []
|
||||
}
|
||||
logger.info(f"Hydrabase album_tracks returned {len(spotify_tracks)} tracks for '{query}'")
|
||||
logger.info(f"Hydrabase album_tracks returned {len(spotify_tracks)} tracks for album_id '{album_id}'")
|
||||
except Exception as e:
|
||||
logger.warning(f"Hydrabase album_tracks failed, falling back to Spotify: {e}")
|
||||
spotify_tracks = None
|
||||
|
|
|
|||
|
|
@ -4307,11 +4307,12 @@ async function rehydrateEnhancedSearchModal(virtualPlaylistId, playlistName, bat
|
|||
const { item, type } = downloadData;
|
||||
|
||||
if (type === 'album') {
|
||||
// For albums, fetch tracks from Spotify API
|
||||
// For albums, fetch tracks (pass name/artist for Hydrabase support)
|
||||
console.log(`💧 Album download - fetching album ${item.id}...`);
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/spotify/album/${item.id}`);
|
||||
const _sap1 = new URLSearchParams({ name: item.name || '', artist: item.artist || '' });
|
||||
const response = await fetch(`/api/spotify/album/${item.id}?${_sap1}`);
|
||||
if (!response.ok) {
|
||||
console.error(`❌ Failed to fetch album: ${response.status}`);
|
||||
return;
|
||||
|
|
@ -13307,10 +13308,11 @@ async function confirmMatch() {
|
|||
console.log('🎵 Fetching Spotify tracklist for album:', currentMatchingData.selectedAlbum.name);
|
||||
|
||||
try {
|
||||
// Fetch Spotify album tracks
|
||||
// Fetch album tracks (pass name/artist for Hydrabase support)
|
||||
const artistId = currentMatchingData.selectedArtist.id;
|
||||
const albumId = currentMatchingData.selectedAlbum.id;
|
||||
const tracksResponse = await fetch(`/api/artist/${artistId}/album/${albumId}/tracks`);
|
||||
const _aat3 = new URLSearchParams({ name: currentMatchingData.selectedAlbum.name || '', artist: currentMatchingData.selectedArtist.name || '' });
|
||||
const tracksResponse = await fetch(`/api/artist/${artistId}/album/${albumId}/tracks?${_aat3}`);
|
||||
|
||||
if (!tracksResponse.ok) {
|
||||
throw new Error(`Failed to fetch Spotify tracks: ${tracksResponse.status}`);
|
||||
|
|
@ -23289,8 +23291,9 @@ async function createArtistAlbumVirtualPlaylist(album, albumType) {
|
|||
try {
|
||||
// Loading overlay already shown by handleArtistAlbumClick
|
||||
|
||||
// Fetch album tracks from backend
|
||||
const response = await fetch(`/api/artist/${artist.id}/album/${album.id}/tracks`);
|
||||
// Fetch album tracks from backend (pass name/artist for Hydrabase support)
|
||||
const _aat1 = new URLSearchParams({ name: album.name || '', artist: artist.name || '' });
|
||||
const response = await fetch(`/api/artist/${artist.id}/album/${album.id}/tracks?${_aat1}`);
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
|
|
@ -24148,11 +24151,12 @@ async function reopenDownloadModal(virtualPlaylistId) {
|
|||
// For albums, we need to fetch the tracks
|
||||
console.log(`📥 [REOPEN] Recreating album modal for: ${item.name}`);
|
||||
|
||||
// Fetch album tracks from Spotify API
|
||||
// Fetch album tracks (pass name/artist for Hydrabase support)
|
||||
showLoadingOverlay(`Loading ${item.name}...`);
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/spotify/album/${item.id}`);
|
||||
const _sap2 = new URLSearchParams({ name: item.name || '', artist: item.artist || '' });
|
||||
const response = await fetch(`/api/spotify/album/${item.id}?${_sap2}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch album tracks');
|
||||
}
|
||||
|
|
@ -28127,8 +28131,9 @@ function createReleaseCard(release) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Load tracks for the album
|
||||
const response = await fetch(`/api/artist/${currentArtist.id}/album/${albumData.id}/tracks`);
|
||||
// Load tracks for the album (pass name/artist for Hydrabase support)
|
||||
const _aat2 = new URLSearchParams({ name: albumData.name || '', artist: currentArtist.name || '' });
|
||||
const response = await fetch(`/api/artist/${currentArtist.id}/album/${albumData.id}/tracks?${_aat2}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to load album tracks: ${response.status}`);
|
||||
}
|
||||
|
|
@ -35380,8 +35385,9 @@ async function openDownloadModalForSeasonalAlbum(albumIndex) {
|
|||
throw new Error('No album ID available');
|
||||
}
|
||||
|
||||
// Fetch album tracks from appropriate source via backend
|
||||
const response = await fetch(`/api/discover/album/${source}/${albumId}`);
|
||||
// Fetch album tracks from appropriate source (pass name/artist for Hydrabase support)
|
||||
const _dap1 = new URLSearchParams({ name: album.album_name || '', artist: album.artist_name || '' });
|
||||
const response = await fetch(`/api/discover/album/${source}/${albumId}?${_dap1}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch album tracks');
|
||||
}
|
||||
|
|
@ -36291,8 +36297,9 @@ async function openDownloadModalForRecentAlbum(albumIndex) {
|
|||
throw new Error(`No ${source} album ID available`);
|
||||
}
|
||||
|
||||
// Fetch album tracks from appropriate source via backend
|
||||
const response = await fetch(`/api/discover/album/${source}/${albumId}`);
|
||||
// Fetch album tracks from appropriate source (pass name/artist for Hydrabase support)
|
||||
const _dap2 = new URLSearchParams({ name: album.album_name || '', artist: album.artist_name || '' });
|
||||
const response = await fetch(`/api/discover/album/${source}/${albumId}?${_dap2}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch album tracks');
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue