diff --git a/.forgejo/workflows/draft-release.yaml b/.forgejo/workflows/draft-release.yaml index 648f84f..100ca8c 100644 --- a/.forgejo/workflows/draft-release.yaml +++ b/.forgejo/workflows/draft-release.yaml @@ -29,7 +29,7 @@ jobs: LATEST_URL: "${{forgejo.server_url}}/${{forgejo.repository}}/releases/download/latest/${{env.MANIFEST}}" - name: Set up default storage - run: mkdir -p storage/db && mv importable/*.json storage/db + run: mkdir -p storage/db && mv importable/artists.json storage/db && mv importable/images.json storage/db - name: Compress files run: zip -r release.zip langs module styles storage templates README.md assets LICENSE ${{env.MANIFEST}} diff --git a/importable/config.json b/importable/config.json new file mode 100644 index 0000000..bbfbdb4 --- /dev/null +++ b/importable/config.json @@ -0,0 +1,150 @@ +{ + "min_tag_frequency": 3, + "ignorePatterns": [ + "**/svg/**", + "**/dice/**" + ], + "skipFiles": [ + "vtt.png", + "vtt-512.png", + "anvil.png", + "fvtt.icns", + "fvtt.ico", + "logo-scifi.png", + "logo-scifi-blank.png", + "LICENSE" + ], + "replacements": { + "abilities": "ability", + "antlers": "antler", + "arrows": "arrow", + "barrels": "barrel", + "beams": "beam", + "birds": "bird", + "bolts": "bolt", + "books": "book", + "bows": "bow", + "boxes": "box", + "bubbles": "bubble", + "bullets": "bullet", + "cards": "card", + "chains": "chain", + "claws": "claw", + "clouds": "cloud", + "clubs": "club", + "coins": "coin", + "documents": "document", + "eggs": "egg", + "eyes": "eye", + "fangs": "fang", + "flags": "flag", + "flowers": "flower", + "grains": "grain", + "guns": "gun", + "hammers": "hammer", + "hands": "hand", + "herbs": "herb", + "horns": "horn", + "lights": "light", + "maces": "mace", + "magical": "magic", + "mushrooms": "mushroom", + "orbs": "orb", + "projectiles": "projectile", + "ribs": "rib", + "roots": "root", + "ropes": "rope", + "runes": "rune", + "scales": "scale", + "sickles": "sickle", + "slimes": "slime", + "spirits": "spirit", + "stems": "stem", + "stick": "stick", + "symbols": "symbol", + "tentacles": "tentacle", + "tips": "tip", + "traps": "trap", + "vines": "vine", + "waves": "wave", + "webs": "web", + "weapons": "weapon", + "wands": "wand", + "swords": "sword", + "cutlasses": "cutlass", + "tools": "tool", + "containers": "container", + "skills": "skill", + "creatures": "creature", + "sundries": "sundry", + "consumables": "consumable", + "gems": "gem", + "daggers": "dagger", + "commodities": "commodity", + "feathers": "feather", + "dynamite": "explosive", + "bomb": "explosive", + "bones": "bone", + "potions": "potion", + "bags": "bag", + "axes": "axe", + "scrolls": "scroll", + "glow": "glowing", + "materials": "material", + "plants": "plant", + "polearms": "polearm", + "staves": "stave", + "academics": "academic", + "aliens": "alien", + "amphibians": "amphibian", + "wings": "wing" + }, + "removals": [ + "", + "white", + "yellow", + "blue", + "red", + "green", + "black", + "brown", + "teal", + "silver", + "purple", + "gray", + "grey", + "orange", + "lime", + "crimson", + "magenta", + "gold", + "cyan", + "pink", + "tan", + "violet", + "beige", + "simple", + "ringed", + "hollow", + "guard", + "pressure", + "gas", + "fuse", + "cloth", + "sharp", + "worn", + "svg", + "rough", + "control", + "3d", + "admission", + "alient", + "alpha", + "and", + "token", + "assorted", + "ember", + "misc", + "mix" + ] +} \ No newline at end of file diff --git a/importable/findFoundryFiles.mjs b/importable/findFoundryFiles.mjs index cbf6c18..c512a18 100644 --- a/importable/findFoundryFiles.mjs +++ b/importable/findFoundryFiles.mjs @@ -1,7 +1,9 @@ import { globSync } from "glob"; import crypto from "crypto"; import { createReadStream } from "fs"; -import { writeFile } from "fs/promises"; +import { readFile, writeFile } from "fs/promises"; + +const config = JSON.parse(await readFile(`importable/config.json`, `utf8`)); async function hashFile(path) { return new Promise((resolve) => { @@ -18,67 +20,61 @@ async function hashFile(path) { }); }; -const skipFiles = [ - `vtt.png`, - `vtt-512.png`, - `anvil.png`, - `fvtt.icns`, - `fvtt.ico`, - `logo-scifi.png`, - `logo-scifi-blank.png`, - `LICENSE`, -]; - -const tagRenames = { - weapons: `weapon`, - wands: `wand`, - swords: `sword`, - cutlasses: `cutlass`, - daggers: `dagger`, - commodities: `commodity`, - feathers: `feather`, - dynamite: `explosive`, - bomb: `explosive`, -} - -const purgeTags = new Set([ - // All of the colours - `white`, `yellow`, `blue`, `red`, `green`, `black`, `brown`, `teal`, `silver`, `purple`, `gray`, `grey`, `orange`, `lime`, `crimson`, `magenta`, `gold`, `cyan`, `pink`, `tan`, `violet`, - - // Terms that just suck as tags - `simple`, `ringed`, `hollow`, `guard`, `pressure`, `gas`, `fuse`, - `cloth`, `sharp`, `worn`, -]); - async function main() { - const imageList = globSync(`foundry/public/icons/**/*`, { nodir: true }); + const imageList = globSync( + `foundry/public/icons/**/*`, + { + nodir: true, + ignore: config.ignorePatterns, + }); const images = {}; + const allTags = {}; for (const path of imageList) { - if (skipFiles.some(file => path.endsWith(file))) continue; + if (config.skipFiles.some(file => path.endsWith(file))) continue; const hash = await hashFile(path); const filename = path.split(`/`).at(-1); - const tags = new Set( + const tags = Array.from(new Set( path .replace(`foundry/public/icons/`, ``) .replace(/\.[a-z]+$/i, ``) .replaceAll(`-`, `/`) .split(`/`) - .map(tag => tagRenames[tag] ?? tag) - .filter(tag => !purgeTags.has(tag)) - ); + .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: Array.from(tags), + 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),