diff --git a/src/encoder/tags.rs b/src/encoder/tags.rs index 9a861a2..f7dde66 100644 --- a/src/encoder/tags.rs +++ b/src/encoder/tags.rs @@ -11,6 +11,7 @@ pub struct Tags { pub artists: Vec, pub album_title: String, pub album_cover: Option, + pub position: Option, } pub async fn store_tags(path: String, tags: &Tags, format: Format) -> Result<()> { @@ -34,6 +35,10 @@ pub async fn store_tags(path: String, tags: &Tags, format: Format) -> Result<()> tag.set_artist(&artists); tag.set_album_title(&tags.album_title); + if let Some(track_number) = &tags.position { + tag.set_track_number(*track_number as u16); + } + if let Some(cover) = &tags.album_cover { tag.set_album_cover(Picture::new( cover.as_ref(), diff --git a/src/track.rs b/src/track.rs index f6d3630..b7ccd33 100644 --- a/src/track.rs +++ b/src/track.rs @@ -70,6 +70,7 @@ fn parse_url(track_url: &str) -> Option { #[derive(Clone, Debug)] pub struct Track { pub id: SpotifyId, + pub position: Option, } lazy_static! { @@ -80,11 +81,15 @@ lazy_static! { impl Track { pub fn new(track: &str) -> Result { let id = parse_uri_or_url(track).ok_or(anyhow::anyhow!("Invalid track"))?; - Ok(Track { id }) + Ok(Track { id, position: None }) } pub fn from_id(id: SpotifyId) -> Self { - Track { id } + Track { id, position: None } + } + + pub fn from_id_with_position(id: SpotifyId, position: usize) -> Self { + Track { id, position: Some(position) } } pub async fn metadata(&self, session: &Session) -> Result { @@ -118,10 +123,13 @@ impl Track { }) }); + let position = self.position.or(Some(metadata.number as usize)); + Ok(TrackMetadata::from( metadata, artists, album, + position, image_retriever, )) } @@ -190,9 +198,11 @@ impl TrackCollection for Playlist { let playlist = librespot::metadata::Playlist::get(session, &self.id) .await .expect("Failed to get playlist"); + playlist .tracks() - .map(|track| Track::from_id(*track)) + .enumerate() + .map(|(i, track)| Track::from_id_with_position(*track, i + 1)) .collect() } } @@ -203,6 +213,7 @@ pub struct TrackMetadata { pub track_name: String, pub album: AlbumMetadata, pub duration: i32, + pub position: Option, image_retriever: AsyncFn, } @@ -211,6 +222,7 @@ impl TrackMetadata { track: librespot::metadata::Track, artists: Vec, album: librespot::metadata::Album, + position: Option, image_retriever: AsyncFn, ) -> Self { let artists = artists @@ -224,6 +236,7 @@ impl TrackMetadata { track_name: track.name.clone(), album, duration: track.duration, + position, image_retriever, } } @@ -243,6 +256,7 @@ impl TrackMetadata { artists: self.artists.iter().map(|a| a.name.clone()).collect(), album_title: self.album.name.clone(), album_cover: (self.image_retriever)().await, + position: self.position, }; Ok(tags) } @@ -250,6 +264,8 @@ impl TrackMetadata { impl ToString for TrackMetadata { fn to_string(&self) -> String { + let position_string = self.position.map_or(String::from(""), |i| format!("{:02}: ", i)); + if self.artists.len() > 3 { let artists_name = self .artists @@ -259,8 +275,8 @@ impl ToString for TrackMetadata { .collect::>() .join(", "); return clean_invalid_characters(format!( - "{}, ... - {}", - artists_name, self.track_name + "{}{}, ... - {}", + position_string, artists_name, self.track_name )); } @@ -270,7 +286,7 @@ impl ToString for TrackMetadata { .map(|artist| artist.name.clone()) .collect::>() .join(", "); - clean_invalid_characters(format!("{} - {}", artists_name, self.track_name)) + clean_invalid_characters(format!("{}{} - {}", position_string, artists_name, self.track_name)) } }