From 7a259ccc4bf2b6c4c2b9750b7513e67e153c8bbf Mon Sep 17 00:00:00 2001 From: George Hahn Date: Mon, 2 Jan 2023 16:24:49 -0700 Subject: [PATCH] Parse named ID URIs --- CHANGELOG.md | 1 + core/src/spotify_id.rs | 32 +++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54eaf48b..8007f93e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -85,6 +85,7 @@ https://github.com/librespot-org/librespot downloads even if librespot doesn't use that for playback itself. - [core] Support downloading of lyrics - [core] Support parsing `SpotifyId` for local files +- [core] Support parsing `SpotifyId` for named playlists - [main] Add all player events to `player_event_handler.rs` - [main] Add an event worker thread that runs async to the main thread(s) but sync to itself to prevent potential data races for event consumers diff --git a/core/src/spotify_id.rs b/core/src/spotify_id.rs index 5057c135..da28f98e 100644 --- a/core/src/spotify_id.rs +++ b/core/src/spotify_id.rs @@ -170,9 +170,24 @@ impl SpotifyId { /// /// [Spotify URI]: https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids pub fn from_uri(src: &str) -> SpotifyIdResult { - // At minimum, should be `spotify:{type}:{id}` - let (scheme, tail) = src.split_once(':').ok_or(SpotifyIdError::InvalidFormat)?; - let (item_type, id) = tail.split_once(':').ok_or(SpotifyIdError::InvalidFormat)?; + // Basic: `spotify:{type}:{id}` + // Named: `spotify:user:{user}:{type}:{id}` + // Local: `spotify:local:{artist}:{album_title}:{track_title}:{duration_in_seconds}` + let mut parts = src.split(':'); + + let scheme = parts.next().ok_or(SpotifyIdError::InvalidFormat)?; + + let item_type = { + let next = parts.next().ok_or(SpotifyIdError::InvalidFormat)?; + if next == "user" { + let _username = parts.next().ok_or(SpotifyIdError::InvalidFormat)?; + parts.next().ok_or(SpotifyIdError::InvalidFormat)? + } else { + next + } + }; + + let id = parts.next().ok_or(SpotifyIdError::InvalidFormat)?; if scheme != "spotify" { return Err(SpotifyIdError::InvalidRoot.into()); @@ -701,6 +716,17 @@ mod tests { assert_eq!(actual.item_type, SpotifyItemType::Local); } + #[test] + fn from_named_uri() { + let actual = + NamedSpotifyId::from_uri("spotify:user:spotify:playlist:37i9dQZF1DWSw8liJZcPOI") + .unwrap(); + + assert_eq!(actual.id, 136159921382084734723401526672209703396); + assert_eq!(actual.item_type, SpotifyItemType::Playlist); + assert_eq!(actual.username, "spotify"); + } + #[test] fn to_uri() { for c in &CONV_VALID {