mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
fix(analysis): native library backfill coordinator for advanced strategy (#881)
* feat(analysis): native library backfill coordinator for advanced strategy Move advanced analytics scheduling from the webview loop into a Rust background worker (configure + spawn_blocking batch/enqueue), matching cover backfill. Scan hash+BPM gap tracks instead of the full library; suppress low-priority analysis UI events; limit loudness refresh IPC to the playback window. * fix(analysis): flat backfill configure IPC and restore probe track-perf Use flattened Tauri args like cover backfill so release/prod invoke works; keep emitting analysis:track-perf for library low-priority work so Performance Probe tpm/last-track stats update while waveform/enrichment UI events stay suppressed. * chore(analysis): fix clippy and drop duplicate TS backfill policy Allow too_many_arguments on library_analysis_backfill_configure for CI; remove unused frontend batch API and TS watermark helpers now owned in Rust; clarify analysis_emits_ui_events comment for low-priority track-perf. * docs: CHANGELOG and credits for PR #881 native analysis backfill
This commit is contained in:
@@ -5,12 +5,14 @@
|
||||
pub mod auth;
|
||||
pub mod client;
|
||||
pub mod error;
|
||||
pub mod stream_url;
|
||||
pub mod types;
|
||||
|
||||
pub use auth::SubsonicCredentials;
|
||||
pub use client::{
|
||||
fingerprint_sample, SubsonicClient, SUBSONIC_API_VERSION, SUBSONIC_CLIENT_ID,
|
||||
};
|
||||
pub use stream_url::{build_stream_view_url, rest_base_from_url};
|
||||
pub use error::SubsonicError;
|
||||
pub use types::{
|
||||
Album, AlbumSummary, ArtistIndex, ArtistRef, IndexBucket, ScanStatus, SearchResult, ServerInfo,
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
//! Subsonic `stream.view` URLs for native library analysis backfill.
|
||||
|
||||
use url::Url;
|
||||
|
||||
use super::auth::SubsonicCredentials;
|
||||
use super::client::{SUBSONIC_API_VERSION, SUBSONIC_CLIENT_ID};
|
||||
|
||||
/// `{origin}/rest` — mirrors frontend `restBaseFromUrl`.
|
||||
pub fn rest_base_from_url(server_url: &str) -> String {
|
||||
let trimmed = server_url.trim().trim_end_matches('/');
|
||||
let base = if trimmed.starts_with("http://") || trimmed.starts_with("https://") {
|
||||
trimmed.to_string()
|
||||
} else {
|
||||
format!("http://{trimmed}")
|
||||
};
|
||||
format!("{base}/rest")
|
||||
}
|
||||
|
||||
/// Authenticated `stream.view` URL for a library track id.
|
||||
pub fn build_stream_view_url(
|
||||
server_url: &str,
|
||||
username: &str,
|
||||
password: &str,
|
||||
track_id: &str,
|
||||
) -> String {
|
||||
let creds = SubsonicCredentials::from_password(username, password);
|
||||
let base = rest_base_from_url(server_url);
|
||||
let mut url =
|
||||
Url::parse(&format!("{base}/stream.view")).unwrap_or_else(|_| Url::parse("http://invalid/rest/stream.view").unwrap());
|
||||
{
|
||||
let mut q = url.query_pairs_mut();
|
||||
q.append_pair("id", track_id);
|
||||
q.append_pair("u", &creds.username);
|
||||
q.append_pair("t", &creds.token);
|
||||
q.append_pair("s", &creds.salt);
|
||||
q.append_pair("v", SUBSONIC_API_VERSION);
|
||||
q.append_pair("c", SUBSONIC_CLIENT_ID);
|
||||
q.append_pair("f", "json");
|
||||
}
|
||||
url.to_string()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn stream_url_contains_track_and_auth_params() {
|
||||
let url = build_stream_view_url(
|
||||
"https://music.example",
|
||||
"alice",
|
||||
"secret",
|
||||
"tr-42",
|
||||
);
|
||||
assert!(url.contains("stream.view"));
|
||||
assert!(url.contains("id=tr-42"));
|
||||
assert!(url.contains("u=alice"));
|
||||
assert!(url.contains("&t="));
|
||||
assert!(url.contains("&s="));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user