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
This commit is contained in:
parent
4d0b54f7d6
commit
b3fd00cb4d
|
|
@ -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")))
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
Loading…
Reference in New Issue