Added scoring

This commit is contained in:
Connor Johnstone
2026-03-02 22:42:30 -05:00
parent 6a16cb1395
commit c3b4c946cb
3 changed files with 169 additions and 13 deletions

View File

@@ -12,6 +12,13 @@ pub struct SimilarArtist {
pub match_score: f64,
}
pub struct TopTrack {
pub name: String,
pub mbid: Option<String>,
pub playcount: u64,
pub listeners: u64,
}
// Last.fm returns {"error": N, "message": "..."} on failure
#[derive(Deserialize)]
struct ApiError {
@@ -40,6 +47,24 @@ struct ArtistEntry {
match_score: String,
}
#[derive(Deserialize)]
struct TopTracksResponse {
toptracks: TopTracksWrapper,
}
#[derive(Deserialize)]
struct TopTracksWrapper {
track: Vec<TrackEntry>,
}
#[derive(Deserialize)]
struct TrackEntry {
name: String,
mbid: Option<String>,
playcount: String,
listeners: String,
}
impl LastfmClient {
pub fn new(api_key: String) -> Self {
Self { api_key }
@@ -75,4 +100,33 @@ impl LastfmClient {
})
.collect())
}
pub fn get_top_tracks(
&self,
artist_mbid: &str,
) -> Result<Vec<TopTrack>, Box<dyn std::error::Error>> {
let url = format!(
"{}?method=artist.getTopTracks&mbid={}&api_key={}&limit=1000&format=json",
BASE_URL, artist_mbid, self.api_key
);
let body: String = ureq::get(&url).call()?.body_mut().read_to_string()?;
if let Ok(err) = serde_json::from_str::<ApiError>(&body) {
eprintln!(" Last.fm: {}", err.message);
return Ok(Vec::new());
}
let resp: TopTracksResponse = serde_json::from_str(&body)?;
Ok(resp
.toptracks
.track
.into_iter()
.map(|t| TopTrack {
name: t.name,
mbid: t.mbid.filter(|s| !s.is_empty()),
playcount: t.playcount.parse().unwrap_or(0),
listeners: t.listeners.parse().unwrap_or(0),
})
.collect())
}
}