picvatar/src/index.ts
2024-06-16 18:42:51 +02:00

90 lines
2.9 KiB
TypeScript

import { createCanvas, loadImage } from "canvas";
import { fetchScript, extractDataFromScript, getAsset, dirname } from "./util.js";
import { writeFile } from "fs/promises";
import path from "path";
const MAKER_ID = "1904634";
await fetchScript(MAKER_ID);
const { config, commonImages, cdnRoot, partsId2Index } = await extractDataFromScript(MAKER_ID);
type UrlsList = { colorId: string, url: string };
type LayerList = { layerId: string, urls: UrlsList[] };
type ItemList = { itemId: string, layers: LayerList[] };
type LayerColorList = { layerIndex: number, cpId: string, colors: string[] };
type CategoryList = { cpId: string, pId: string, items: ItemList[], index: number };
const items: ItemList[] = [];
const categories: CategoryList[] = [];
const layerColors: LayerColorList[] = [];
for (const c in config.pList) {
const category = config.pList[c];
layerColors.push({
layerIndex: Number(c),
cpId: category.cpId,
colors: config.cpList[category.cpId].map((c) => c.cId.toString()),
});
const localItems: ItemList[] = [];
for (const item of category.items) {
const id = item.itmId;
const obj = commonImages[id];
const layers: LayerList[] = [];
for (const layer of category.lyrs) {
if (!obj[layer]) continue; // Not every entry uses all layers
const variants = Object.keys(obj[layer]);
const urls: UrlsList[] = variants.map((v) => ({
colorId: v,
url: cdnRoot + obj[layer][v].url,
}));
layers.push({ layerId: layer.toString(), urls });
}
localItems.push({ itemId: id.toString(), layers: layers });
}
items.push(...localItems);
categories.push({ cpId: category.cpId, pId: category.pId.toString(), items: localItems, index: partsId2Index[category.pId.toString()] });
}
const canvas = createCanvas(config.w, config.h);
const ctx = canvas.getContext('2d');
console.log(categories);
const images: { layer: number, url: string }[] = [];
for (const category of categories.sort((a, b) => b.index - a.index)) {
const colors = layerColors.find((c) => c.cpId == category.cpId)!.colors;
const colorId = colors[Math.floor(Math.random() * colors.length)];
const item = category.items[Math.floor(Math.random() * category.items.length)];
for (const layer of item.layers) {
const url = (layer.urls.find((i) => i.colorId == colorId) ?? layer.urls?.[0])?.url;
if (url) {
images.push({ layer: Number(layer.layerId), url });
}
}
}
// Retains the correct order
const imgPaths = await Promise.all(
images
.sort((a, b) => config.lyrList[a.layer] - config.lyrList[b.layer])
.map((img) => getAsset(img.url))
);
for (const path of imgPaths) {
const img = await loadImage(path);
ctx.drawImage(img, 0, 0, config.w, config.h);
}
await writeFile(path.join(dirname, "..", "cache", MAKER_ID + ".png"), canvas.toBuffer());