mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Update zeroconf fields and publish active user
This commit is contained in:
parent
f10b8f69f8
commit
bae304fdb0
3 changed files with 43 additions and 17 deletions
|
@ -77,13 +77,14 @@ impl From<DiscoveryError> for Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
/// Starts a new builder using the provided device id.
|
/// Starts a new builder using the provided device and client IDs.
|
||||||
pub fn new(device_id: impl Into<String>) -> Self {
|
pub fn new<T: Into<String>>(device_id: T, client_id: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
server_config: server::Config {
|
server_config: server::Config {
|
||||||
name: "Librespot".into(),
|
name: "Librespot".into(),
|
||||||
device_type: DeviceType::default(),
|
device_type: DeviceType::default(),
|
||||||
device_id: device_id.into(),
|
device_id: device_id.into(),
|
||||||
|
client_id: client_id.into(),
|
||||||
},
|
},
|
||||||
port: 0,
|
port: 0,
|
||||||
}
|
}
|
||||||
|
@ -141,13 +142,13 @@ impl Builder {
|
||||||
|
|
||||||
impl Discovery {
|
impl Discovery {
|
||||||
/// Starts a [`Builder`] with the provided device id.
|
/// Starts a [`Builder`] with the provided device id.
|
||||||
pub fn builder(device_id: impl Into<String>) -> Builder {
|
pub fn builder<T: Into<String>>(device_id: T, client_id: T) -> Builder {
|
||||||
Builder::new(device_id)
|
Builder::new(device_id, client_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new instance with the specified device id and default paramaters.
|
/// Create a new instance with the specified device id and default paramaters.
|
||||||
pub fn new(device_id: impl Into<String>) -> Result<Self, Error> {
|
pub fn new<T: Into<String>>(device_id: T, client_id: T) -> Result<Self, Error> {
|
||||||
Self::builder(device_id).launch()
|
Self::builder(device_id, client_id).launch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,10 +36,12 @@ pub struct Config {
|
||||||
pub name: Cow<'static, str>,
|
pub name: Cow<'static, str>,
|
||||||
pub device_type: DeviceType,
|
pub device_type: DeviceType,
|
||||||
pub device_id: String,
|
pub device_id: String,
|
||||||
|
pub client_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RequestHandler {
|
struct RequestHandler {
|
||||||
config: Config,
|
config: Config,
|
||||||
|
username: Option<String>,
|
||||||
keys: DhLocalKeys,
|
keys: DhLocalKeys,
|
||||||
tx: mpsc::UnboundedSender<Credentials>,
|
tx: mpsc::UnboundedSender<Credentials>,
|
||||||
}
|
}
|
||||||
|
@ -50,6 +52,7 @@ impl RequestHandler {
|
||||||
|
|
||||||
let discovery = Self {
|
let discovery = Self {
|
||||||
config,
|
config,
|
||||||
|
username: None,
|
||||||
keys: DhLocalKeys::random(&mut rand::thread_rng()),
|
keys: DhLocalKeys::random(&mut rand::thread_rng()),
|
||||||
tx,
|
tx,
|
||||||
};
|
};
|
||||||
|
@ -60,24 +63,45 @@ impl RequestHandler {
|
||||||
fn handle_get_info(&self) -> Response<hyper::Body> {
|
fn handle_get_info(&self) -> Response<hyper::Body> {
|
||||||
let public_key = base64::encode(&self.keys.public_key());
|
let public_key = base64::encode(&self.keys.public_key());
|
||||||
let device_type: &str = self.config.device_type.into();
|
let device_type: &str = self.config.device_type.into();
|
||||||
|
let mut active_user = String::new();
|
||||||
|
if let Some(username) = &self.username {
|
||||||
|
active_user = username.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
// See: https://developer.spotify.com/documentation/commercial-hardware/implementation/guides/zeroconf/
|
||||||
let body = json!({
|
let body = json!({
|
||||||
"status": 101,
|
"status": 101,
|
||||||
"statusString": "ERROR-OK",
|
"statusString": "OK",
|
||||||
"spotifyError": 0,
|
"spotifyError": 0,
|
||||||
"version": crate::core::version::SEMVER,
|
// departing from the Spotify documentation, Google Cast uses "5.0.0"
|
||||||
|
"version": "2.9.0",
|
||||||
"deviceID": (self.config.device_id),
|
"deviceID": (self.config.device_id),
|
||||||
"remoteName": (self.config.name),
|
|
||||||
"activeUser": "",
|
|
||||||
"publicKey": (public_key),
|
|
||||||
"deviceType": (device_type),
|
"deviceType": (device_type),
|
||||||
"libraryVersion": crate::core::version::SEMVER,
|
"remoteName": (self.config.name),
|
||||||
"accountReq": "PREMIUM",
|
// valid value seen in the wild: "empty"
|
||||||
|
"publicKey": (public_key),
|
||||||
"brandDisplayName": "librespot",
|
"brandDisplayName": "librespot",
|
||||||
"modelDisplayName": "librespot",
|
"modelDisplayName": "librespot",
|
||||||
"resolverVersion": "0",
|
"libraryVersion": crate::core::version::SEMVER,
|
||||||
|
"resolverVersion": "1",
|
||||||
"groupStatus": "NONE",
|
"groupStatus": "NONE",
|
||||||
"voiceSupport": "NO",
|
// valid value documented & seen in the wild: "accesstoken"
|
||||||
|
// Using it will cause clients to fail to connect.
|
||||||
|
"tokenType": "default",
|
||||||
|
"clientID": (self.config.client_id),
|
||||||
|
"productID": 0,
|
||||||
|
// Other known scope: client-authorization-universal
|
||||||
|
// Comma-separated.
|
||||||
|
"scope": "streaming",
|
||||||
|
"availability": "",
|
||||||
|
"supported_drm_media_formats": [],
|
||||||
|
// TODO: bitmask but what are the flags?
|
||||||
|
"supported_capabilities": 1,
|
||||||
|
// undocumented but should still work
|
||||||
|
"accountReq": "PREMIUM",
|
||||||
|
"activeUser": active_user,
|
||||||
|
// others seen-in-the-wild:
|
||||||
|
// - "deviceAPI_isGroup": False
|
||||||
})
|
})
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
|
@ -162,7 +186,7 @@ impl RequestHandler {
|
||||||
let result = json!({
|
let result = json!({
|
||||||
"status": 101,
|
"status": 101,
|
||||||
"spotifyError": 0,
|
"spotifyError": 0,
|
||||||
"statusString": "ERROR-OK"
|
"statusString": "OK",
|
||||||
});
|
});
|
||||||
|
|
||||||
let body = result.to_string();
|
let body = result.to_string();
|
||||||
|
|
|
@ -1635,7 +1635,8 @@ async fn main() {
|
||||||
|
|
||||||
if setup.enable_discovery {
|
if setup.enable_discovery {
|
||||||
let device_id = setup.session_config.device_id.clone();
|
let device_id = setup.session_config.device_id.clone();
|
||||||
match librespot::discovery::Discovery::builder(device_id)
|
let client_id = setup.session_config.client_id.clone();
|
||||||
|
match librespot::discovery::Discovery::builder(device_id, client_id)
|
||||||
.name(setup.connect_config.name.clone())
|
.name(setup.connect_config.name.clone())
|
||||||
.device_type(setup.connect_config.device_type)
|
.device_type(setup.connect_config.device_type)
|
||||||
.port(setup.zeroconf_port)
|
.port(setup.zeroconf_port)
|
||||||
|
|
Loading…
Reference in a new issue