diff --git a/core/spotify_client.py b/core/spotify_client.py index f06ff955..aee617a5 100644 --- a/core/spotify_client.py +++ b/core/spotify_client.py @@ -955,7 +955,8 @@ class SpotifyClient: if use_spotify: # Check Spotify cache - cached_results = cache.get_search_results('spotify', 'track', query, min(limit, 10)) + effective_limit = min(limit, 50) # Spotify API max is 50 + cached_results = cache.get_search_results('spotify', 'track', query, effective_limit) if cached_results is not None: tracks = [] for raw in cached_results: @@ -967,7 +968,7 @@ class SpotifyClient: return tracks try: - results = self.sp.search(q=query, type='track', limit=min(limit, 10)) + results = self.sp.search(q=query, type='track', limit=effective_limit) tracks = [] raw_items = results['tracks']['items'] @@ -979,7 +980,7 @@ class SpotifyClient: entries = [(td.get('id'), td) for td in raw_items if td.get('id')] if entries: cache.store_entities_bulk('spotify', 'track', entries) - cache.store_search_results('spotify', 'track', query, min(limit, 10), + cache.store_search_results('spotify', 'track', query, effective_limit, [td.get('id') for td in raw_items if td.get('id')]) return tracks diff --git a/web_server.py b/web_server.py index 0f5ad099..d89a706a 100644 --- a/web_server.py +++ b/web_server.py @@ -25069,10 +25069,23 @@ def search_spotify_tracks(): return jsonify({"error": "Spotify not authenticated."}), 401 try: - query = request.args.get('query', '').strip() + # Support field-specific search params (track, artist) or legacy combined query + track_q = request.args.get('track', '').strip() + artist_q = request.args.get('artist', '').strip() + legacy_query = request.args.get('query', '').strip() limit = int(request.args.get('limit', 20)) - if not query: + # Build Spotify field-filtered query + if track_q or artist_q: + parts = [] + if track_q: + parts.append(f'track:{track_q}') + if artist_q: + parts.append(f'artist:{artist_q}') + query = ' '.join(parts) + elif legacy_query: + query = legacy_query + else: return jsonify({"error": "Query parameter is required"}), 400 if use_hydrabase: @@ -25101,10 +25114,22 @@ def search_spotify_tracks(): def search_itunes_tracks(): """Search for tracks on iTunes - used by discovery fix modal when iTunes is the source""" try: - query = request.args.get('query', '').strip() + # Support field-specific search params or legacy combined query + track_q = request.args.get('track', '').strip() + artist_q = request.args.get('artist', '').strip() + legacy_query = request.args.get('query', '').strip() limit = int(request.args.get('limit', 20)) - if not query: + if track_q or artist_q: + parts = [] + if track_q: + parts.append(track_q) + if artist_q: + parts.append(artist_q) + query = ' '.join(parts) + elif legacy_query: + query = legacy_query + else: return jsonify({"error": "Query parameter is required"}), 400 use_hydrabase = _is_hydrabase_active() diff --git a/webui/static/script.js b/webui/static/script.js index 8991af5b..803abeeb 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -15392,12 +15392,19 @@ async function searchDiscoveryFix() { resultsContainer.innerHTML = `
🔍 Searching ${sourceLabel}...
`; try { - // Build search query - const query = `${artistInput} ${trackInput}`.trim(); + // Build search params — send track and artist separately for field-specific filtering + const params = new URLSearchParams(); + if (trackInput) params.set('track', trackInput); + if (artistInput) params.set('artist', artistInput); + if (!trackInput && !artistInput) { + resultsContainer.innerHTML = '
Enter a track name or artist.
'; + return; + } + params.set('limit', '50'); // Call appropriate search API based on discovery source const searchEndpoint = useFallback ? '/api/itunes/search_tracks' : '/api/spotify/search_tracks'; - const response = await fetch(`${searchEndpoint}?query=${encodeURIComponent(query)}&limit=20`); + const response = await fetch(`${searchEndpoint}?${params.toString()}`); const data = await response.json(); if (data.error) { @@ -55496,8 +55503,9 @@ async function searchPoolFix() { const resultsContainer = document.getElementById('pool-fix-results'); if (!trackInput || !resultsContainer) return; - const query = `${artistInput.value.trim()} ${trackInput.value.trim()}`.trim(); - if (!query) { + const trackVal = trackInput.value.trim(); + const artistVal = artistInput.value.trim(); + if (!trackVal && !artistVal) { resultsContainer.innerHTML = '
Enter a search term
'; return; } @@ -55505,7 +55513,11 @@ async function searchPoolFix() { resultsContainer.innerHTML = '
Searching...
'; try { - const res = await fetch(`/api/spotify/search_tracks?query=${encodeURIComponent(query)}&limit=20`); + const params = new URLSearchParams(); + if (trackVal) params.set('track', trackVal); + if (artistVal) params.set('artist', artistVal); + params.set('limit', '50'); + const res = await fetch(`/api/spotify/search_tracks?${params.toString()}`); const data = await res.json(); const tracks = data.tracks || [];