| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- import { mkdir, readFile, writeFile } from "node:fs/promises";
- import path from "node:path";
- const UA =
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36";
- const entries = JSON.parse(await readFile(".scratch/images.json", "utf8"));
- // Map every tildacdn URL (including resize derivatives) to its original full-size URL.
- const canonical = new Map();
- for (const { url } of entries) {
- let orig = url.replace("thb.tildacdn.com", "static.tildacdn.com");
- orig = orig.replace(/\/-\/resize[^/]*\//, "/");
- orig = orig.replace(/\/20x\//, "/");
- canonical.set(url, orig);
- }
- const unique = [...new Set(canonical.values())];
- console.log(`${entries.length} refs -> ${unique.length} original images`);
- await mkdir("public/images", { recursive: true });
- const usedNames = new Set();
- const map = {};
- let ok = 0, fail = 0;
- for (const url of unique) {
- if (url.includes("/lib/icons/")) continue; // stock bullet icons, replaced by our own
- let name = decodeURIComponent(path.basename(new URL(url).pathname));
- if (usedNames.has(name)) {
- const ext = path.extname(name);
- name = name.slice(0, -ext.length) + "-" + Math.abs(hash(url)).toString(36) + ext;
- }
- usedNames.add(name);
- try {
- const res = await fetch(url, { headers: { "User-Agent": UA } });
- if (!res.ok) throw new Error("HTTP " + res.status);
- const buf = Buffer.from(await res.arrayBuffer());
- const min = url.endsWith(".svg") ? 50 : 1000;
- if (buf.length < min) throw new Error("too small");
- await writeFile(path.join("public/images", name), buf);
- map[url] = "/images/" + name;
- ok++;
- } catch (e) {
- fail++;
- console.log(`FAIL ${url}: ${e.message}`);
- }
- }
- // hash helper
- function hash(s) {
- let h = 0;
- for (let i = 0; i < s.length; i++) h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;
- return h;
- }
- await writeFile(".scratch/image-map.json", JSON.stringify(map, null, 2));
- console.log(`downloaded ${ok}, failed ${fail}`);
|