PMOQobuz client is now working

This commit is contained in:
2025-12-15 10:23:43 +01:00
parent d2f6abf4bb
commit 4bc80dfd08
6 changed files with 113 additions and 31 deletions

View File

@@ -167,7 +167,7 @@ struct SearchResponse {
struct FileUrlResponse {
url: String,
mime_type: String,
sampling_rate: u32,
sampling_rate: f64,
bit_depth: u32,
format_id: u8,
}
@@ -260,8 +260,8 @@ impl QobuzApi {
("track_id", track_id),
];
// Utiliser POST (comme Python)
let response: FileUrlResponse = self.post("/track/getFileUrl", &params).await?;
// Utiliser GET (comme qobuz-player-client qui fonctionne)
let response: FileUrlResponse = self.get("/track/getFileUrl", &params).await?;
Ok(StreamInfo {
url: response.url,

View File

@@ -251,6 +251,10 @@ impl QobuzApi {
request = request.header("X-User-Auth-Token", token);
}
// Headers additionnels pour compatibilité avec qobuz-player-client
request = request.header("Accept-Language", "en,en-US;q=0.8,ko;q=0.6,zh;q=0.4,zh-CN;q=0.2");
request = request.header("Access-Control-Request-Headers", "x-user-auth-token,x-app-id");
// Ajouter les paramètres
if method == "GET" {
request = request.query(params);
@@ -272,7 +276,7 @@ impl QobuzApi {
if !status.is_success() {
let error_text = response.text().await.unwrap_or_default();
warn!("API error ({}) on {}: {}", status_code, endpoint, error_text);
debug!("API error ({}) on {}: {}", status_code, endpoint, error_text);
return Err(QobuzError::from_status_code(status_code, error_text));
}
@@ -286,7 +290,7 @@ impl QobuzApi {
.get("message")
.and_then(|m| m.as_str())
.unwrap_or("Unknown error");
warn!("Qobuz API error on {}: {}", endpoint, message);
debug!("Qobuz API error on {}: {}", endpoint, message);
return Err(QobuzError::ApiError {
code: status_code,
message: message.to_string(),
@@ -297,7 +301,7 @@ impl QobuzApi {
// Parser la réponse
serde_json::from_str(&text).map_err(|e| {
warn!("Failed to parse response: {}", e);
debug!("Failed to parse response: {}", e);
QobuzError::JsonParse(e)
})
}

View File

@@ -10,7 +10,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
///
/// # Returns
///
/// Timestamp Unix sous forme de string avec décimales
/// Timestamp Unix sous forme de string (integer, sans décimales)
///
/// # Exemple
///
@@ -23,7 +23,7 @@ pub fn get_timestamp() -> String {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs_f64()
.as_secs()
.to_string()
}
@@ -107,16 +107,16 @@ mod tests {
#[test]
fn test_get_timestamp() {
let ts = get_timestamp();
// Vérifier que c'est un nombre valide
assert!(ts.parse::<f64>().is_ok());
// Vérifier que c'est un nombre entier valide
assert!(ts.parse::<u64>().is_ok());
// Vérifier que c'est proche du temps actuel (>= 2024)
assert!(ts.parse::<f64>().unwrap() > 1704067200.0); // 1er janvier 2024
assert!(ts.parse::<u64>().unwrap() > 1704067200); // 1er janvier 2024
}
#[test]
fn test_sign_track_get_file_url() {
let signature =
sign_track_get_file_url("27", "stream", "12345", "1234567890.123", b"test_secret");
sign_track_get_file_url("27", "stream", "12345", "1234567890", b"test_secret");
// Vérifier que c'est un hash MD5 valide (32 caractères hex)
assert_eq!(signature.len(), 32);
@@ -125,7 +125,7 @@ mod tests {
#[test]
fn test_sign_userlib_get_albums() {
let signature = sign_userlib_get_albums("1234567890.123", b"test_secret");
let signature = sign_userlib_get_albums("1234567890", b"test_secret");
// Vérifier que c'est un hash MD5 valide (32 caractères hex)
assert_eq!(signature.len(), 32);