ipv4.army/index.ts
seth cf21a56d7a
Some checks failed
Code quality checks / biome (push) Failing after 7s
Add API endpoint to return request headers as a gzipped JSON response
2025-05-04 14:45:35 -04:00

268 lines
No EOL
7.9 KiB
TypeScript

import { build, serve, gzipSync, file, type BunRequest, gc } from "bun";
import pkg from "./package.json";
const development = process.env.NODE_ENV === "development";
let heartrate = 0;
let lanyard = {};
require("node:fs/promises").rm("./dist", { recursive: true, force: true }).catch(() => {
// ignore
});
const buildWeb = async () => {
return await build({
entrypoints: ['./src/index.html'],
outdir: './dist',
minify: !development,
sourcemap: (development ? "inline" : "none"),
splitting: true,
publicPath: "/assets/",
loader: {
".woff2": "file"
},
})
}
if (!development) {
await buildWeb()
}
const webserver = serve({
routes: {
"/": async () => {
if (development) {
await buildWeb()
}
return new Response(gzipSync(await file("./dist/index.html").arrayBuffer()), {
headers: {
"Content-Type": "text/html",
"Cache-Control": "no-cache",
"Content-Encoding": "gzip",
}
})
},
"/assets/:file": async (req: BunRequest<"/assets/:file">) => {
const reqFile = file(`./dist/${req.params.file}`)
return new Response(gzipSync(await reqFile.arrayBuffer()), {
headers: {
"Content-Type": reqFile.type,
"Cache-Control": "public, max-age=31536000",
"Content-Encoding": "gzip",
}
})
},
"/public/:file": async (req: BunRequest<"/public/:file">) => {
const reqFile = file(`./public/${req.params.file}`)
let fileRes = await reqFile.text()
fileRes = fileRes.replace("{{LANYARD}}", `${JSON.stringify({ example: "lanyard data" })}`)
fileRes = fileRes.replace("{{HYPERATE}}", `${JSON.stringify({ example: "hyperate data" })}`)
return new Response(gzipSync(fileRes), {
headers: {
"Content-Type": reqFile.type,
"Cache-Control": "public, max-age=31536000",
"Content-Encoding": "gzip",
}
})
},
"/public/font/:file": async (req: BunRequest<"/public/font/:file">) => {
const reqFile = file(`./public/font/${req.params.file}`)
return new Response(gzipSync(await reqFile.arrayBuffer()), {
headers: {
"Content-Type": reqFile.type,
"Cache-Control": "public, max-age=31536000",
"Content-Encoding": "gzip",
}
})
},
"/api/server": () => {
const string = JSON.stringify(process)
const json = JSON.parse(string)
// clear possibly data that could be sensitive
json.argv = {}
json.debugPort = 0
json.env = {}
json.execArgv = []
json.execPath = ""
json.stderr = {}
json.stdin = {}
json.stdout = {}
json.title = ""
json.availableMemory = process.availableMemory()
json.constrainedMemory = process.constrainedMemory()
json.cpuUsage = process.cpuUsage()
json.memoryUsage = process.memoryUsage()
json.uptime = process.uptime()
json.package = pkg
return new Response(gzipSync(JSON.stringify({ data: json })), {
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-cache",
"Content-Encoding": "gzip",
}
})
},
"/api/health": () => {
return new Response(gzipSync(JSON.stringify({ data: "ok" })), {
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-cache",
"Content-Encoding": "gzip",
}
})
},
"/api/ws": (req, server) => {
if (server.upgrade(req)) {
return;
}
return new Response("Upgrade failed", { status: 500 });
},
"/api/gc": async (req, server) => {
gc(true)
return new Response(gzipSync(JSON.stringify({ data: "triggered" })), {
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-cache",
"Content-Encoding": "gzip",
}
})
},
"/api/script.js": async () => {
const req = await fetch("https://plausible.creations.works/js/script.js")
const script = await req.text()
return new Response(gzipSync(script), {
headers: {
"Content-Type": "application/javascript",
"Content-Encoding": "gzip",
"Cache-Control": "public, max-age=31536000",
}
})
},
"/api/script": async (req) => {
const request = new Request(req);
request.headers.delete('cookie');
return await fetch("https://plausible.creations.works/api/event", request);
},
"/api/headers": async (req) => {
return new Response(gzipSync(JSON.stringify({ headers: req.headers })), {
headers: {
"Content-Type": "application/json",
"Content-Encoding": "gzip",
"Cache-Control": "no-cache",
}
})
}
},
websocket: {
open: async (ws) => {
ws.subscribe("lanyard");
ws.send(JSON.stringify({ type: "lanyard", data: lanyard }), true);
ws.subscribe("hyperate");
ws.send(JSON.stringify({ type: "hyperate", data: { hr: heartrate } }), true);
},
message: async (ws, message) => {
ws.send(JSON.stringify({ type: "echo", data: message }), true)
}
},
development,
port: 2056
});
const lanyardSocket = new WebSocket("wss://lanyard.creations.works/socket");
const setLanyard = (data: object) => {
lanyard = data;
return webserver.publish("lanyard", JSON.stringify({ type: "lanyard", data }), true);
}
lanyardSocket.onmessage = ({ data }) => {
data = JSON.parse(data);
switch (data.op) {
case 0: {
setLanyard(data.d)
break;
}
case 1: {
lanyardSocket.send(JSON.stringify({
op: 2,
d: {
subscribe_to_id: "1273447359417942128"
}
}))
break;
}
}
}
const hyperate = new WebSocket(
"wss://app.hyperate.io/socket/websocket?token=wv39nM6iyrNJulvpmMQrimYPIXy2dVrYRjkuHpbRapKT2VSh65ngDGHdCdCtmEN9",
);
let hrTimeout: ReturnType<typeof setTimeout>;
const setHeartrate = async (hr: number) => {
heartrate = hr;
return webserver.publish("hyperate", JSON.stringify({ type: "hyperate", data: { hr } }), true);
}
const setHrInterval = () => {
hrTimeout = setTimeout(() => {
setHeartrate(0);
}, 6000);
};
hyperate.onopen = () => {
hyperate.send(
JSON.stringify({
topic: "hr:0BCA",
event: "phx_join",
payload: {},
ref: 0,
}),
);
setInterval(() => {
hyperate.send(
JSON.stringify({
topic: "phoenix",
event: "heartbeat",
payload: {},
ref: 0,
}),
);
}, 10000);
return setHrInterval();
};
hyperate.onmessage = ({ data }) => {
const { event, payload } = JSON.parse(data);
switch (event) {
case "hr_update": {
clearTimeout(hrTimeout);
setHrInterval();
setHeartrate(payload.hr);
break;
}
default: {
break;
}
}
};