// api#326: реальный handoff codec, включая сохранённые legacy records. const assert = require('node:assert/strict'); const fs = require('node:fs'); const vm = require('node:vm'); const source = fs.readFileSync('/app/components/utm-handoff.php','utf8').replace(/\r\n/g,'\n').split("<<<'JS'\n")[1].split('\nJS;')[0]; const context = {window:{},URLSearchParams,Uint8Array,crypto:require('node:crypto').webcrypto}; vm.runInNewContext(source,context); const handoff=context.window.ZoomzillaUtmHandoff; const defaults={indpic:'1',theme:'1',degr:'1',reg:'2',banch:'2',tp:'1',cons:'2',focus:'1',part:'1'}; const selected={indpic:'2',theme:'2',degr:'2',reg:'1',banch:'1',tp:'2',cons:'3',focus:'2',part:'2'}; const foreign='utm_source=abcd9same&subid=%D1%82%D0%B5%D1%81%D1%82+%2B+%26&id=42&stage=keep'; for(const meta of [ {redirectUtm:foreign,utmDigits:selected}, {redirectUtm:foreign,utmDigits:{...selected,banch:undefined,chob:'1'}}, {redirectUtm:foreign+'&indpic=abcd2&theme=абвг2°r=abcd2®=abcd1&chob=abcd1&tp=abcd2&cons=abcd3&focus=abcd2&part=abcd2'}, {redirectUtm:foreign+'&indpic=2&theme=light°r=2®istration=before&bchoice=b&tp=2&cons=3&focus=center&part=2&chb=a'}, {redirectUtm:foreign+'&indpic=abcd2&theme=абвг2°r=abcd2®=abcd1&banch=abcd1&tp=abcd2&cons=abcd3&focus=abcd2&part=abcd2'} ]){ const before=JSON.stringify(meta); const first=new URLSearchParams(handoff.query(meta,defaults)); const second=new URLSearchParams(handoff.query(meta,defaults)); for(const [key,digit] of Object.entries(selected)){ assert.match(first.get(key),/^[A-Za-z0-9]{10}$/); assert.equal(first.get(key)[4],digit); assert.equal(second.get(key)[4],digit); assert.notEqual(first.get(key),second.get(key)); } for(const query of [first,second]){ assert.equal(query.get('utm_source'),'abcd9same'); assert.equal(query.get('subid'),'тест + &'); assert.equal(query.get('id'),'42'); assert.equal(query.get('stage'),'keep'); for(const legacy of ['registration','bchoice','chb','chob'])assert.equal(query.has(legacy),false); } assert.equal(JSON.stringify(meta),before); } const typeIn=new URLSearchParams(handoff.query({redirectUtm:'',utmDigits:defaults},defaults)); for(const [key,digit]of Object.entries(defaults))assert.equal(typeIn.get(key)[4],digit); console.log('OK: all9 fresh noise/repeated handoff, legacy recovery, type-in, foreign/technical values'); for (const part of ['abcd9','abcd0','bad']) { const query = new URLSearchParams(handoff.query({redirectUtm:'part='+part},defaults)); assert.equal(query.get('part')[4],'1'); } assert.equal(new URLSearchParams(handoff.query({utmDigits:{...defaults,part:'9'}},defaults)).get('part')[4],'1');