mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
This commit is contained in:
@@ -63,13 +63,15 @@ pub fn build_fanart_url(mbid: &str, api_key: &str, client_key: Option<&str>) ->
|
||||
/// `Ok(None)` when the artist carries no MBID tag.
|
||||
pub async fn fetch_artist_tag_mbid(
|
||||
client: &Client,
|
||||
registry: Option<&psysonic_core::server_http::ServerHttpRegistry>,
|
||||
server_ref: Option<&str>,
|
||||
rest_base: &str,
|
||||
username: &str,
|
||||
password: &str,
|
||||
artist_id: &str,
|
||||
) -> Result<Option<String>, String> {
|
||||
let url = build_artist_info2_url(rest_base, username, password, artist_id);
|
||||
let body = http_get_text(client, &url).await?;
|
||||
let body = http_get_text_scoped(client, registry, server_ref, &url).await?;
|
||||
let v: serde_json::Value = serde_json::from_str(&body).map_err(|e| e.to_string())?;
|
||||
let mbid = v
|
||||
.get("subsonic-response")
|
||||
@@ -218,8 +220,21 @@ fn classify_mb_releases(v: &serde_json::Value) -> MbResolution {
|
||||
}
|
||||
|
||||
/// Single GET → response text; any non-2xx is an error.
|
||||
async fn http_get_text(client: &Client, url: &str) -> Result<String, String> {
|
||||
let resp = client.get(url).send().await.map_err(|e| e.to_string())?;
|
||||
async fn http_get_text_scoped(
|
||||
client: &Client,
|
||||
registry: Option<&psysonic_core::server_http::ServerHttpRegistry>,
|
||||
server_ref: Option<&str>,
|
||||
url: &str,
|
||||
) -> Result<String, String> {
|
||||
let resp = psysonic_core::server_http::apply_optional_registry_headers(
|
||||
registry,
|
||||
server_ref,
|
||||
url,
|
||||
client.get(url),
|
||||
)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
let status = resp.status();
|
||||
if !status.is_success() {
|
||||
return Err(format!("HTTP {status}"));
|
||||
|
||||
@@ -242,12 +242,18 @@ pub(super) async fn try_external_fanart(
|
||||
|
||||
let _permit = fanart_sem.clone().acquire_owned().await.ok()?;
|
||||
|
||||
let http_registry = app
|
||||
.try_state::<Arc<psysonic_core::server_http::ServerHttpRegistry>>()
|
||||
.map(|s| Arc::clone(&*s));
|
||||
|
||||
// §23: resolve the tag MBID Rust-side via getArtistInfo2 — unless the cache
|
||||
// already carries one (skip the Navidrome round-trip).
|
||||
let (mbid, mbid_source) = match cached.as_ref().and_then(|r| r.mbid.clone()) {
|
||||
Some(m) => (m, cached.as_ref().and_then(|r| r.mbid_source.clone())),
|
||||
None => match external::fetch_artist_tag_mbid(
|
||||
client,
|
||||
http_registry.as_deref(),
|
||||
Some(server_id),
|
||||
&args.rest_base_url,
|
||||
&args.username,
|
||||
&args.password,
|
||||
@@ -344,7 +350,7 @@ pub(super) async fn try_external_fanart(
|
||||
}
|
||||
};
|
||||
|
||||
let bytes = match fetch::fetch_cover_bytes(client, &img_url).await {
|
||||
let bytes = match fetch::fetch_cover_bytes(client, &img_url, None, None).await {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
eprintln!("[fanart] download failed: {e}"); // transient — don't cache
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use reqwest::Client;
|
||||
use psysonic_core::server_http::ServerHttpRegistry;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
use url::Url;
|
||||
|
||||
@@ -83,8 +84,21 @@ enum FetchAttempt {
|
||||
Permanent(String),
|
||||
}
|
||||
|
||||
async fn fetch_cover_once(client: &Client, url: &str) -> FetchAttempt {
|
||||
let resp = match client.get(url).send().await {
|
||||
async fn fetch_cover_once(
|
||||
client: &Client,
|
||||
url: &str,
|
||||
registry: Option<&ServerHttpRegistry>,
|
||||
server_ref: Option<&str>,
|
||||
) -> FetchAttempt {
|
||||
let mut req = client.get(url);
|
||||
if let Some(reg) = registry {
|
||||
if let Some(sid) = server_ref.filter(|s| !s.is_empty()) {
|
||||
req = reg.apply_for_http_url(sid, url, req);
|
||||
} else if let Some(ctx) = reg.get_for_server_url(url) {
|
||||
req = psysonic_core::server_http::apply_server_headers_for_http_url(req, &ctx, url);
|
||||
}
|
||||
}
|
||||
let resp = match req.send().await {
|
||||
Ok(r) => r,
|
||||
// Connection reset / timeout / DNS — transient under server load.
|
||||
Err(e) => return FetchAttempt::Transient(e.to_string()),
|
||||
@@ -104,10 +118,15 @@ async fn fetch_cover_once(client: &Client, url: &str) -> FetchAttempt {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_cover_bytes(client: &Client, url: &str) -> Result<Vec<u8>, String> {
|
||||
pub async fn fetch_cover_bytes(
|
||||
client: &Client,
|
||||
url: &str,
|
||||
registry: Option<&ServerHttpRegistry>,
|
||||
server_ref: Option<&str>,
|
||||
) -> Result<Vec<u8>, String> {
|
||||
let mut last_err = String::from("cover fetch failed");
|
||||
for attempt in 0..COVER_FETCH_ATTEMPTS {
|
||||
match fetch_cover_once(client, url).await {
|
||||
match fetch_cover_once(client, url, registry, server_ref).await {
|
||||
FetchAttempt::Ok(bytes) => return Ok(bytes),
|
||||
FetchAttempt::Permanent(e) => return Err(e),
|
||||
FetchAttempt::Transient(e) => {
|
||||
|
||||
@@ -354,7 +354,10 @@ impl CoverCacheState {
|
||||
let source = if let Some(img) = load_image_from_disk(&dir) {
|
||||
CoverSource::Image(img)
|
||||
} else {
|
||||
match download_cover_payload(&dir, &client, &http_sem, args).await {
|
||||
let http_registry = app
|
||||
.try_state::<Arc<psysonic_core::server_http::ServerHttpRegistry>>()
|
||||
.map(|s| Arc::clone(&*s));
|
||||
match download_cover_payload(&dir, &client, &http_sem, args, http_registry).await {
|
||||
Ok(bytes) => CoverSource::Bytes(bytes),
|
||||
Err(err) => {
|
||||
log_cover_fetch_failure(app, args, &err);
|
||||
@@ -532,6 +535,7 @@ async fn download_cover_payload(
|
||||
client: &Client,
|
||||
http_sem: &Semaphore,
|
||||
args: &CoverCacheEnsureArgs,
|
||||
registry: Option<Arc<psysonic_core::server_http::ServerHttpRegistry>>,
|
||||
) -> Result<Vec<u8>, String> {
|
||||
let _permit = http_sem
|
||||
.acquire()
|
||||
@@ -549,7 +553,13 @@ async fn download_cover_payload(
|
||||
&args.cover_art_id,
|
||||
fetch_size,
|
||||
);
|
||||
fetch::fetch_cover_bytes(client, &url).await
|
||||
fetch::fetch_cover_bytes(
|
||||
client,
|
||||
&url,
|
||||
registry.as_deref(),
|
||||
Some(args.server_index_key.as_str()),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
fn spawn_derive_remaining_tiers(
|
||||
|
||||
Reference in New Issue
Block a user