diff --git a/README.md b/README.md index 633f6cf..da35c0c 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,21 @@ # BluGlo -A Fortnite STW taxibot manager with a real-time web dashboard and interactive CLI. +A Fortnite STW taxibot manager with an interactive CLI. ## Installation ```bash -npm install +bun install ``` ## Run ```bash -npm start +bun start ``` This starts: -- Dashboard: `http://localhost:3000` - Interactive CLI in the same terminal ## CLI commands @@ -45,7 +44,6 @@ You can use just the first 8 characters of an `accountId` in CLI commands. - `bot.auth` - `bot.timings` - `bot.reconnect` -- `dashboard` - `dataFile` ### Auth flow used by `/add` diff --git a/config.json b/config.json index 3b25a3d..232c03a 100644 --- a/config.json +++ b/config.json @@ -41,10 +41,5 @@ "xmppMaxConnectionRetries": 3 } }, - "dashboard": { - "port": 3000, - "host": "0.0.0.0", - "title": "BluGlo Dashboard" - }, "dataFile": "./data/accounts.json" } diff --git a/package.json b/package.json index 26370d5..4aad7a5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bluglo-stw", "version": "1.0.0", - "description": "A Fortnite STW taxibot manager with a real-time web dashboard and interactive CLI.", + "description": "A Fortnite STW taxibot manager with an interactive CLI.", "type": "module", "main": "dist/index.js", "scripts": { diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 0866188..0000000 --- a/public/index.html +++ /dev/null @@ -1,684 +0,0 @@ - - - - - - BluGlo — Dashboard - - - - - -
-
-
-
šŸš•
-
-
BLUGLO
-
Bot dashboard
-
-
- -
-
-
- Connecting... -
-
0 bots
-
-
-
- - - -
- -
-
-
šŸš•
-
Select a bot
-
Choose one from the list to see its live info, power stats, taxi counters and uptime.
-
-
-
-
- - - - diff --git a/src/bot.ts b/src/bot.ts index a0bc17d..3a51a24 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -190,7 +190,7 @@ export class BluGlo { } /** - * Updates the in-memory presence and broadcasts it to the dashboard. + * Updates the in-memory presence and emits runtime status events. */ public setPresence(presence: PresenceValue, status: string): void { this.presence = presence; diff --git a/src/bot/constants.ts b/src/bot/constants.ts index 0759281..8a41956 100644 --- a/src/bot/constants.ts +++ b/src/bot/constants.ts @@ -1,5 +1,5 @@ /** - * High-level runtime presence shown in the dashboard and CLI. + * High-level runtime presence shown in the CLI and runtime events. * * @see https://fnbr.js.org * @see https://github.com/fnbrjs/fnbr.js diff --git a/src/cli.ts b/src/cli.ts index 484aaa6..4dc6cc3 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -687,7 +687,6 @@ function compactLog(text: string): string { .trim(); value = value - .replace(/Dashboard at .*/i, "Dashboard ready") .replace(/Loading (\d+) account\(s\)\.\.\./i, "Loading $1 account(s)") .replace(/No saved accounts found\. Use \/add to add one\./i, "No saved accounts") .replace(/Exchanging authorization code with .*?/i, "Exchanging auth code") diff --git a/src/config.ts b/src/config.ts index 494d971..c00324b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -39,12 +39,6 @@ export const BOT = { }, } as const; -export const DASH = { - port: config.dashboard?.port ?? 3000, - host: config.dashboard?.host ?? "0.0.0.0", - title: config.dashboard?.title ?? "BluGlo Dashboard", -} as const; - export const TIMINGS = { initTimeoutMs: timings.initTimeoutMs ?? 10000, postAcceptDelayMs: timings.postAcceptDelayMs ?? 1000, diff --git a/src/index.ts b/src/index.ts index 4fd8cfd..432a64b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,6 @@ import { startCLI } from "./cli.js"; import { log } from "./events.js"; import { BotManager } from "./manager.js"; -import { startServer } from "./server.js"; async function main(): Promise { console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); @@ -10,7 +9,6 @@ async function main(): Promise { const manager = new BotManager(); - startServer(manager); manager.loadAll(); startCLI(manager); diff --git a/src/server.ts b/src/server.ts deleted file mode 100644 index 2c163dc..0000000 --- a/src/server.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { existsSync, readFileSync } from "node:fs"; -import { createServer, type ServerResponse } from "node:http"; -import { dirname, extname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; - -import { DASH } from "./config.js"; -import { bus, log } from "./events.js"; -import type { BotManager } from "./manager.js"; - -const __dirname = dirname(fileURLToPath(import.meta.url)); -const publicDir = resolve(__dirname, "../public"); - -const MIME: Record = { - ".html": "text/html; charset=utf-8", - ".js": "application/javascript; charset=utf-8", - ".css": "text/css; charset=utf-8", - ".json": "application/json", - ".ico": "image/x-icon", -}; - -const sseClients = new Set(); - -/** - * Broadcasts dashboard-safe runtime updates to every connected SSE client. - * Logs are intentionally excluded so the browser only receives state changes. - */ -export function broadcast(event: string, data: unknown): void { - const chunk = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`; - for (const response of sseClients) { - try { - response.write(chunk); - } catch { - sseClients.delete(response); - } - } -} - -export function startServer(manager: BotManager) { - const events = ["status", "profile", "invite", "joined", "left", "friend", "removed"]; - for (const eventName of events) { - bus.on(eventName, (data) => broadcast(eventName, data)); - } - - const server = createServer((req, res) => { - const url = new URL( - req.url ?? "/", - `http://${req.headers.host ?? `${DASH.host}:${DASH.port}`}`, - ); - const pathname = url.pathname; - - if (pathname === "/events") { - res.writeHead(200, { - "Content-Type": "text/event-stream", - "Cache-Control": "no-cache", - Connection: "keep-alive", - "Access-Control-Allow-Origin": "*", - }); - res.flushHeaders?.(); - - const snapshot = manager.getSnapshot(); - res.write(`event: snapshot\ndata: ${JSON.stringify(snapshot)}\n\n`); - - const keepalive = setInterval(() => { - try { - res.write(": ping\n\n"); - } catch { - clearInterval(keepalive); - } - }, 15000); - - sseClients.add(res); - req.on("close", () => { - clearInterval(keepalive); - sseClients.delete(res); - }); - return; - } - - if (pathname === "/api/bots" && req.method === "GET") { - const data = JSON.stringify(manager.getSnapshot()); - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(data); - return; - } - - const filePath = - pathname === "/" || pathname === "/index.html" - ? resolve(publicDir, "index.html") - : resolve(publicDir, pathname.slice(1)); - - if (!filePath.startsWith(publicDir)) { - res.writeHead(403); - res.end("Forbidden"); - return; - } - - if (!existsSync(filePath)) { - res.writeHead(404); - res.end("Not found"); - return; - } - - const ext = extname(filePath); - const mime = MIME[ext] ?? "application/octet-stream"; - - try { - const content = readFileSync(filePath); - res.writeHead(200, { "Content-Type": mime }); - res.end(content); - } catch { - res.writeHead(500); - res.end("Internal error"); - } - }); - - server.listen(DASH.port, DASH.host, () => { - log( - null, - "ok", - `Dashboard at http://${DASH.host === "0.0.0.0" ? "localhost" : DASH.host}:${DASH.port}`, - ); - }); - - return server; -} diff --git a/src/types.ts b/src/types.ts index b417c12..7136fa9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -61,11 +61,6 @@ export interface ConfigShape { timings?: Record; reconnect?: Record; }; - dashboard?: { - port?: number; - host?: string; - title?: string; - }; dataFile?: string; }