Merge branch 'main' into main

This commit is contained in:
SteelTech 2025-04-06 22:32:07 +00:00
commit b2c79c2b39
3 changed files with 78 additions and 7 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
/node_modules
bun.lock
.env
logs/

View file

@ -10,13 +10,13 @@
"cleanup": "rm -rf logs node_modules bun.lockdb"
},
"devDependencies": {
"@eslint/js": "^9.23.0",
"@types/bun": "^1.2.6",
"@eslint/js": "^9.24.0",
"@types/bun": "^1.2.8",
"@types/ejs": "^3.1.5",
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"eslint": "^9.23.0",
"eslint-plugin-prettier": "^5.2.5",
"@typescript-eslint/eslint-plugin": "^8.29.0",
"@typescript-eslint/parser": "^8.29.0",
"eslint": "^9.24.0",
"eslint-plugin-prettier": "^5.2.6",
"eslint-plugin-promise": "^7.2.1",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-unicorn": "^56.0.1",
@ -25,10 +25,11 @@
"prettier": "^3.5.3"
},
"peerDependencies": {
"typescript": "^5.8.2"
"typescript": "^5.8.3"
},
"dependencies": {
"ejs": "^3.1.10",
"node-vibrant": "^4.0.3",
"marked": "^15.0.7"
}
}

69
src/routes/api/colors.ts Normal file
View file

@ -0,0 +1,69 @@
import { fetch } from "bun";
import { Vibrant } from "node-vibrant/node";
type Palette = Awaited<ReturnType<typeof Vibrant.prototype.getPalette>>;
const routeDef: RouteDef = {
method: "GET",
accepts: "*/*",
returns: "application/json",
};
async function handler(request: ExtendedRequest): Promise<Response> {
const { url } = request.query;
if (!url) {
return Response.json({ error: "URL is required" }, { status: 400 });
}
if (typeof url !== "string" || !url.startsWith("http")) {
return Response.json({ error: "Invalid URL" }, { status: 400 });
}
let res: Response;
try {
res = await fetch(url);
} catch {
return Response.json(
{ error: "Failed to fetch image" },
{ status: 500 },
);
}
if (!res.ok) {
return Response.json(
{ error: "Image fetch returned error" },
{ status: res.status },
);
}
const type: string | null = res.headers.get("content-type");
if (!type?.startsWith("image/")) {
return Response.json({ error: "Not an image" }, { status: 400 });
}
const buffer: Buffer = Buffer.from(await res.arrayBuffer());
const base64: string = buffer.toString("base64");
const colors: Palette = await Vibrant.from(buffer).getPalette();
const payload: {
img: string;
colors: Palette;
} = {
img: `data:${type};base64,${base64}`,
colors,
};
const compressed: Uint8Array = Bun.gzipSync(JSON.stringify(payload));
return new Response(compressed, {
headers: {
"Content-Type": "application/json",
"Content-Encoding": "gzip",
"Cache-Control": "public, max-age=31536000, immutable",
"Access-Control-Allow-Origin": "*",
},
});
}
export { handler, routeDef };