update liked songs to include album info

This commit is contained in:
Broque Thomas 2025-11-24 07:19:15 -08:00
parent c46e2c527e
commit 178bb7696d
2 changed files with 110 additions and 26 deletions

View file

@ -11983,10 +11983,38 @@ def get_playlist_tracks(playlist_id):
try:
# Handle special "Liked Songs" virtual playlist
if playlist_id == "spotify:liked-songs":
saved_tracks = spotify_client.get_saved_tracks()
user_info = spotify_client.get_user_info()
owner_name = user_info.get('display_name', 'You') if user_info else 'You'
# Fetch raw saved tracks with full album data
tracks = []
limit = 50
offset = 0
while True:
results = spotify_client.sp.current_user_saved_tracks(limit=limit, offset=offset)
if not results or 'items' not in results:
break
for item in results['items']:
if item['track'] and item['track']['id']:
track_data = item['track']
tracks.append({
'id': track_data['id'],
'name': track_data['name'],
'artists': [artist['name'] for artist in track_data['artists']],
'album': track_data['album'], # Full album object
'duration_ms': track_data['duration_ms'],
'popularity': track_data.get('popularity', 0),
'spotify_track_id': track_data['id']
})
if len(results['items']) < limit or not results.get('next'):
break
offset += limit
# Create virtual playlist dict for Liked Songs
playlist_dict = {
'id': 'spotify:liked-songs',
@ -11995,31 +12023,49 @@ def get_playlist_tracks(playlist_id):
'owner': owner_name,
'public': False,
'collaborative': False,
'track_count': len(saved_tracks),
'track_count': len(tracks),
'image_url': None,
'snapshot_id': '',
'tracks': [{'id': t.id, 'name': t.name, 'artists': t.artists, 'album': t.album, 'duration_ms': t.duration_ms, 'popularity': t.popularity} for t in saved_tracks]
'tracks': tracks
}
return jsonify(playlist_dict)
# Handle regular playlists
# This reuses the robust track fetching logic from your GUI's sync.py
full_playlist = spotify_client.get_playlist_by_id(playlist_id)
if not full_playlist:
return jsonify({})
# Fetch raw playlist data to preserve full album objects
playlist_data = spotify_client.sp.playlist(playlist_id)
# Convert playlist to dict manually since core class doesn't have to_dict method
# Fetch all tracks with full album data
tracks = []
results = spotify_client.sp.playlist_tracks(playlist_id, limit=100)
while results:
for item in results['items']:
if item['track'] and item['track']['id']:
track_data = item['track']
tracks.append({
'id': track_data['id'],
'name': track_data['name'],
'artists': [artist['name'] for artist in track_data['artists']],
'album': track_data['album'], # Full album object with album_type, total_tracks, etc.
'duration_ms': track_data['duration_ms'],
'popularity': track_data.get('popularity', 0),
'spotify_track_id': track_data['id'] # Also include as spotify_track_id for consistency
})
results = spotify_client.sp.next(results) if results['next'] else None
# Convert playlist to dict
playlist_dict = {
'id': full_playlist.id,
'name': full_playlist.name,
'description': full_playlist.description,
'owner': full_playlist.owner,
'public': full_playlist.public,
'collaborative': full_playlist.collaborative,
'track_count': full_playlist.total_tracks,
'image_url': getattr(full_playlist, 'image_url', None),
'snapshot_id': getattr(full_playlist, 'snapshot_id', ''),
'tracks': [{'id': t.id, 'name': t.name, 'artists': t.artists, 'album': t.album, 'duration_ms': t.duration_ms, 'popularity': t.popularity} for t in full_playlist.tracks]
'id': playlist_data['id'],
'name': playlist_data['name'],
'description': playlist_data.get('description', ''),
'owner': playlist_data['owner']['display_name'],
'public': playlist_data.get('public', False),
'collaborative': playlist_data.get('collaborative', False),
'track_count': len(tracks),
'image_url': playlist_data['images'][0]['url'] if playlist_data.get('images') else None,
'snapshot_id': playlist_data.get('snapshot_id', ''),
'tracks': tracks
}
return jsonify(playlist_dict)
except Exception as e:
@ -12053,6 +12099,21 @@ def get_album_tracks(album_id):
return jsonify({"error": str(e)}), 500
@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."""
if not spotify_client or not spotify_client.is_authenticated():
return jsonify({"error": "Spotify not authenticated."}), 401
try:
track_data = spotify_client.get_track_details(track_id)
if not track_data:
return jsonify({"error": "Track not found"}), 404
return jsonify(track_data)
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/api/spotify/search_tracks', methods=['GET'])
def search_spotify_tracks():
"""Search for tracks on Spotify - used by discovery fix modal"""

View file

@ -8808,15 +8808,38 @@ async function addModalTracksToWishlist(playlistId) {
};
// Use track's own album data if available (has correct album_type)
// Don't fall back to process album/playlist if track has no album
// (better to skip than add with wrong data)
if (!track.album || !track.album.name) {
console.warn(`⚠️ Skipping track "${track.name}" - missing album data`);
continue;
}
// If missing, fetch from Spotify using track ID
let trackAlbum = track.album;
let trackAlbumType = track.album?.album_type || 'album';
const trackAlbum = track.album;
const trackAlbumType = track.album.album_type || 'album';
if (!trackAlbum || !trackAlbum.name) {
// Try to fetch track data from Spotify to get album info
if (track.spotify_track_id || track.id) {
try {
const spotifyTrackId = track.spotify_track_id || track.id;
const trackInfoResponse = await fetch(`/api/spotify/track/${spotifyTrackId}`);
const trackInfo = await trackInfoResponse.json();
if (trackInfo && trackInfo.album) {
trackAlbum = trackInfo.album;
trackAlbumType = trackInfo.album.album_type || 'album';
console.log(`✅ Fetched album data for "${track.name}"`);
} else {
console.warn(`⚠️ Skipping track "${track.name}" - could not fetch album data`);
errorCount++;
continue;
}
} catch (fetchError) {
console.error(`❌ Error fetching track data for "${track.name}":`, fetchError);
errorCount++;
continue;
}
} else {
console.warn(`⚠️ Skipping track "${track.name}" - missing album data and track ID`);
errorCount++;
continue;
}
}
const response = await fetch('/api/add-album-to-wishlist', {
method: 'POST',