initial commit
This commit is contained in:
commit
abcee32d38
6 changed files with 176 additions and 0 deletions
85
index.js
Normal file
85
index.js
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import express from "express";
|
||||
import http from "http";
|
||||
import { WebSocketServer } from "ws";
|
||||
import cors from "cors";
|
||||
import pkg from "pg";
|
||||
|
||||
const { Pool } = pkg;
|
||||
|
||||
const app = express();
|
||||
const PORT = 3000;
|
||||
|
||||
// Setup Postgres connection pool
|
||||
const pool = new Pool({
|
||||
connectionString: process.env.DATABASE_URL || "neverleavetheconnectionstringhereforproduction",
|
||||
});
|
||||
|
||||
app.use(cors());
|
||||
|
||||
// HTTP GET /games/:id → return game info from DB
|
||||
app.get("/games/:id", async (req, res) => {
|
||||
const gameId = req.params.id;
|
||||
try {
|
||||
const result = await pool.query("SELECT info FROM items WHERE id = $1", [gameId]);
|
||||
if (result.rows.length === 0) {
|
||||
return res.redirect(302, "https://engine.battlesnake.com");
|
||||
// return res.status(404).json({ error: "Game not found" });
|
||||
|
||||
}
|
||||
res.json(result.rows[0].info); // send back the JSONB field
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Database error" });
|
||||
}
|
||||
});
|
||||
|
||||
// Create HTTP server and attach WebSocket server
|
||||
const server = http.createServer(app);
|
||||
const wss = new WebSocketServer({ server });
|
||||
|
||||
// Helper to match the path pattern
|
||||
function matchGameEventsPath(url) {
|
||||
if (!url) return null;
|
||||
const match = url.match(/^\/games\/([^\/]+)\/events$/);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
wss.on("connection", async (ws, req) => {
|
||||
const gameId = matchGameEventsPath(req.url);
|
||||
if (!gameId) {
|
||||
ws.close();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`WS client connected for game: ${gameId}`);
|
||||
|
||||
try {
|
||||
// Grab frames array from DB
|
||||
const result = await pool.query("SELECT frames FROM items WHERE id = $1", [gameId]);
|
||||
if (result.rows.length === 0) {
|
||||
ws.send(JSON.stringify({ error: "Game not found" }));
|
||||
ws.close();
|
||||
return;
|
||||
}
|
||||
|
||||
const frames = result.rows[0].frames || [];
|
||||
|
||||
// Stream frames one by one with delay
|
||||
frames.forEach((frame, i) => {
|
||||
setTimeout(() => {
|
||||
if (ws.readyState === ws.OPEN) {
|
||||
ws.send(JSON.stringify(frame));
|
||||
}
|
||||
}, i * 5); // staggered delay
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
ws.send(JSON.stringify({ error: "Database error" }));
|
||||
ws.close();
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(PORT, "0.0.0.0", () => {
|
||||
console.log(`Server running at http://localhost:${PORT} (HTTP + WebSocket)`);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue