import { Application, Router } from "@oak/oak"; import { XMLParser } from "npm:fast-xml-parser"; const router = new Router(); let wsClients: WebSocket[] = []; router.get("/", (context) => { if (context.isUpgradable) { const ws = context.upgrade(); ws.onopen = () => wsClients.push(ws); ws.onclose = () => wsClients = wsClients.filter((client) => client != ws); } }); router .get("/statusline", async (ctx) => { ctx.response.body = await Deno.readFile("web/statusline.html"); }) .get("/statusline.js", async (ctx) => { ctx.response.body = await Deno.readFile("web/statusline.js"); }) .get("/style.css", async (ctx) => { ctx.response.body = await Deno.readFile("web/style.css"); }); const app = new Application(); app.use(router.routes()); app.use(router.allowedMethods()); app.addEventListener("listen", ({ hostname, port }) => { console.log(`Start listening on ${hostname}:${port}`); }); app.listen({ port: 8012 }); const topic = "Something Fun For Everyone With Streamboy!!!!!!!! git.jeevio.xyz/jeeves/streamboy"; setInterval(async () => { const songinfo = await getVlcSongInfo(); const data = { blocks: [ { text: topic, color: "#ffffff" }, { text: `♪ ${songinfo.title} - ${songinfo.artist}`, color: "#ffffff" }, ], }; for (const ws of wsClients) { // ws.send( // `${topic} | ♪ ${songinfo.title} - ${songinfo.artist} | `, // ); // ws.send(JSON.stringify(data)); } }, 900); interface SongInfo { title?: string; artist?: string; album?: string; } async function getVlcSongInfo(): Promise { const parser = new XMLParser({ ignoreAttributes: false }); const password = "1234"; const res = await fetch("http://localhost:8080/requests/status.xml", { headers: { authorization: `Basic ${btoa(`:${password}`)}` }, }); const json = parser.parse(await res.text()); const songinfo: SongInfo = {}; for (const category of json.root.information.category) { if (category["@_name"] != "meta") continue; for (const property of category.info) { if (property["@_name"] == "title") { songinfo.title = processBadXmlString(property["#text"]); } else if (property["@_name"] == "artist") { songinfo.artist = processBadXmlString(property["#text"]); } else if (property["@_name"] == "album") { songinfo.album = processBadXmlString(property["#text"]); } } } return songinfo; } function processBadXmlString(str: string): string { let newStr = str; while (true) { const amp = newStr.indexOf("&#"); if (amp > 0) { const semi = newStr.indexOf(";", amp); if (semi > 0) { const int = String.fromCharCode(parseInt(newStr.slice(amp + 2, semi))); newStr = newStr.replace(newStr.slice(amp, semi + 1), int); } else break; } else break; } return newStr; }