update liked songs to include album info
This commit is contained in:
parent
c46e2c527e
commit
178bb7696d
2 changed files with 110 additions and 26 deletions
|
|
@ -11983,10 +11983,38 @@ def get_playlist_tracks(playlist_id):
|
||||||
try:
|
try:
|
||||||
# Handle special "Liked Songs" virtual playlist
|
# Handle special "Liked Songs" virtual playlist
|
||||||
if playlist_id == "spotify:liked-songs":
|
if playlist_id == "spotify:liked-songs":
|
||||||
saved_tracks = spotify_client.get_saved_tracks()
|
|
||||||
user_info = spotify_client.get_user_info()
|
user_info = spotify_client.get_user_info()
|
||||||
owner_name = user_info.get('display_name', 'You') if user_info else 'You'
|
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
|
# Create virtual playlist dict for Liked Songs
|
||||||
playlist_dict = {
|
playlist_dict = {
|
||||||
'id': 'spotify:liked-songs',
|
'id': 'spotify:liked-songs',
|
||||||
|
|
@ -11995,31 +12023,49 @@ def get_playlist_tracks(playlist_id):
|
||||||
'owner': owner_name,
|
'owner': owner_name,
|
||||||
'public': False,
|
'public': False,
|
||||||
'collaborative': False,
|
'collaborative': False,
|
||||||
'track_count': len(saved_tracks),
|
'track_count': len(tracks),
|
||||||
'image_url': None,
|
'image_url': None,
|
||||||
'snapshot_id': '',
|
'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)
|
return jsonify(playlist_dict)
|
||||||
|
|
||||||
# Handle regular playlists
|
# Handle regular playlists
|
||||||
# This reuses the robust track fetching logic from your GUI's sync.py
|
# Fetch raw playlist data to preserve full album objects
|
||||||
full_playlist = spotify_client.get_playlist_by_id(playlist_id)
|
playlist_data = spotify_client.sp.playlist(playlist_id)
|
||||||
if not full_playlist:
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
# 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 = {
|
playlist_dict = {
|
||||||
'id': full_playlist.id,
|
'id': playlist_data['id'],
|
||||||
'name': full_playlist.name,
|
'name': playlist_data['name'],
|
||||||
'description': full_playlist.description,
|
'description': playlist_data.get('description', ''),
|
||||||
'owner': full_playlist.owner,
|
'owner': playlist_data['owner']['display_name'],
|
||||||
'public': full_playlist.public,
|
'public': playlist_data.get('public', False),
|
||||||
'collaborative': full_playlist.collaborative,
|
'collaborative': playlist_data.get('collaborative', False),
|
||||||
'track_count': full_playlist.total_tracks,
|
'track_count': len(tracks),
|
||||||
'image_url': getattr(full_playlist, 'image_url', None),
|
'image_url': playlist_data['images'][0]['url'] if playlist_data.get('images') else None,
|
||||||
'snapshot_id': getattr(full_playlist, 'snapshot_id', ''),
|
'snapshot_id': playlist_data.get('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]
|
'tracks': tracks
|
||||||
}
|
}
|
||||||
return jsonify(playlist_dict)
|
return jsonify(playlist_dict)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -12053,6 +12099,21 @@ def get_album_tracks(album_id):
|
||||||
return jsonify({"error": str(e)}), 500
|
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'])
|
@app.route('/api/spotify/search_tracks', methods=['GET'])
|
||||||
def search_spotify_tracks():
|
def search_spotify_tracks():
|
||||||
"""Search for tracks on Spotify - used by discovery fix modal"""
|
"""Search for tracks on Spotify - used by discovery fix modal"""
|
||||||
|
|
|
||||||
|
|
@ -8808,15 +8808,38 @@ async function addModalTracksToWishlist(playlistId) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use track's own album data if available (has correct album_type)
|
// 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
|
// If missing, fetch from Spotify using track ID
|
||||||
// (better to skip than add with wrong data)
|
let trackAlbum = track.album;
|
||||||
if (!track.album || !track.album.name) {
|
let trackAlbumType = track.album?.album_type || 'album';
|
||||||
console.warn(`⚠️ Skipping track "${track.name}" - missing album data`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const trackAlbum = track.album;
|
if (!trackAlbum || !trackAlbum.name) {
|
||||||
const trackAlbumType = track.album.album_type || 'album';
|
// 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', {
|
const response = await fetch('/api/add-album-to-wishlist', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue