Skip to content

Commit bae304f

Browse files
committed
Update zeroconf fields and publish active user
1 parent f10b8f6 commit bae304f

3 files changed

Lines changed: 42 additions & 16 deletions

File tree

discovery/src/lib.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,14 @@ impl From<DiscoveryError> for Error {
7777
}
7878

7979
impl Builder {
80-
/// Starts a new builder using the provided device id.
81-
pub fn new(device_id: impl Into<String>) -> Self {
80+
/// Starts a new builder using the provided device and client IDs.
81+
pub fn new<T: Into<String>>(device_id: T, client_id: T) -> Self {
8282
Self {
8383
server_config: server::Config {
8484
name: "Librespot".into(),
8585
device_type: DeviceType::default(),
8686
device_id: device_id.into(),
87+
client_id: client_id.into(),
8788
},
8889
port: 0,
8990
}
@@ -141,13 +142,13 @@ impl Builder {
141142

142143
impl Discovery {
143144
/// Starts a [`Builder`] with the provided device id.
144-
pub fn builder(device_id: impl Into<String>) -> Builder {
145-
Builder::new(device_id)
145+
pub fn builder<T: Into<String>>(device_id: T, client_id: T) -> Builder {
146+
Builder::new(device_id, client_id)
146147
}
147148

148149
/// Create a new instance with the specified device id and default paramaters.
149-
pub fn new(device_id: impl Into<String>) -> Result<Self, Error> {
150-
Self::builder(device_id).launch()
150+
pub fn new<T: Into<String>>(device_id: T, client_id: T) -> Result<Self, Error> {
151+
Self::builder(device_id, client_id).launch()
151152
}
152153
}
153154

discovery/src/server.rs

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ pub struct Config {
3636
pub name: Cow<'static, str>,
3737
pub device_type: DeviceType,
3838
pub device_id: String,
39+
pub client_id: String,
3940
}
4041

4142
struct RequestHandler {
4243
config: Config,
44+
username: Option<String>,
4345
keys: DhLocalKeys,
4446
tx: mpsc::UnboundedSender<Credentials>,
4547
}
@@ -50,6 +52,7 @@ impl RequestHandler {
5052

5153
let discovery = Self {
5254
config,
55+
username: None,
5356
keys: DhLocalKeys::random(&mut rand::thread_rng()),
5457
tx,
5558
};
@@ -60,24 +63,45 @@ impl RequestHandler {
6063
fn handle_get_info(&self) -> Response<hyper::Body> {
6164
let public_key = base64::encode(&self.keys.public_key());
6265
let device_type: &str = self.config.device_type.into();
66+
let mut active_user = String::new();
67+
if let Some(username) = &self.username {
68+
active_user = username.to_string();
69+
}
6370

71+
// See: https://developer.spotify.com/documentation/commercial-hardware/implementation/guides/zeroconf/
6472
let body = json!({
6573
"status": 101,
66-
"statusString": "ERROR-OK",
74+
"statusString": "OK",
6775
"spotifyError": 0,
68-
"version": crate::core::version::SEMVER,
76+
// departing from the Spotify documentation, Google Cast uses "5.0.0"
77+
"version": "2.9.0",
6978
"deviceID": (self.config.device_id),
79+
"deviceType": (device_type),
7080
"remoteName": (self.config.name),
71-
"activeUser": "",
81+
// valid value seen in the wild: "empty"
7282
"publicKey": (public_key),
73-
"deviceType": (device_type),
74-
"libraryVersion": crate::core::version::SEMVER,
75-
"accountReq": "PREMIUM",
7683
"brandDisplayName": "librespot",
7784
"modelDisplayName": "librespot",
78-
"resolverVersion": "0",
85+
"libraryVersion": crate::core::version::SEMVER,
86+
"resolverVersion": "1",
7987
"groupStatus": "NONE",
80-
"voiceSupport": "NO",
88+
// valid value documented & seen in the wild: "accesstoken"
89+
// Using it will cause clients to fail to connect.
90+
"tokenType": "default",
91+
"clientID": (self.config.client_id),
92+
"productID": 0,
93+
// Other known scope: client-authorization-universal
94+
// Comma-separated.
95+
"scope": "streaming",
96+
"availability": "",
97+
"supported_drm_media_formats": [],
98+
// TODO: bitmask but what are the flags?
99+
"supported_capabilities": 1,
100+
// undocumented but should still work
101+
"accountReq": "PREMIUM",
102+
"activeUser": active_user,
103+
// others seen-in-the-wild:
104+
// - "deviceAPI_isGroup": False
81105
})
82106
.to_string();
83107

@@ -162,7 +186,7 @@ impl RequestHandler {
162186
let result = json!({
163187
"status": 101,
164188
"spotifyError": 0,
165-
"statusString": "ERROR-OK"
189+
"statusString": "OK",
166190
});
167191

168192
let body = result.to_string();

src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1635,7 +1635,8 @@ async fn main() {
16351635

16361636
if setup.enable_discovery {
16371637
let device_id = setup.session_config.device_id.clone();
1638-
match librespot::discovery::Discovery::builder(device_id)
1638+
let client_id = setup.session_config.client_id.clone();
1639+
match librespot::discovery::Discovery::builder(device_id, client_id)
16391640
.name(setup.connect_config.name.clone())
16401641
.device_type(setup.connect_config.device_type)
16411642
.port(setup.zeroconf_port)

0 commit comments

Comments
 (0)