Skip to content

Commit 4061327

Browse files
spockfishpaulfariellophotovoltex
committed
Broken metadata (#2)
* feat: Add pre-commit configuration (librespot-org#1606) * fix: uses the extended-metadata endpoint to retrieve metadata * chore: update CHANGELOG.md * chore: fix clippy warnings --------- Co-authored-by: Paul Fariello <[email protected]> Co-authored-by: Felix Prillwitz <[email protected]>
1 parent e24f7e8 commit 4061327

File tree

9 files changed

+81
-76
lines changed

9 files changed

+81
-76
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- [metadata] Changed arguments for `Metadata` trait from `&SpotifyId` to `&SpotifyUri` (breaking)
1818
- [player] `load` function changed from accepting a `SpotifyId` to accepting a `SpotifyUri` (breaking)
1919
- [player] `preload` function changed from accepting a `SpotifyId` to accepting a `SpotifyUri` (breaking)
20-
- [spclient] `get_radio_for_track` function changed from accepting a `SpotifyId` to accepting a `SpotifyUri` (breaking)
20+
- [core] `get_radio_for_track` function changed from accepting a `SpotifyId` to accepting a `SpotifyUri` (breaking)
21+
- [core] Changed return type of `get_extended_metadata` to return `BatchedExtensionResponse` (breaking)
22+
- [core] Changed parameter of `get_<item>_metadata` from `SpotifyId` to `SpotifyUri` (breaking)
2123

24+
### Fixed
25+
26+
- [core] Fixed a problem where the metadata didn't include the audio file by switching to `get_extended_metadata`
2227

2328
### Removed
2429

core/src/spclient.rs

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use crate::{
1818
connect::PutStateRequest,
1919
context::Context,
2020
extended_metadata::BatchedEntityRequest,
21+
extended_metadata::{BatchedExtensionResponse, EntityRequest, ExtensionQuery},
22+
extension_kind::ExtensionKind,
2123
},
2224
token::Token,
2325
util,
@@ -32,7 +34,7 @@ use hyper::{
3234
header::{ACCEPT, AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, HeaderName, RANGE},
3335
};
3436
use hyper_util::client::legacy::ResponseFuture;
35-
use protobuf::{Enum, Message, MessageFull};
37+
use protobuf::{Enum, EnumOrUnknown, Message, MessageFull};
3638
use rand::RngCore;
3739
use sysinfo::System;
3840
use thiserror::Error;
@@ -58,18 +60,14 @@ const NO_METRICS_AND_SALT: RequestOptions = RequestOptions {
5860
base_url: None,
5961
};
6062

61-
const SPCLIENT_FALLBACK_ENDPOINT: RequestOptions = RequestOptions {
62-
metrics: true,
63-
salt: true,
64-
base_url: Some("https://spclient.wg.spotify.com"),
65-
};
66-
6763
#[derive(Debug, Error)]
6864
pub enum SpClientError {
6965
#[error("missing attribute {0}")]
7066
Attribute(String),
7167
#[error("expected data but received none")]
7268
NoData,
69+
#[error("expected an entry to exist in {0}")]
70+
ExpectedEntry(&'static str),
7371
}
7472

7573
impl From<SpClientError> for Error {
@@ -572,39 +570,67 @@ impl SpClient {
572570
.await
573571
}
574572

575-
pub async fn get_metadata(&self, scope: &str, id: &SpotifyId) -> SpClientResult {
576-
let endpoint = format!("/metadata/4/{}/{}", scope, id.to_base16()?);
577-
// For unknown reasons, metadata requests must now be sent through spclient.wg.spotify.com.
578-
// Otherwise, the API will respond with 500 Internal Server Error responses.
579-
// Context: https://github.com/librespot-org/librespot/issues/1527
580-
self.request_with_options(
581-
&Method::GET,
582-
&endpoint,
583-
None,
584-
None,
585-
&SPCLIENT_FALLBACK_ENDPOINT,
586-
)
587-
.await
573+
pub async fn get_extended_metadata(
574+
&self,
575+
request: BatchedEntityRequest,
576+
) -> Result<BatchedExtensionResponse, Error> {
577+
let endpoint = "/extended-metadata/v0/extended-metadata";
578+
let res = self
579+
.request_with_protobuf(&Method::POST, endpoint, None, &request)
580+
.await?;
581+
Ok(BatchedExtensionResponse::parse_from_bytes(&res)?)
582+
}
583+
584+
pub async fn get_metadata(&self, kind: ExtensionKind, id: &SpotifyUri) -> SpClientResult {
585+
let req = BatchedEntityRequest {
586+
entity_request: vec![EntityRequest {
587+
entity_uri: id.to_uri()?,
588+
query: vec![ExtensionQuery {
589+
extension_kind: EnumOrUnknown::new(kind),
590+
..Default::default()
591+
}],
592+
..Default::default()
593+
}],
594+
..Default::default()
595+
};
596+
597+
let mut res = self.get_extended_metadata(req).await?;
598+
let mut extended_metadata = res
599+
.extended_metadata
600+
.pop()
601+
.ok_or(SpClientError::ExpectedEntry("extended_metadata"))?;
602+
603+
let mut data = extended_metadata
604+
.extension_data
605+
.pop()
606+
.ok_or(SpClientError::ExpectedEntry("extension_data"))?;
607+
608+
match data.extension_data.take() {
609+
None => Err(SpClientError::ExpectedEntry("data").into()),
610+
Some(data) => Ok(Bytes::from(data.value)),
611+
}
588612
}
589613

590-
pub async fn get_track_metadata(&self, track_id: &SpotifyId) -> SpClientResult {
591-
self.get_metadata("track", track_id).await
614+
pub async fn get_track_metadata(&self, track_uri: &SpotifyUri) -> SpClientResult {
615+
self.get_metadata(ExtensionKind::TRACK_V4, track_uri).await
592616
}
593617

594-
pub async fn get_episode_metadata(&self, episode_id: &SpotifyId) -> SpClientResult {
595-
self.get_metadata("episode", episode_id).await
618+
pub async fn get_episode_metadata(&self, episode_uri: &SpotifyUri) -> SpClientResult {
619+
self.get_metadata(ExtensionKind::EPISODE_V4, episode_uri)
620+
.await
596621
}
597622

598-
pub async fn get_album_metadata(&self, album_id: &SpotifyId) -> SpClientResult {
599-
self.get_metadata("album", album_id).await
623+
pub async fn get_album_metadata(&self, album_uri: &SpotifyUri) -> SpClientResult {
624+
self.get_metadata(ExtensionKind::ALBUM_V4, album_uri).await
600625
}
601626

602-
pub async fn get_artist_metadata(&self, artist_id: &SpotifyId) -> SpClientResult {
603-
self.get_metadata("artist", artist_id).await
627+
pub async fn get_artist_metadata(&self, artist_uri: &SpotifyUri) -> SpClientResult {
628+
self.get_metadata(ExtensionKind::ARTIST_V4, artist_uri)
629+
.await
604630
}
605631

606-
pub async fn get_show_metadata(&self, show_id: &SpotifyId) -> SpClientResult {
607-
self.get_metadata("show", show_id).await
632+
pub async fn get_show_metadata(&self, show_uri: &SpotifyUri) -> SpClientResult {
633+
self.get_metadata(ExtensionKind::SHOW_V4, show_uri).await
608634
}
609635

610636
pub async fn get_lyrics(&self, track_id: &SpotifyId) -> SpClientResult {
@@ -733,12 +759,6 @@ impl SpClient {
733759
// TODO: Seen-in-the-wild but unimplemented endpoints
734760
// - /presence-view/v1/buddylist
735761

736-
pub async fn get_extended_metadata(&self, request: BatchedEntityRequest) -> SpClientResult {
737-
let endpoint = "/extended-metadata/v0/extended-metadata";
738-
self.request_with_protobuf(&Method::POST, endpoint, None, &request)
739-
.await
740-
}
741-
742762
pub async fn get_audio_storage(&self, file_id: &FileId) -> SpClientResult {
743763
let endpoint = format!(
744764
"/storage-resolve/files/audio/interactive/{}",

discovery/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ fn launch_libmdns(
406406
}
407407
.map_err(|e| DiscoveryError::DnsSdError(Box::new(e)))?;
408408

409-
let svc = responder.register(&DNS_SD_SERVICE_NAME, &name, port, &TXT_RECORD);
409+
let svc = responder.register(DNS_SD_SERVICE_NAME, &name, port, &TXT_RECORD);
410410

411411
let _ = shutdown_rx.blocking_recv();
412412

metadata/src/album.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ impl Metadata for Album {
7575
type Message = protocol::metadata::Album;
7676

7777
async fn request(session: &Session, album_uri: &SpotifyUri) -> RequestResult {
78-
let SpotifyUri::Album { id: album_id } = album_uri else {
78+
let SpotifyUri::Album { .. } = album_uri else {
7979
return Err(Error::invalid_argument("album_uri"));
8080
};
8181

82-
session.spclient().get_album_metadata(album_id).await
82+
session.spclient().get_album_metadata(album_uri).await
8383
}
8484

8585
fn parse(msg: &Self::Message, _: &SpotifyUri) -> Result<Self, Error> {

metadata/src/artist.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,11 @@ impl Metadata for Artist {
172172
type Message = protocol::metadata::Artist;
173173

174174
async fn request(session: &Session, artist_uri: &SpotifyUri) -> RequestResult {
175-
let SpotifyUri::Artist { id: artist_id } = artist_uri else {
175+
let SpotifyUri::Artist { .. } = artist_uri else {
176176
return Err(Error::invalid_argument("artist_uri"));
177177
};
178178

179-
session.spclient().get_artist_metadata(artist_id).await
179+
session.spclient().get_artist_metadata(artist_uri).await
180180
}
181181

182182
fn parse(msg: &Self::Message, _: &SpotifyUri) -> Result<Self, Error> {

metadata/src/episode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ impl Metadata for Episode {
5858
type Message = protocol::metadata::Episode;
5959

6060
async fn request(session: &Session, episode_uri: &SpotifyUri) -> RequestResult {
61-
let SpotifyUri::Episode { id: episode_id } = episode_uri else {
61+
let SpotifyUri::Episode { .. } = episode_uri else {
6262
return Err(Error::invalid_argument("episode_uri"));
6363
};
6464

65-
session.spclient().get_episode_metadata(episode_id).await
65+
session.spclient().get_episode_metadata(episode_uri).await
6666
}
6767

6868
fn parse(msg: &Self::Message, _: &SpotifyUri) -> Result<Self, Error> {

metadata/src/show.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ impl Metadata for Show {
3737
type Message = protocol::metadata::Show;
3838

3939
async fn request(session: &Session, show_uri: &SpotifyUri) -> RequestResult {
40-
let SpotifyUri::Show { id: show_id } = show_uri else {
40+
let SpotifyUri::Show { .. } = show_uri else {
4141
return Err(Error::invalid_argument("show_uri"));
4242
};
4343

44-
session.spclient().get_show_metadata(show_id).await
44+
session.spclient().get_show_metadata(show_uri).await
4545
}
4646

4747
fn parse(msg: &Self::Message, _: &SpotifyUri) -> Result<Self, Error> {

metadata/src/track.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ impl Metadata for Track {
5959
type Message = protocol::metadata::Track;
6060

6161
async fn request(session: &Session, track_uri: &SpotifyUri) -> RequestResult {
62-
let SpotifyUri::Track { id: track_id } = track_uri else {
62+
let SpotifyUri::Track { .. } = track_uri else {
6363
return Err(Error::invalid_argument("track_uri"));
6464
};
6565

66-
session.spclient().get_track_metadata(track_id).await
66+
session.spclient().get_track_metadata(track_uri).await
6767
}
6868

6969
fn parse(msg: &Self::Message, _: &SpotifyUri) -> Result<Self, Error> {

playback/src/config.rs

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use std::{mem, str::FromStr, time::Duration};
33
pub use crate::dither::{DithererBuilder, TriangularDitherer, mk_ditherer};
44
use crate::{convert::i24, player::duration_to_coefficient};
55

6-
#[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
6+
#[derive(Clone, Copy, Debug, Default, Hash, PartialOrd, Ord, PartialEq, Eq)]
77
pub enum Bitrate {
88
Bitrate96,
9+
#[default]
910
Bitrate160,
1011
Bitrate320,
1112
}
@@ -22,19 +23,14 @@ impl FromStr for Bitrate {
2223
}
2324
}
2425

25-
impl Default for Bitrate {
26-
fn default() -> Self {
27-
Self::Bitrate160
28-
}
29-
}
30-
31-
#[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
26+
#[derive(Clone, Copy, Debug, Default, Hash, PartialOrd, Ord, PartialEq, Eq)]
3227
pub enum AudioFormat {
3328
F64,
3429
F32,
3530
S32,
3631
S24,
3732
S24_3,
33+
#[default]
3834
S16,
3935
}
4036

@@ -53,12 +49,6 @@ impl FromStr for AudioFormat {
5349
}
5450
}
5551

56-
impl Default for AudioFormat {
57-
fn default() -> Self {
58-
Self::S16
59-
}
60-
}
61-
6252
impl AudioFormat {
6353
// not used by all backends
6454
#[allow(dead_code)]
@@ -73,10 +63,11 @@ impl AudioFormat {
7363
}
7464
}
7565

76-
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
66+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
7767
pub enum NormalisationType {
7868
Album,
7969
Track,
70+
#[default]
8071
Auto,
8172
}
8273

@@ -92,15 +83,10 @@ impl FromStr for NormalisationType {
9283
}
9384
}
9485

95-
impl Default for NormalisationType {
96-
fn default() -> Self {
97-
Self::Auto
98-
}
99-
}
100-
101-
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
86+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
10287
pub enum NormalisationMethod {
10388
Basic,
89+
#[default]
10490
Dynamic,
10591
}
10692

@@ -115,12 +101,6 @@ impl FromStr for NormalisationMethod {
115101
}
116102
}
117103

118-
impl Default for NormalisationMethod {
119-
fn default() -> Self {
120-
Self::Dynamic
121-
}
122-
}
123-
124104
#[derive(Clone)]
125105
pub struct PlayerConfig {
126106
pub bitrate: Bitrate,

0 commit comments

Comments
 (0)