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>();
@ -53,39 +54,52 @@ async function fetchLastFmSong(): Promise<LastSong | null> {
// Function to check for song changes and notify clients // Function to check for song changes and notify clients
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
const newSongId = `${newSong.artist}-${newSong.name}-${newSong.nowPlaying}`; if (newSong) {
// Create a unique identifier for the song (include nowPlaying state)
// Check if song has changed const newSongId = `${newSong.artist}-${newSong.name}-${newSong.nowPlaying}`;
if (newSongId !== lastSongId) {
console.log('Song changed:', newSong.name, 'by', newSong.artist); // Check if song has changed
currentSong = newSong; if (newSongId !== lastSongId) {
lastSongId = newSongId; console.log('Song changed:', newSong.name, 'by', newSong.artist);
// Update state and notify clients
// Notify all connected WebSocket clients currentSong = newSong;
const message = JSON.stringify({ lastSongId = newSongId;
type: 'song-update',
data: newSong const message = JSON.stringify({
}); type: 'song-update',
data: newSong
connections.forEach(ws => { });
try {
ws.send(message); connections.forEach(ws => {
} catch (error) { try {
console.error('Error sending to WebSocket client:', error); ws.send(message);
connections.delete(ws); } catch (error) {
} console.error('Error sending to WebSocket client:', error);
}); 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.*"
]
}