correction for lazy playlist and lazy cache
This commit is contained in:
@@ -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) => {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user