Refactor song polling logic for adaptive delays and add tsconfig.json for TypeScript configuration
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m23s

This commit is contained in:
Cameron Redmore 2025-08-08 17:59:21 +01:00
parent 6714a4763a
commit 84f9502b4a
No known key found for this signature in database
2 changed files with 66 additions and 31 deletions

View file

@ -1,4 +1,4 @@
import { Elysia, t } from 'elysia'; import { Elysia } from 'elysia';
import { staticPlugin } from '@elysiajs/static'; import { staticPlugin } from '@elysiajs/static';
import path from 'path'; import path from 'path';
@ -15,6 +15,7 @@ interface LastSong {
// Current song state // Current song state
let currentSong: LastSong | null = null; let currentSong: LastSong | null = null;
let lastSongId: string | null = null; let lastSongId: string | null = null;
let pollTimer: ReturnType<typeof setTimeout> | null = null;
// WebSocket connections // WebSocket connections
const connections = new Set<any>(); const connections = new Set<any>();
@ -54,38 +55,51 @@ async function fetchLastFmSong(): Promise<LastSong | null> {
async function checkAndUpdateSong(): Promise<void> { async function checkAndUpdateSong(): Promise<void> {
const newSong = await fetchLastFmSong(); const newSong = await fetchLastFmSong();
if (!newSong) return; // Default to not currently playing if we couldn't fetch anything
let nowPlaying = false;
// Create a unique identifier for the song if (newSong) {
const newSongId = `${newSong.artist}-${newSong.name}-${newSong.nowPlaying}`; // Create a unique identifier for the song (include nowPlaying state)
const newSongId = `${newSong.artist}-${newSong.name}-${newSong.nowPlaying}`;
// Check if song has changed // Check if song has changed
if (newSongId !== lastSongId) { if (newSongId !== lastSongId) {
console.log('Song changed:', newSong.name, 'by', newSong.artist); console.log('Song changed:', newSong.name, 'by', newSong.artist);
currentSong = newSong; // Update state and notify clients
lastSongId = newSongId; currentSong = newSong;
lastSongId = newSongId;
// Notify all connected WebSocket clients const message = JSON.stringify({
const message = JSON.stringify({ type: 'song-update',
type: 'song-update', data: newSong
data: newSong });
});
connections.forEach(ws => { connections.forEach(ws => {
try { try {
ws.send(message); ws.send(message);
} catch (error) { } catch (error) {
console.error('Error sending to WebSocket client:', error); console.error('Error sending to WebSocket client:', error);
connections.delete(ws); connections.delete(ws);
} }
}); });
} else {
// Keep currentSong updated even if no change to ID (e.g., image/url may vary)
currentSong = newSong;
}
nowPlaying = !!newSong.nowPlaying;
} else {
// If fetch failed, keep existing currentSong and fall back to slower polling
nowPlaying = currentSong?.nowPlaying ?? false;
} }
// Schedule next poll based on whether a track is currently playing
const delayMs = nowPlaying ? 5000 : 30000;
if (pollTimer) clearTimeout(pollTimer);
pollTimer = setTimeout(checkAndUpdateSong, delayMs);
} }
// Start polling Last.fm every second // Kick off adaptive polling with an immediate check
setInterval(checkAndUpdateSong, 1000);
// Initial fetch
checkAndUpdateSong(); checkAndUpdateSong();
// Determine static assets path - adjust for compiled executable // Determine static assets path - adjust for compiled executable

21
tsconfig.json Normal file
View file

@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"noEmit": true,
"skipLibCheck": true,
"types": [
"bun-types",
"vite/client"
],
"jsx": "react-jsx",
"allowJs": true,
"resolveJsonModule": true
},
"include": [
"src",
"vite.config.*"
]
}