import express from "express"; import expressWs from "express-ws"; import { MediaPlayer } from "./MediaPlayer"; const app = express(); app.use(express.json()); expressWs(app); const apiRouter = express.Router(); const mediaPlayer = new MediaPlayer(); const withErrorHandling = (func: (req: any, res: any) => Promise) => { return async (req: any, res: any) => { try { await func(req, res); } catch (error: any) { res.status(500).send(JSON.stringify({ success: false, error: error.message })); } }; }; apiRouter.get("/playlist", withErrorHandling(async (req, res) => { const playlist = await mediaPlayer.getPlaylist(); res.send(playlist); })); apiRouter.post("/playlist", withErrorHandling(async (req, res) => { const { url } = req.body as { url: string }; await mediaPlayer.append(url); res.send(JSON.stringify({ success: true })); })); apiRouter.delete("/playlist/:index", withErrorHandling(async (req, res) => { const { index } = req.params as { index: string }; await mediaPlayer.deletePlaylistItem(parseInt(index)); res.send(JSON.stringify({ success: true })); })); apiRouter.post("/play", withErrorHandling(async (req, res) => { await mediaPlayer.play(); res.send(JSON.stringify({ success: true })); })); apiRouter.post("/pause", withErrorHandling(async (req, res) => { await mediaPlayer.pause(); res.send(JSON.stringify({ success: true })); })); apiRouter.post("/skip", withErrorHandling(async (req, res) => { await mediaPlayer.skip(); res.send(JSON.stringify({ success: true })); })); apiRouter.post("/previous", withErrorHandling(async (req, res) => { await mediaPlayer.previous(); res.send(JSON.stringify({ success: true })); })); apiRouter.get("/nowplaying", withErrorHandling(async (req, res) => { const nowPlaying = await mediaPlayer.getNowPlaying(); const currentFile = await mediaPlayer.getCurrentFile(); const pauseState = await mediaPlayer.getPauseState(); const volume = await mediaPlayer.getVolume(); const idle = await mediaPlayer.getIdle(); res.send(JSON.stringify({ success: true, nowPlaying: nowPlaying, isPaused: pauseState, volume: volume, isIdle: idle, currentFile: currentFile })); })); apiRouter.post("/volume", withErrorHandling(async (req, res) => { const { volume } = req.body as { volume: number }; await mediaPlayer.setVolume(volume); res.send(JSON.stringify({ success: true })); })); apiRouter.ws("/events", (ws, req) => { console.log("Events client connected"); mediaPlayer.subscribe(ws); ws.on("close", () => { console.log("Events client disconnected"); mediaPlayer.unsubscribe(ws); }); }); // Serve static files for React app (after building) app.use(express.static("dist/frontend")); // Mount API routes under /api app.use("/api", apiRouter); // Serve React app for all other routes (client-side routing) app.get("*", (req, res) => { res.sendFile("dist/frontend/index.html", { root: "." }); }); app.listen(3000, () => { console.log("Server is running on port 3000"); });