Fetch Custom CSS in ​/Branding​/Configuration

This commit is contained in:
Lukas Kreussel
2026-02-01 14:43:28 +01:00
parent e2e43fc63c
commit e60f64ee2b
4 changed files with 76 additions and 3 deletions

View File

@@ -236,6 +236,13 @@ impl JellyfinClient {
.await
}
pub async fn get_branding_configuration(
&self,
) -> Result<crate::models::BrandingConfiguration, Error> {
self.request(reqwest::Method::GET, "Branding/Configuration", None)
.await
}
// Admin methods
pub async fn get_users(&self) -> Result<Vec<User>, Error> {
@@ -401,4 +408,36 @@ mod tests {
assert_eq!(folders.len(), 1);
assert_eq!(folders[0].name, "Movies");
}
#[tokio::test]
async fn test_get_branding_configuration() {
let mock_server = MockServer::start().await;
let branding_response = json!({
"LoginDisclaimer": "Welcome to Jellyfin",
"CustomCss": "body { background: black; }",
"SplashscreenEnabled": true
});
Mock::given(method("GET"))
.and(path("/Branding/Configuration"))
.respond_with(ResponseTemplate::new(200).set_body_json(branding_response))
.mount(&mock_server)
.await;
let client_info = ClientInfo::default();
let client = JellyfinClient::new(&mock_server.uri(), client_info).unwrap();
let config = client.get_branding_configuration().await.unwrap();
assert_eq!(
config.login_disclaimer,
Some("Welcome to Jellyfin".to_string())
);
assert_eq!(
config.custom_css,
Some("body { background: black; }".to_string())
);
assert_eq!(config.splashscreen_enabled, Some(true));
}
}

View File

@@ -91,3 +91,13 @@ pub struct ItemsResponse {
#[serde(rename = "TotalRecordCount")]
pub total_record_count: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BrandingConfiguration {
#[serde(rename = "LoginDisclaimer")]
pub login_disclaimer: Option<String>,
#[serde(rename = "CustomCss")]
pub custom_css: Option<String>,
#[serde(rename = "SplashscreenEnabled")]
pub splashscreen_enabled: Option<bool>,
}

View File

@@ -1,5 +1,6 @@
use axum::{extract::State, Json};
use hyper::StatusCode;
use jellyfin_api::JellyfinClient;
use crate::{models::BrandingConfig, AppState};
@@ -13,6 +14,8 @@ pub async fn handle_branding(
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
let mut message = "Jellyswarrm proxying to the following servers: ".to_string();
let mut custom_css = String::new();
if !servers.is_empty() {
let server_links: Vec<String> = servers
.iter()
@@ -24,13 +27,34 @@ pub async fn handle_branding(
})
.collect();
message.push_str(&server_links.join(", "));
for server in servers {
if state
.server_storage
.server_status(server.id)
.await
.is_healthy()
{
if let Ok(client) = JellyfinClient::new_with_client(
server.url.as_ref(),
state.server_storage.client_info.clone(),
state.server_storage.http_client.clone(),
) {
if let Ok(branding) = client.get_branding_configuration().await {
if let Some(remote_custom_css) = branding.custom_css {
custom_css = remote_custom_css;
}
}
}
}
}
} else {
message.push_str("No servers configured.");
}
let config = BrandingConfig {
login_disclaimer: message,
custom_css: String::new(),
custom_css,
splashscreen_enabled: false,
};
Ok(Json(config))

View File

@@ -52,8 +52,8 @@ impl ServerHealthStatus {
pub struct ServerStorageService {
pool: SqlitePool,
health_status: Arc<RwLock<HashMap<i64, ServerHealthStatus>>>,
http_client: reqwest::Client,
client_info: ClientInfo,
pub http_client: reqwest::Client,
pub client_info: ClientInfo,
}
impl ServerStorageService {