Minimal subsonic functionality
All checks were successful
CI / check (push) Successful in 1m12s
CI / docker (push) Successful in 2m2s

This commit is contained in:
Connor Johnstone
2026-03-20 20:04:35 -04:00
parent 0496944923
commit 43f4dad038
5 changed files with 50 additions and 3 deletions

15
Cargo.lock generated
View File

@@ -2423,6 +2423,16 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "quick-xml"
version = "0.37.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
dependencies = [
"memchr",
"serde",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.45" version = "1.0.45"
@@ -3333,11 +3343,15 @@ dependencies = [
"chrono", "chrono",
"clap", "clap",
"dirs", "dirs",
"hex",
"md-5",
"quick-xml",
"rand 0.9.2", "rand 0.9.2",
"reqwest", "reqwest",
"sea-orm", "sea-orm",
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded",
"serde_yaml", "serde_yaml",
"shanty-config", "shanty-config",
"shanty-data", "shanty-data",
@@ -3351,6 +3365,7 @@ dependencies = [
"shanty-watch", "shanty-watch",
"thiserror", "thiserror",
"tokio", "tokio",
"tokio-util",
"tracing", "tracing",
"tracing-actix-web", "tracing-actix-web",
"tracing-subscriber", "tracing-subscriber",

View File

@@ -38,6 +38,9 @@ pub struct AppConfig {
#[serde(default)] #[serde(default)]
pub scheduling: SchedulingConfig, pub scheduling: SchedulingConfig,
#[serde(default)]
pub subsonic: SubsonicConfig,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -152,6 +155,26 @@ pub struct SchedulingConfig {
pub monitor_interval_hours: u32, pub monitor_interval_hours: u32,
} }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SubsonicConfig {
/// Whether the Subsonic API is enabled.
#[serde(default = "default_true")]
pub enabled: bool,
/// Whether transcoding via ffmpeg is enabled.
#[serde(default = "default_true")]
pub transcoding_enabled: bool,
}
impl Default for SubsonicConfig {
fn default() -> Self {
Self {
enabled: true,
transcoding_enabled: true,
}
}
}
impl Default for SchedulingConfig { impl Default for SchedulingConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
@@ -179,6 +202,7 @@ impl Default for AppConfig {
indexing: IndexingConfig::default(), indexing: IndexingConfig::default(),
metadata: MetadataConfig::default(), metadata: MetadataConfig::default(),
scheduling: SchedulingConfig::default(), scheduling: SchedulingConfig::default(),
subsonic: SubsonicConfig::default(),
} }
} }
} }

View File

@@ -131,13 +131,21 @@ async fn main() -> anyhow::Result<()> {
.service( .service(
actix_files::Files::new("/", static_dir.clone()) actix_files::Files::new("/", static_dir.clone())
.index_file("index.html") .index_file("index.html")
.prefer_utf8(true), .prefer_utf8(true)
.guard(actix_web::guard::fn_guard(|ctx| {
!ctx.head().uri.path().starts_with("/rest")
})),
) )
.default_service(web::to({ .default_service(web::to({
let index_path = static_dir.join("index.html"); let index_path = static_dir.join("index.html");
move |req: actix_web::HttpRequest| { move |req: actix_web::HttpRequest| {
let index_path = index_path.clone(); let index_path = index_path.clone();
async move { async move {
if req.path().starts_with("/rest") {
return Ok(actix_web::HttpResponse::NotFound()
.content_type("application/json")
.body(r#"{"subsonic-response":{"status":"failed","version":"1.16.1","error":{"code":0,"message":"Unknown endpoint"}}}"#));
}
actix_files::NamedFile::open_async(index_path) actix_files::NamedFile::open_async(index_path)
.await .await
.map(|f| f.into_response(&req)) .map(|f| f.into_response(&req))