← back to Gmc Titlefix

step-d-scale-all.js.bak2

29 lines

// GATED WRITE — pushes title overrides for ALL risky offers. Usage: node step-d-scale-all.js <dataSourceName>
const {token,MERCHANT}=require('./_auth');
const fs=require('fs');
const DS=process.argv[2];
if(!DS){ console.error('Usage: node step-d-scale-all.js <dataSourceName from step A>'); process.exit(1); }
// FAIL-CLOSED GATE (vp-compliance-policy ask): refuse to scale unless step-c verify PASSED.
// Override only deliberately: SKIP_VERIFY_GATE=1 node step-d-scale-all.js <DS>
if(!process.env.SKIP_VERIFY_GATE && !fs.existsSync('/tmp/gmc-titlefix-verify-pass.txt')){
  console.error('BLOCKED: step-c verify has not PASSED (no /tmp/gmc-titlefix-verify-pass.txt).');
  console.error('Run step-b then step-c and confirm the canary title flipped before scaling 29,672 offers.');
  process.exit(2);
}
const list=require('./gmc_titlefix_list.json');
const sleep=ms=>new Promise(r=>setTimeout(r,ms));
(async()=>{
  let tok=await token(), tokAt=Date.now(), ok=0, fail=0;
  for(let i=0;i<list.length;i++){
    if(Date.now()-tokAt>50*60*1000){ tok=await token(); tokAt=Date.now(); }
    const row=list[i];
    const url=`https://merchantapi.googleapis.com/products/v1/accounts/${MERCHANT}/productInputs:insert?dataSource=${encodeURIComponent(DS)}`;
    const body={ offerId:row.offerId, contentLanguage:'en', feedLabel:'US', attributes:{ title: row.proposedTitle } };
    const r=await fetch(url,{method:'POST',headers:{Authorization:'Bearer '+tok,'Content-Type':'application/json'},body:JSON.stringify(body)});
    if(r.ok) ok++; else { fail++; if(fail<=10) console.error('FAIL',row.offerId,r.status,(await r.text()).slice(0,120)); }
    if(i%500===0) console.log(`  ${i}/${list.length} | ok ${ok} fail ${fail}`);
    if(r.status===429){ await sleep(3000); }
  }
  console.log(`DONE: ok ${ok} fail ${fail} of ${list.length}`);
})();