Added last.fm support

This commit is contained in:
Connor Johnstone
2026-03-02 21:46:39 -05:00
parent 8a07a3edc2
commit 16e8962be1
6 changed files with 516 additions and 23 deletions

View File

@@ -1,25 +1,47 @@
use std::path::Path;
use lofty::file::TaggedFileExt;
use lofty::tag::Accessor;
use lofty::tag::{ItemKey, ItemValue};
pub struct TrackMetadata {
pub title: Option<String>,
pub artist: Option<String>,
pub album: Option<String>,
/// A single key-value metadata item from a tag.
pub struct TagEntry {
pub key: String,
pub value: String,
}
/// Read metadata from a music file, returning `None` if no tags are present.
pub fn read_track_metadata(path: &Path) -> Result<Option<TrackMetadata>, lofty::error::LoftyError> {
/// Read all metadata items from a music file.
/// Returns `None` if no tags are present, otherwise a list of all tag entries.
pub fn read_all_metadata(path: &Path) -> Result<Option<Vec<TagEntry>>, lofty::error::LoftyError> {
let tagged_file = lofty::read_from_path(path)?;
let Some(tag) = tagged_file.primary_tag().or_else(|| tagged_file.first_tag()) else {
return Ok(None);
};
Ok(Some(TrackMetadata {
title: tag.title().map(|s| s.into_owned()),
artist: tag.artist().map(|s| s.into_owned()),
album: tag.album().map(|s| s.into_owned()),
}))
let entries = tag
.items()
.filter_map(|item| {
let value = match item.value() {
ItemValue::Text(t) | ItemValue::Locator(t) => t.clone(),
ItemValue::Binary(b) => format!("<{} bytes>", b.len()),
};
Some(TagEntry {
key: format!("{:?}", item.key()),
value,
})
})
.collect();
Ok(Some(entries))
}
/// Extract the MusicBrainz artist ID from a music file.
pub fn read_artist_mbid(path: &Path) -> Result<Option<String>, lofty::error::LoftyError> {
let tagged_file = lofty::read_from_path(path)?;
let Some(tag) = tagged_file.primary_tag().or_else(|| tagged_file.first_tag()) else {
return Ok(None);
};
Ok(tag.get_string(ItemKey::MusicBrainzArtistId).map(String::from))
}