spotify: search_tracks() free-form con limit configurabile

This commit is contained in:
luciano committed 2026-07-14 17:14:02 +02:00
1 parent 58d4896ffe
commit 252d76b907
2 files changed
+111

No files matched your search

+34
View File
@@ -280,3 +280,37 @@ def search_track(token: str, query: str):
"name": t.get("name", ""),
"artists": ", ".join(a.get("name", "") for a in t.get("artists", [])),
}
def search_tracks(token: str, query: str, limit: int = 50) -> list:
"""Cerca brani su Spotify e ritorna una lista di dict.
Args:
token: access token Spotify
query: query libera (titolo, artista, misto)
limit: max risultati (Spotify cap = 50)
Returns:
list[dict] con {id, url, name, artists, album, duration_sec}. Vuota se nessun match.
"""
resp = requests.get(
"https://api.spotify.com/v1/search",
headers={"Authorization": f"Bearer {token}"},
params={"q": query, "type": "track", "limit": min(limit, 50)},
timeout=15,
)
resp.raise_for_status()
items = resp.json().get("tracks", {}).get("items", [])
return [_track_to_dict(t) for t in items]
def _track_to_dict(t: dict) -> dict:
"""Mappa il track object Spotify sul nostro schema uniforme."""
return {
"id": t.get("id", ""),
"url": t.get("external_urls", {}).get("spotify", ""),
"name": t.get("name", ""),
"artists": ", ".join(a.get("name", "") for a in t.get("artists", [])),
"album": t.get("album", {}).get("name", ""),
"duration_sec": int(t.get("duration_ms", 0)) // 1000,
}
+77
View File
@@ -68,3 +68,80 @@ class TestSearchTrack:
assert params["q"] == "Kapuchon Hot Sauce"
assert params["type"] == "track"
assert params["limit"] == "1"
class TestSearchTracks:
@responses.activate
def test_returns_list_of_tracks(self):
responses.add(
responses.GET,
"https://api.spotify.com/v1/search",
json={
"tracks": {
"items": [
{
"id": f"id{i}",
"name": f"Track {i}",
"artists": [{"name": "Solomun"}],
"album": {"name": "Album X"},
"duration_ms": 300000 + i * 1000,
"external_urls": {"spotify": f"https://open.spotify.com/track/id{i}"},
}
for i in range(50)
]
}
},
status=200,
)
result = spotify_client.search_tracks("t", "solomun", limit=50)
assert isinstance(result, list)
assert len(result) == 50
first = result[0]
assert first["id"] == "id0"
assert first["name"] == "Track 0"
assert first["artists"] == "Solomun"
assert first["album"] == "Album X"
assert first["duration_sec"] == 300
assert first["url"] == "https://open.spotify.com/track/id0"
@responses.activate
def test_multiple_artists_joined_with_comma(self):
responses.add(
responses.GET,
"https://api.spotify.com/v1/search",
json={"tracks": {"items": [{
"id": "x", "name": "n",
"artists": [{"name": "A"}, {"name": "B"}, {"name": "C"}],
"album": {"name": "Alb"},
"duration_ms": 60000,
"external_urls": {"spotify": "u"},
}]}},
status=200,
)
result = spotify_client.search_tracks("t", "q", limit=1)
assert result[0]["artists"] == "A, B, C"
@responses.activate
def test_empty_query_returns_empty_list(self):
responses.add(
responses.GET,
"https://api.spotify.com/v1/search",
json={"tracks": {"items": []}},
status=200,
)
result = spotify_client.search_tracks("t", "no-match", limit=50)
assert result == []
@responses.activate
def test_query_params_include_limit(self):
responses.add(
responses.GET,
"https://api.spotify.com/v1/search",
json={"tracks": {"items": []}},
status=200,
)
spotify_client.search_tracks("t", "q", limit=25)
params = responses.calls[0].request.params
assert params["q"] == "q"
assert params["type"] == "track"
assert params["limit"] == "25"