diff --git a/.gitignore b/.gitignore index d23d9c1..d0ef245 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules bun.lock .env +logs/ \ No newline at end of file diff --git a/package.json b/package.json index 8240d4f..b92f1d3 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "typescript": "^5.8.2" }, "dependencies": { - "ejs": "^3.1.10" + "ejs": "^3.1.10", + "node-vibrant": "^4.0.3" } } diff --git a/src/routes/img.ts b/src/routes/img.ts new file mode 100644 index 0000000..18de14a --- /dev/null +++ b/src/routes/img.ts @@ -0,0 +1,37 @@ +import { Vibrant } from "node-vibrant/node"; + +const routeDef: RouteDef = { + method: "GET", + accepts: "*/*", + returns: "application/json", +}; + +async function handler(request: ExtendedRequest): Promise { + const req = await fetch(request.query.url); + + if (!req.ok) { + return Response.json({ error: "Failed to fetch image" }, { status: 500 }); + } + + const type = req.headers.get("content-type") + if (!type?.includes("image/")) { + return Response.json({ error: "Not an image" }, { status: 400 }); + } + + const imageBuffer = await req.arrayBuffer() + + const colors = await Vibrant.from(Buffer.from(imageBuffer)).getPalette(); + + return new Response(Bun.gzipSync(JSON.stringify({ + img: `data:${type};base64,${Buffer.from(imageBuffer).toString("base64")}`, + colors, + })), { + headers: { + "Content-Type": "application/json", + "Content-Encoding": "gzip", + "Cache-Control": "public, max-age=31536000, immutable", + } + }) +} + +export { handler, routeDef };