From b3fd00cb4db71992a304c73583776272e8ca36fb Mon Sep 17 00:00:00 2001 From: glenneth Date: Fri, 17 Oct 2025 05:29:47 +0300 Subject: [PATCH] refactor: improve code consistency and maintainability - Add /api/asteroid/partial/now-playing-inline endpoint for inline text - Refactor admin.js to use server-side partial (removes 23 lines of JSON/XML parsing) - Fix hardcoded path in convert-to-docker-path to use *music-library-path* variable - Consistent with front-page and player refactoring from upstream - Improves portability and reduces client-side JavaScript complexity --- frontend-partials.lisp | 15 +++++++++++++++ static/js/admin.js | 36 +++++++++++++----------------------- stream-control.lisp | 4 ++-- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/frontend-partials.lisp b/frontend-partials.lisp index 45a088d..9eaf1d2 100644 --- a/frontend-partials.lisp +++ b/frontend-partials.lisp @@ -53,3 +53,18 @@ (api-output `(("status" . "error") ("message" . ,(format nil "Error loading profile: ~a" e))) :status 500)))) + +(define-api asteroid/partial/now-playing-inline () () + "Get inline text with now playing info (for admin dashboard and widgets)" + (handler-case + (let ((now-playing-stats (icecast-now-playing *stream-base-url*))) + (if now-playing-stats + (progn + (setf (header "Content-Type") "text/plain") + (cdr (assoc :title now-playing-stats))) + (progn + (setf (header "Content-Type") "text/plain") + "Stream Offline"))) + (error (e) + (setf (header "Content-Type") "text/plain") + "Error loading stream info"))) diff --git a/static/js/admin.js b/static/js/admin.js index 27cfb00..d5a520c 100644 --- a/static/js/admin.js +++ b/static/js/admin.js @@ -561,35 +561,25 @@ function displayQueueSearchResults(results) { // Live stream info update async function updateLiveStreamInfo() { try { - const response = await fetch('/api/asteroid/icecast-status'); - if (!response.ok) { + const response = await fetch('/api/asteroid/partial/now-playing-inline'); + const contentType = response.headers.get("content-type"); + + if (!contentType.includes('text/plain')) { + console.error('Unexpected content type:', contentType); return; } - const result = await response.json(); + const nowPlayingText = await response.text(); + const nowPlayingEl = document.getElementById('live-now-playing'); - // Handle Radiance API response format - const data = result.data || result; - - // Sources are nested in icestats - const sources = data.icestats?.source; - - if (sources) { - const mainStream = Array.isArray(sources) - ? sources.find(s => s.listenurl?.includes('/asteroid.aac') || s.listenurl?.includes('/asteroid.mp3')) - : sources; - - if (mainStream && mainStream.title) { - const nowPlayingEl = document.getElementById('live-now-playing'); - if (nowPlayingEl) { - const parts = mainStream.title.split(' - '); - const artist = parts[0] || 'Unknown'; - const track = parts.slice(1).join(' - ') || 'Unknown'; - nowPlayingEl.textContent = `${artist} - ${track}`; - } - } + if (nowPlayingEl) { + nowPlayingEl.textContent = nowPlayingText; } } catch (error) { console.error('Could not fetch stream info:', error); + const nowPlayingEl = document.getElementById('live-now-playing'); + if (nowPlayingEl) { + nowPlayingEl.textContent = 'Error loading stream info'; + } } } diff --git a/stream-control.lisp b/stream-control.lisp index 7ae3c7e..3bad8ee 100644 --- a/stream-control.lisp +++ b/stream-control.lisp @@ -72,8 +72,8 @@ (defun convert-to-docker-path (host-path) "Convert host file path to Docker container path" - ;; Replace /home/glenn/Projects/Code/asteroid/music/library/ with /app/music/ - (let ((library-prefix "/home/glenn/Projects/Code/asteroid/music/library/")) + ;; Replace the music library path with /app/music/ + (let ((library-prefix (namestring *music-library-path*))) (if (and (stringp host-path) (>= (length host-path) (length library-prefix)) (string= host-path library-prefix :end1 (length library-prefix)))