Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637import {readFileSync, writeFileSync, mkdirSync} from 'node:fs';import {createHash} from 'node:crypto';import {config,request,id} from '../../toolchain/robloxplorer/robloxplorer.mjs';const dir=import.meta.dirname;mkdirSync(`${dir}/build`,{recursive:true});const catalog=JSON.parse(readFileSync(`${dir}/catalog.json`));const {key,userId}=config();const headers={'x-api-key':key};const [command='import',slug='ac-pals']=process.argv.slice(2);const entry=catalog.items.find(x=>x.id===slug && x.approved===true);if(!entry) throw new Error('Entry must be explicitly approved in catalog.json');const file=`${dir}/build/${entry.id}.json`;if(command==='import') { let previous;try{previous=JSON.parse(readFileSync(file));}catch{} if(previous?.operation) throw new Error('Upload already recorded; use poll to avoid duplicates'); const url=new URL(entry.sourceUrl); if(url.origin!=='https://assets.aesthetic.computer' || !url.pathname.endsWith('.png')) throw new Error('Only approved AC asset PNGs'); const res=await fetch(url,{redirect:'error',signal:AbortSignal.timeout(15000)}); if(!res.ok)throw new Error(`Source HTTP ${res.status}`); const bytes=new Uint8Array(await res.arrayBuffer()); if(bytes.length>10*1024*1024 || bytes.length<24 || Buffer.from(bytes.subarray(0,8)).toString('hex')!=='89504e470d0a1a0a')throw new Error('Expected PNG under 10MB'); const body=new FormData(); body.set('request',JSON.stringify({assetType:'Image',displayName:entry.title,description:'AC-owned artwork imported for the Aesthetic Arena media bridge.',creationContext:{creator:{userId:id(userId)}}})); body.set('fileContent',new Blob([bytes],{type:'image/png'}),`${entry.id}.png`); const operation=await request('https://apis.roblox.com/assets/v1/assets',{method:'POST',headers,body}); const record={source:entry,sha256:createHash('sha256').update(bytes).digest('hex'),operation}; writeFileSync(file,JSON.stringify(record,null,2)+'\n'); console.log(JSON.stringify(operation));} else if(command==='poll') { const record=JSON.parse(readFileSync(file)); const path=record.operation.path; if(!/^operations\/[A-Za-z0-9-]+$/.test(path))throw new Error('Unexpected operation path'); record.operation=await request(`https://apis.roblox.com/assets/v1/${path}`,{headers}); writeFileSync(file,JSON.stringify(record,null,2)+'\n'); console.log(JSON.stringify(record.operation,null,2));} else throw new Error('Use import or poll');