/^[1-9]$/.test(value || '') && (!enums[key] || Object.values(enums[key]).includes(value)); function restore(meta, defaults) { const query = new URLSearchParams(meta.redirectUtm || ''); const digits = {}; for (const key of keys) { let value = meta.utmDigits?.[key] ?? (key === 'banch' ? meta.utmDigits?.chob : undefined); if (!valid(key, value)) { // Только сохранённый record: старые enum/открытые цифры не являются raw URL alias. const stored = query.get(legacy[key] || key) ?? query.get(key) ?? (key === 'banch' ? query.get('chob') : null); value = enums[key]?.[stored] || stored; if (!valid(key, value)) value = Array.from(stored || '')[4]; } digits[key] = valid(key, value) ? value : defaults[key]; } return digits; } const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; function mask(digit) { const bytes = new Uint8Array(10); crypto.getRandomValues(bytes); const chars = Array.from(bytes, value => alphabet[value % alphabet.length]); chars[4] = digit; return chars.join(''); } function query(meta, defaults) { const params = new URLSearchParams(meta.redirectUtm || ''); const digits = restore(meta, defaults); for (const key of ['registration','bchoice','chob','chb','key','shown_theme',...keys]) params.delete(key); for (const key of keys) params.set(key, mask(digits[key])); return params.toString(); } window.ZoomzillaUtmHandoff = {restore, query}; })(); JS;