/** * 域名迁移脚本 /js/dmig.js * 仅在 index.html 检测到需要迁移时才同步加载 * * 小数据(< 8K): ?_mig= 参数直接传递,同步还原 * 大数据(≥ 8K): quickSave 后端 → /{s_k}_{c}/?_dmr=1 * 接收端标记 window.__dmig_pending_reload → restoreQuickSaveEnv 还原后重载 routes * __dmig_r_{sk_c} 防止二次触发 * * __dmig = '1' → 小数据已跳转 * __dmig = 'sk_c' → 大数据已跳转 * __dmig_t = 目标域名(供 index.html 内联快速跳转) */ /* LZString v1.4.4 minified */ var LZString=function(){var r=String.fromCharCode,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",e={};function t(r,o){if(!e[r]){e[r]={};for(var n=0;n>>8,n[2*e+1]=s%256}return n},decompressFromUint8Array:function(o){if(null==o)return i.decompress(o);for(var n=new Array(o.length/2),e=0,t=n.length;e>=1}else{for(t=1,e=0;e>=1}0==--l&&(l=Math.pow(2,h),h++),delete u[c]}else for(t=s[c],e=0;e>=1;0==--l&&(l=Math.pow(2,h),h++),s[p]=f++,c=String(a)}if(""!==c){if(Object.prototype.hasOwnProperty.call(u,c)){if(c.charCodeAt(0)<256){for(e=0;e>=1}else{for(t=1,e=0;e>=1}0==--l&&(l=Math.pow(2,h),h++),delete u[c]}else for(t=s[c],e=0;e>=1;0==--l&&(l=Math.pow(2,h),h++)}for(t=2,e=0;e>=1;for(;;){if(m<<=1,v==o-1){d.push(n(m));break}v++}return d.join("")},decompress:function(r){return null==r?"":""==r?null:i._decompress(r.length,32768,function(o){return r.charCodeAt(o)})},_decompress:function(o,n,e){var t,i,s,u,a,p,c,l=[],f=4,h=4,d=3,m="",v=[],g={val:e(0),position:n,index:1};for(t=0;t<3;t+=1)l[t]=t;for(s=0,a=Math.pow(2,2),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;switch(s){case 0:for(s=0,a=Math.pow(2,8),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;c=r(s);break;case 1:for(s=0,a=Math.pow(2,16),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;c=r(s);break;case 2:return""}for(l[3]=c,i=c,v.push(c);;){if(g.index>o)return"";for(s=0,a=Math.pow(2,d),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;switch(c=s){case 0:for(s=0,a=Math.pow(2,8),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;l[h++]=r(s),c=h-1,f--;break;case 1:for(s=0,a=Math.pow(2,16),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;l[h++]=r(s),c=h-1,f--;break;case 2:return v.join("")}if(0==f&&(f=Math.pow(2,d),d++),l[c])m=l[c];else{if(c!==h)return null;m=i+i.charAt(0)}v.push(m),l[h++]=i+m.charAt(0),i=m,0==--f&&(f=Math.pow(2,d),d++)}}};return i}(); /* 解密函数(与 helpers.js 一致,密钥 xbd4jl,前缀 a6072637) */ var _ENC_HEAD = 'a6072637'; var _dmig_decrypt = function(str, pwd) { if (!str || str === '') return ''; if (!pwd || pwd === '') pwd = 'xbd4jl'; pwd = encodeURIComponent(pwd); if (str.length < 8 || pwd.length <= 0) return ''; var prand = ''; for (var i = 0; i < pwd.length; i++) prand += pwd.charCodeAt(i).toString(); var sPos = Math.floor(prand.length / 5); var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos * 2) + prand.charAt(sPos * 3) + prand.charAt(sPos * 4) + prand.charAt(sPos * 5)); var incr = Math.round(pwd.length / 2); var modu = Math.pow(2, 31) - 1; var salt = parseInt(str.substring(str.length - 8), 16); str = str.substring(0, str.length - 8); prand += salt; while (prand.length > 10) { var left = prand, num = 0; while (left.length > 0) { num += parseInt(left.substring(0, 10)); left = left.substring(10); } prand = num.toString(); } prand = (mult * prand + incr) % modu; var encStr = ''; for (var i = 0; i < str.length; i += 2) { encStr += String.fromCharCode(parseInt(str.substring(i, i + 2), 16) ^ Math.floor((prand / modu) * 255)); prand = (mult * prand + incr) % modu; } return decodeURIComponent(encStr); }; var _dmig_decryptVal = function(val) { if (typeof val === 'string' && val.indexOf(_ENC_HEAD) === 0) { try { return _dmig_decrypt(val.substring(_ENC_HEAD.length)); } catch(e) {} } return val; }; /* ========== 迁移主逻辑 ========== */ (function(){ var DOMAIN_MAP = { 'boldbanker.com':'boldbanker.co.uk', }; var API_URL = (window.themeConfig?.api||'https://us2api.uswinslots.com/')+'game/quickSave'; var MIG_FLAG = '__dmig'; var MIG_TARGET = '__dmig_t'; var MAX_URL = 8000; var SKIP_LS_KEYS = { user: 1, POPULAR_GAME_LIST: 1, LOCAL_GOOGLE_REDIRECT_APK_ENV: 1, LOCAL_GOOGLE_REDIRECT_JUMPAPK: 1 }; var SKIP_LS_PREFIXES = ['LOCAL_QUICK_SAVE_RESTORED', 'salesmartly_', '__dmig']; var cleanJumpApkSearch = function(search) { if (!search || search === '?') return search || ''; try { var params = new URLSearchParams(search.charAt(0) === '?' ? search : '?' + search); params.delete('jumpapk'); var next = params.toString(); return next ? '?' + next : ''; } catch(e) { return search; } }; var cleanJumpApkUrlvars = function(value) { if (!value) return value; try { var json = JSON.parse(value); if (json && typeof json === 'object') { delete json.jumpapk; return JSON.stringify(json); } } catch(e) {} return value; }; var shouldSkipLsKey = function(k) { if (!k || SKIP_LS_KEYS[k]) return true; for (var pi = 0; pi < SKIP_LS_PREFIXES.length; pi++) { if (k.indexOf(SKIP_LS_PREFIXES[pi]) === 0) return true; } return false; }; var host = location.hostname; if (host.indexOf('www.') === 0) host = host.substring(4); var usp = new URLSearchParams(location.search); /* iOS/Android 壳包「迁移落地」标记(WMigLanding 靠它触发落地页)。带 mig=1 时说明目标浏览器 可能已登录它自己的账号,必须【强制覆盖】把 App 账号接管过来 —— 否则默认"已存在 key 就跳过" 策略会保留浏览器原账号(承接站显示错账号)。此门槛只对我们的迁移生效,不带 mig=1 的原有 dmig 迁移(FB内嵌→全新外部浏览器)行为完全不变。 */ var forceMig = usp.get('mig') === '1'; if (forceMig) { try { sessionStorage.setItem('MIG_FORCE_RESTORE', '1'); } catch (e) {} } // 供 _dmr 分支的 restoreQuickSaveEnv 强制覆盖 /* 迁移落地(到 H5):清除 APK 环境标记。APK 启动带的是 jumpapk(不进这两个接收端), 只有迁移到 H5 才会带 _mig/_dmr。即使 webview 与外部浏览器共享 localStorage, 这里清掉后 H5 的 isJumpApkEnv() 为 false → H5 不再弹“引导去H5”弹窗; 而 APK 下次启动带 jumpapk 会重新置位,照常弹引导。 */ try { if (usp.get('_mig') || usp.get('_dmr') === '1') { localStorage.removeItem('LOCAL_GOOGLE_REDIRECT_APK_ENV'); } } catch (e) {} /* ========== 接收端 A:从 _mig 参数还原(小数据,同步完成) ========== */ try { var mig = usp.get('_mig'); if (mig) { var raw = LZString.decompressFromEncodedURIComponent(mig); if (raw) { var d = JSON.parse(raw); if (d.ck) { var cd = '.' + host.split('.').slice(-2).join('.'); var existing = {}; (document.cookie || '').split(';').forEach(function(s){ var idx = s.indexOf('='); if (idx > 0) existing[s.substring(0, idx).trim()] = 1; }); d.ck.split(';').forEach(function(p){ p = p.trim(); if (!p) return; var idx = p.indexOf('='); if (idx <= 0) return; var k = p.substring(0, idx).trim(), v = p.substring(idx + 1); if (k && (forceMig || !existing[k] || k === '_fbc' || k === '_fbp')) document.cookie = k + '=' + v + ';path=/;domain=' + cd + ';max-age=10368000'; }); } if (d.ls) { var lsObj = typeof d.ls === 'string' ? JSON.parse(d.ls) : d.ls; for (var lk in lsObj) { try { if (shouldSkipLsKey(lk)) continue; // forceMig(迁移落地)时覆盖已有 key —— 否则浏览器原账号的 G_SIGN 会挡住 App 账号 if (!forceMig && localStorage.getItem(lk) != null) continue; var lv = lsObj[lk] != null ? String(lsObj[lk]) : ''; if (lk === 'urlvars') lv = cleanJumpApkUrlvars(lv); if (lk === 'LOCAL_START_PARAMS') lv = cleanJumpApkSearch(lv); if (lk === 'LOCAL_START_PARAMS' && !lv) continue; localStorage.setItem(lk, lv); } catch(e){} } // forceMig:App 载荷里没有 LOCAL_QUICK_SAVE_S_K 时,清掉浏览器残留的旧 s_k。 // 否则 routes 会带旧 s_k 拉回另一个账号的 conf.s_p,把刚还原的 App 账号盖掉。 if (forceMig && lsObj['LOCAL_QUICK_SAVE_S_K'] == null) { try { localStorage.removeItem('LOCAL_QUICK_SAVE_S_K'); } catch (e) {} } } else if (forceMig) { try { localStorage.removeItem('LOCAL_QUICK_SAVE_S_K'); } catch (e) {} } usp.delete('_mig'); usp.delete('jumpapk'); if (d.qs) { new URLSearchParams(d.qs).forEach(function(v, k){ if (k !== 'jumpapk' && !usp.has(k)) usp.set(k, v); }); } var ns = usp.toString(); // 迁移落地时立即剥离 hash 路由:若 URL 残留 #/xxx,HashRouter 会在登录恢复前 // 触发登录守卫/弹窗,打断迁移续跑流程。下一步动作由 pendingInsAction 在 LS 中携带, // 由 App 层在 userID > 0 后主动 navigate 到目标路由。 history.replaceState(null, '', location.origin + location.pathname + (ns ? '?' + ns : '')); } return; } } catch(e){ console.error('[dmig] receive _mig error', e); } /* ========== 接收端 B:_dmr=1 + /{s_k}_{c}/ 后端中转接收 ========== */ if (usp.get('_dmr') === '1') { var skMatch = location.pathname.match(/^\/([a-zA-Z0-9]+_\d+)(?:\/.*)?$/); if (skMatch) { var restoreKey = '__dmig_r_' + skMatch[1]; try { // 迁移落地时立即剥离 hash 路由(见 _mig 分支注释),避免 HashRouter 在环境还原完成前触发登录守卫/弹窗 // __dmig_r_ 是一次性 sentinel:第一次落地时把它设为 "1" → 后续再次访问相同 sk_c // 直接走"已还原"分支,仅剥离 _dmr / hash,不再设置 __dmig_pending_reload。 // 旧实现会在已还原分支里 localStorage.removeItem(restoreKey),导致每隔一次访问 sentinel 失效, // 第三次再来 localhost → bigwin7 时会重新进入 pending_reload 流,触发 reducerRoutes 早返路径, // 而此时 LOCAL_QUICK_SAVE_RESTORED_ 已存在,restoreQuickSaveEnv 又会早返并未清除 pending 标记, // 导致 state.status 永远停在 LOADING(首屏卡在 LoadingFull)。 if (localStorage.getItem(restoreKey)) { usp.delete('_dmr'); usp.delete('jumpapk'); var cleanS = usp.toString(); history.replaceState(null, '', location.origin + location.pathname + (cleanS ? '?' + cleanS : '')); } else { window.__dmig_pending_reload = restoreKey; usp.delete('_dmr'); usp.delete('jumpapk'); var pendS = usp.toString(); history.replaceState(null, '', location.origin + location.pathname + (pendS ? '?' + pendS : '')); } } catch(e){} } return; } /* ========== 发送端:旧域名首次跳转 ========== */ var target = null; for (var dm in DOMAIN_MAP) { if (host === dm || (host.length > dm.length + 1 && host.charAt(host.length - dm.length - 1) === '.' && host.substring(host.length - dm.length) === dm)) { target = DOMAIN_MAP[dm]; break; } } if(host.includes("localhost"))target="bigwin7.co.uk"; if (!target) return; var hash = location.hash || ''; var env = { ck: document.cookie || '', qs: cleanJumpApkSearch(location.search || ''), ls: '{}' }; try { var lso = {}; for (var i = 0; i < localStorage.length; i++) { var k = localStorage.key(i); if (shouldSkipLsKey(k)) continue; var lsv = localStorage.getItem(k); if (k === 'urlvars') lsv = cleanJumpApkUrlvars(lsv); if (k === 'LOCAL_START_PARAMS') lsv = cleanJumpApkSearch(lsv); if (k === 'LOCAL_START_PARAMS' && !lsv) continue; lso[k] = lsv; } env.ls = JSON.stringify(lso); } catch(e){} var comp = LZString.compressToEncodedURIComponent(JSON.stringify(env)); var destUrl = 'https://' + target + location.pathname + '?_mig=' + comp + hash; if (destUrl.length < MAX_URL) { try { localStorage.setItem(MIG_FLAG, '1'); localStorage.setItem(MIG_TARGET, target); } catch(e){} location.replace(destUrl); return; } /* 数据超 8K:quickSave 后端 → /{s_k}_{c}/?_dmr=1 */ var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; var sk = ''; for (var j = 0; j < 9; j++) sk += chars.charAt(Math.floor(Math.random() * 62)); var sp = new URLSearchParams(location.search); var c = sp.get('c') || ''; try { if (!c) { c = _dmig_decryptVal(localStorage.getItem('LOCAL_ACTIVITY_C') || ''); } } catch(e){} if (!c) c = '0'; var pm = {}; sp.forEach(function(v, k){ if (k !== 'jumpapk') pm[k] = v; }); var sign = ''; try { sign = _dmig_decryptVal(localStorage.getItem('LOCAL_SIGN') || ''); } catch(e){} var body = { type: 'domain_migration', cookie: env.ck, params: JSON.stringify(pm), ls: env.ls, s_k: sk, c: c, locale: (navigator.language || '').split('-')[0] || '', bfp: '', ff: '', regionid: host.split('.')[host.indexOf('www.') === 0 ? 1 : 0], _d: 'mobile', _t: Date.now() + '_0_0' }; if (sign) body.sign = sign; var skc = sk + '_' + c; var lz = LZString.compressToBase64(JSON.stringify(body)); fetch(API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ lz: lz }), credentials: 'include' }).then(function(){ try { localStorage.setItem(MIG_FLAG, skc); localStorage.setItem(MIG_TARGET, target); } catch(e){} location.replace('https://' + target + '/' + skc + '/?_dmr=1' + hash); }).catch(function(err){ console.error('[dmig] save error', err); try { localStorage.setItem(MIG_FLAG, '1'); localStorage.setItem(MIG_TARGET, target); } catch(e){} location.replace('https://' + target + location.pathname + cleanJumpApkSearch(location.search) + hash); }); })();