import { globSync } from "glob"; import crypto from "crypto"; import { createReadStream } from "fs"; import { readFile, writeFile } from "fs/promises"; const config = JSON.parse(await readFile(`importable/config.json`, `utf8`)); async function hashFile(path) { return new Promise((resolve) => { const stream = createReadStream(path); const hash = crypto.createHash(`sha1`); hash.setEncoding(`hex`); stream.on(`end`, () => { hash.end(); resolve(hash.read()); }); stream.pipe(hash); }); }; async function main() { const imageList = globSync( `foundry/public/icons/**/*`, { nodir: true, ignore: config.ignorePatterns, }); const images = {}; const allTags = {}; for (const path of imageList) { if (config.skipFiles.some(file => path.endsWith(file))) continue; const hash = await hashFile(path); const filename = path.split(`/`).at(-1); const tags = Array.from(new Set( path .replace(`foundry/public/icons/`, ``) .replace(/\.[a-z]+$/i, ``) .replaceAll(`-`, `/`) .split(`/`) .map(tag => config.replacements[tag] ?? tag) .filter(tag => !config.removals.includes(tag)) )); tags.forEach(t => { allTags[t] ??= 0; allTags[t]++; }); images[hash] = { name: filename, tags, artists: [`FVTT`], path: path.replace(`foundry/public/`, ``), external: true }; }; const sortedTags = Object.entries(allTags) .sort((a,b) => a[0].localeCompare(b[0])) // Remove all of the tags that have too low of frequency const removeTags = new Set(); for (const [tag, count] of sortedTags) { if (count <= config.min_tag_frequency) { removeTags.add(tag); }; }; for (const image of Object.values(images)) { image.tags = image.tags.filter(t => !removeTags.has(t)); }; console.log(`Removed ${removeTags.size} tags from images due to frequency requirements.`); await writeFile( `importable/images.json`, JSON.stringify(images), ); }; main();