correction for lazy playlist and lazy cache

This commit is contained in:
2025-12-15 11:18:58 +01:00
parent 4bc80dfd08
commit 90399b408a
28 changed files with 349 additions and 39126 deletions

View File

@@ -50,7 +50,10 @@ async fn main() -> Result<()> {
match api.get_file_url(track_id).await {
Ok(stream_info) => {
println!(" ✓ Success!");
println!(" URL: {}...", &stream_info.url[..80.min(stream_info.url.len())]);
println!(
" URL: {}...",
&stream_info.url[..80.min(stream_info.url.len())]
);
println!(" MIME type: {}", stream_info.mime_type);
}
Err(e) => {

View File

@@ -29,7 +29,10 @@ async fn main() -> Result<()> {
println!(" format_id: {}", format_id);
println!(" intent: {}", intent);
println!(" timestamp: {}", timestamp);
println!(" secret: {}... (first 10 chars)", &app_secret[..10.min(app_secret.len())]);
println!(
" secret: {}... (first 10 chars)",
&app_secret[..10.min(app_secret.len())]
);
// Calculer la signature
let signature = signing::sign_track_get_file_url(

View File

@@ -252,8 +252,14 @@ impl QobuzApi {
}
// 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");
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" {
@@ -268,7 +274,11 @@ impl QobuzApi {
}
/// Traite la réponse HTTP
async fn handle_response<T: DeserializeOwned>(&self, response: Response, endpoint: &str) -> Result<T> {
async fn handle_response<T: DeserializeOwned>(
&self,
response: Response,
endpoint: &str,
) -> Result<T> {
let status = response.status();
let status_code = status.as_u16();
@@ -276,7 +286,10 @@ impl QobuzApi {
if !status.is_success() {
let error_text = response.text().await.unwrap_or_default();
debug!("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));
}

View File

@@ -134,10 +134,7 @@ impl QobuzClient {
let mut api = match (config_appid.clone(), config_spoofer_secret, config_secret) {
// Priority 1: Try memorized Spoofer secret (raw, no XOR)
(Some(app_id), Some(spoofer_secret), _) => {
info!(
"Trying memorized Spoofer secret with App ID: {}",
app_id
);
info!("Trying memorized Spoofer secret with App ID: {}", app_id);
match QobuzApi::with_raw_secret(&app_id, &spoofer_secret) {
Ok(api) => {
used_config_credentials = true;
@@ -174,9 +171,7 @@ impl QobuzClient {
}
// Priority 3: Fallback to Spoofer
_ => {
info!(
"AppID or secret not configured, using Spoofer..."
);
info!("AppID or secret not configured, using Spoofer...");
Self::try_spoofer_fallback(config).await?
}
};
@@ -266,13 +261,19 @@ impl QobuzClient {
// Optimization: Login once with first secret to get auth token
// Then test all secrets using the same token
if let Some((first_timezone, first_secret)) = secrets.first() {
if let Ok(temp_api) = QobuzApi::with_raw_secret(&app_id, first_secret) {
if let Ok(_auth_info) = temp_api.login(&username, &password).await {
if let Ok(temp_api) =
QobuzApi::with_raw_secret(&app_id, first_secret)
{
if let Ok(_auth_info) =
temp_api.login(&username, &password).await
{
// Now test each secret with the authenticated token
for (timezone, secret) in secrets.iter() {
debug!("Testing timezone secret: {}", timezone);
if let Ok(test_api) = QobuzApi::with_raw_secret(&app_id, secret) {
if let Ok(test_api) =
QobuzApi::with_raw_secret(&app_id, secret)
{
// Set the auth token from our initial login
test_api.set_auth_token(
temp_api.auth_token().unwrap(),
@@ -282,17 +283,29 @@ impl QobuzClient {
// Test the secret using track/getFileUrl (like qobuz-player-client)
// Use the same hardcoded track_id (64868955) as qobuz-player-client
if test_api.get_file_url("64868955").await.is_ok() {
info!("✓ Secret from timezone '{}' works!", timezone);
info!(
"✓ Secret from timezone '{}' works!",
timezone
);
// Save both appid and the working secret
if let Err(e) = config.set_qobuz_appid(&app_id) {
if let Err(e) = config.set_qobuz_appid(&app_id)
{
debug!("Could not save appid: {}", e);
}
if let Err(e) = config.set_qobuz_spoofer_secret(secret) {
debug!("Could not save spoofer secret: {}", e);
if let Err(e) =
config.set_qobuz_spoofer_secret(secret)
{
debug!(
"Could not save spoofer secret: {}",
e
);
}
return Ok(Some((app_id.clone(), secret.clone())));
return Ok(Some((
app_id.clone(),
secret.clone(),
)));
} else {
debug!("✗ Secret from timezone '{}' failed track/getFileUrl test", timezone);
}
@@ -310,7 +323,7 @@ impl QobuzClient {
Ok(None)
}
}
},
}
Err(e) => {
info!(
"Spoofer failed to extract app_id: {}, falling back to DEFAULT_APP_ID",

View File

@@ -230,8 +230,9 @@ impl QobuzSource {
///
/// # Returns
///
/// The track ID (e.g., "qobuz://track/12345")
pub async fn add_track_lazy(&self, track: &Track) -> Result<String> {
/// `(track_id, lazy_pk)` where `track_id` is the logical Qobuz URI and
/// `lazy_pk` the cache identifier stored in pmocache.
pub async fn add_track_lazy(&self, track: &Track) -> Result<(String, String)> {
let track_id = format!("qobuz://track/{}", track.id);
// Get streaming URL
@@ -287,7 +288,12 @@ impl QobuzSource {
.cache_manager
.cache_audio_lazy(&stream_url, Some(metadata))
.await
.ok();
.map_err(|e| {
MusicSourceError::CacheError(format!(
"Failed to cache lazy track {}: {}",
track.title, e
))
})?;
// 4. Store metadata
self.inner
@@ -296,13 +302,13 @@ impl QobuzSource {
track_id.clone(),
pmosource::TrackMetadata {
original_uri: stream_url,
cached_audio_pk,
cached_audio_pk: Some(cached_audio_pk.clone()),
cached_cover_pk,
},
)
.await;
Ok(track_id)
Ok((track_id, cached_audio_pk))
}
/// Load full album into pmoplaylist with lazy audio
@@ -345,15 +351,15 @@ impl QobuzSource {
for (i, track) in tracks.iter().enumerate() {
match self.add_track_lazy(track).await {
Ok(track_id) => {
debug!("Track {}/{}: {} (lazy)", i + 1, tracks.len(), track.title);
// Extract lazy PK from cache manager
if let Some(metadata) = self.inner.cache_manager.get_metadata(&track_id).await {
if let Some(audio_pk) = metadata.cached_audio_pk {
lazy_pks.push(audio_pk);
}
}
Ok((_track_id, lazy_pk)) => {
debug!(
"Track {}/{}: {} (lazy pk {})",
i + 1,
tracks.len(),
track.title,
&lazy_pk
);
lazy_pks.push(lazy_pk);
}
Err(e) => {
warn!("Failed to add track {} ({}): {}", i + 1, track.title, e);
@@ -431,15 +437,15 @@ impl QobuzSource {
for (i, track) in tracks.iter().enumerate() {
match self.add_track_lazy(track).await {
Ok(track_id) => {
debug!("Track {}/{}: {} (lazy)", i + 1, tracks.len(), track.title);
// Extract lazy PK from cache manager
if let Some(metadata) = self.inner.cache_manager.get_metadata(&track_id).await {
if let Some(audio_pk) = metadata.cached_audio_pk {
lazy_pks.push(audio_pk);
}
}
Ok((_track_id, lazy_pk)) => {
debug!(
"Track {}/{}: {} (lazy pk {})",
i + 1,
tracks.len(),
track.title,
&lazy_pk
);
lazy_pks.push(lazy_pk);
}
Err(e) => {
warn!("Failed to add track {} ({}): {}", i + 1, track.title, e);