33 lines
2.9 KiB
JavaScript
33 lines
2.9 KiB
JavaScript
import {readFile,readdir} from 'node:fs/promises';
|
|
import {fileURLToPath} from 'node:url';
|
|
import {join,dirname} from 'node:path';
|
|
import {createHash} from 'node:crypto';
|
|
import {requiredPackImages} from './verify-character-pack.mjs';
|
|
const root=join(dirname(fileURLToPath(import.meta.url)),'..','seed','characters');
|
|
const base=process.env.PROMPT_IMPORT_BASE_URL||'http://127.0.0.1:3000';
|
|
const packs=JSON.parse(await readFile(join(root,'packs.json'),'utf8'));
|
|
async function verify(pack){
|
|
let cursor='',post;const seen=new Set();
|
|
do{const response=await fetch(base+'/api/feed?'+new URLSearchParams({section:'images',...(cursor?{cursor}:{})}));if(!response.ok)throw Error('Cannot verify character feed: '+response.status);const page=await response.json();post=page.posts.find(p=>p.slug===pack.slug);cursor=page.nextCursor||'';if(cursor&&seen.has(cursor))throw Error('Character feed cursor did not advance');seen.add(cursor);}while(!post&&cursor);
|
|
if(!post)throw Error('Character pack missing: '+pack.slug);
|
|
const files=(await readdir(join(root,pack.directory))).filter(n=>n.endsWith('.png')).sort();if(files.length!==pack.count)throw Error('Seed file count mismatch: '+pack.slug);
|
|
const hashes=await Promise.all(files.map(async file=>createHash('sha256').update(await readFile(join(root,pack.directory,file))).digest('hex')));
|
|
const originals=requiredPackImages(hashes,post.assets.filter(a=>a.kind==='image'));
|
|
for(const image of originals){const media=await fetch(`${base}/api/media/${image.id}`,{method:'HEAD'});if(!media.ok||media.headers.get('content-type')!=='image/png')throw Error('Original PNG unavailable');}
|
|
console.log(`Verified: /p/${pack.slug} (${originals.length} original PNGs preserved; editorial covers allowed)`);
|
|
}
|
|
for(const pack of packs){
|
|
const existing=await fetch(`${base}/p/${pack.slug}`);
|
|
if(existing.ok){console.log(`Already imported: /p/${pack.slug}`);await verify(pack);continue;}
|
|
if(existing.status!==404)throw new Error(`Cannot check pack ${pack.slug}: ${existing.status}`);
|
|
const files=(await readdir(join(root,pack.directory))).filter(n=>n.endsWith('.png')).sort();
|
|
if(files.length!==pack.count)throw new Error(`Expected ${pack.count} PNGs for ${pack.slug}, got ${files.length}`);
|
|
const data=new FormData();data.set('title',pack.title);data.set('slug',pack.slug);data.set('description',pack.description);
|
|
for(const file of files)data.append('files',new Blob([await readFile(join(root,pack.directory,file))],{type:'image/png'}),file);
|
|
const response=await fetch(`${base}/api/skills/street-people`,{method:'POST',body:data});
|
|
if(response.status!==201&&response.status!==409)throw new Error(`Import ${pack.slug}: ${response.status} ${await response.text()}`);
|
|
if(response.status===409&&!(await fetch(`${base}/p/${pack.slug}`)).ok)throw new Error(`Conflicting import ${pack.slug}`);
|
|
console.log(`Imported: /p/${pack.slug} (${files.length} transparent PNGs)`);
|
|
await verify(pack);
|
|
}
|