dmig.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /**
  2. * 域名迁移脚本 /js/dmig.js
  3. * 仅在 index.html 检测到需要迁移时才同步加载
  4. *
  5. * 小数据(< 8K): ?_mig= 参数直接传递,同步还原
  6. * 大数据(≥ 8K): quickSave 后端 → /{s_k}_{c}/?_dmr=1
  7. * 接收端标记 window.__dmig_pending_reload → restoreQuickSaveEnv 还原后重载 routes
  8. * __dmig_r_{sk_c} 防止二次触发
  9. *
  10. * __dmig = '1' → 小数据已跳转
  11. * __dmig = 'sk_c' → 大数据已跳转
  12. * __dmig_t = 目标域名(供 index.html 内联快速跳转)
  13. */
  14. /* LZString v1.4.4 minified */
  15. 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<r.length;n++)e[r][r.charAt(n)]=n}return e[r][o]}var i={compressToBase64:function(r){if(null==r)return"";var n=i._compress(r,6,function(r){return o.charAt(r)});switch(n.length%4){default:case 0:return n;case 1:return n+"===";case 2:return n+"==";case 3:return n+"="}},decompressFromBase64:function(r){return null==r?"":""==r?null:i._decompress(r.length,32,function(n){return t(o,r.charAt(n))})},compressToUTF16:function(o){return null==o?"":i._compress(o,15,function(o){return r(o+32)})+" "},decompressFromUTF16:function(r){return null==r?"":""==r?null:i._decompress(r.length,16384,function(o){return r.charCodeAt(o)-32})},compressToUint8Array:function(r){for(var o=i.compress(r),n=new Uint8Array(2*o.length),e=0,t=o.length;e<t;e++){var s=o.charCodeAt(e);n[2*e]=s>>>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<t;e++)n[e]=256*o[2*e]+o[2*e+1];var s=[];return n.forEach(function(o){s.push(r(o))}),i.decompress(s.join(""))},compressToEncodedURIComponent:function(r){return null==r?"":i._compress(r,6,function(r){return n.charAt(r)})},decompressFromEncodedURIComponent:function(r){return null==r?"":""==r?null:(r=r.replace(/ /g,"+"),i._decompress(r.length,32,function(o){return t(n,r.charAt(o))}))},compress:function(o){return i._compress(o,16,function(o){return r(o)})},_compress:function(r,o,n){if(null==r)return"";var e,t,i,s={},u={},a="",p="",c="",l=2,f=3,h=2,d=[],m=0,v=0;for(i=0;i<r.length;i+=1)if(a=r.charAt(i),Object.prototype.hasOwnProperty.call(s,a)||(s[a]=f++,u[a]=!0),p=c+a,Object.prototype.hasOwnProperty.call(s,p))c=p;else{if(Object.prototype.hasOwnProperty.call(u,c)){if(c.charCodeAt(0)<256){for(e=0;e<h;e++)m<<=1,v==o-1?(v=0,d.push(n(m)),m=0):v++;for(t=c.charCodeAt(0),e=0;e<8;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;e<h;e++)m=m<<1|t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=c.charCodeAt(0),e=0;e<16;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}0==--l&&(l=Math.pow(2,h),h++),delete u[c]}else for(t=s[c],e=0;e<h;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=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<h;e++)m<<=1,v==o-1?(v=0,d.push(n(m)),m=0):v++;for(t=c.charCodeAt(0),e=0;e<8;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;e<h;e++)m=m<<1|t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=c.charCodeAt(0),e=0;e<16;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}0==--l&&(l=Math.pow(2,h),h++),delete u[c]}else for(t=s[c],e=0;e<h;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;0==--l&&(l=Math.pow(2,h),h++)}for(t=2,e=0;e<h;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=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}();
  16. /* 解密函数(与 helpers.js 一致,密钥 xbd4jl,前缀 a6072637) */
  17. var _ENC_HEAD = 'a6072637';
  18. var _dmig_decrypt = function(str, pwd) {
  19. if (!str || str === '') return '';
  20. if (!pwd || pwd === '') pwd = 'xbd4jl';
  21. pwd = encodeURIComponent(pwd);
  22. if (str.length < 8 || pwd.length <= 0) return '';
  23. var prand = '';
  24. for (var i = 0; i < pwd.length; i++) prand += pwd.charCodeAt(i).toString();
  25. var sPos = Math.floor(prand.length / 5);
  26. var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos * 2) + prand.charAt(sPos * 3) + prand.charAt(sPos * 4) + prand.charAt(sPos * 5));
  27. var incr = Math.round(pwd.length / 2);
  28. var modu = Math.pow(2, 31) - 1;
  29. var salt = parseInt(str.substring(str.length - 8), 16);
  30. str = str.substring(0, str.length - 8);
  31. prand += salt;
  32. while (prand.length > 10) {
  33. var left = prand, num = 0;
  34. while (left.length > 0) { num += parseInt(left.substring(0, 10)); left = left.substring(10); }
  35. prand = num.toString();
  36. }
  37. prand = (mult * prand + incr) % modu;
  38. var encStr = '';
  39. for (var i = 0; i < str.length; i += 2) {
  40. encStr += String.fromCharCode(parseInt(str.substring(i, i + 2), 16) ^ Math.floor((prand / modu) * 255));
  41. prand = (mult * prand + incr) % modu;
  42. }
  43. return decodeURIComponent(encStr);
  44. };
  45. var _dmig_decryptVal = function(val) {
  46. if (typeof val === 'string' && val.indexOf(_ENC_HEAD) === 0) {
  47. try { return _dmig_decrypt(val.substring(_ENC_HEAD.length)); } catch(e) {}
  48. }
  49. return val;
  50. };
  51. /* ========== 迁移主逻辑 ========== */
  52. (function(){
  53. var DOMAIN_MAP = {
  54. 'bigwin7.vip':'bigwin7.co.uk',
  55. 'bigwinrush.vip':'bigwinrush.co.uk',
  56. 'spinblitz.cc':'spinblitz.co.uk',
  57. 'rapidjackpot.net':'rapidjackpot.co.uk',
  58. 'cashstorm.cc':'cashstorm.org',
  59. 'jackpotfury.cc':'jackpotfury.co.uk',
  60. 'ultrawinner.cc':'ultrawinner.co.uk',
  61. 'megacashgo.cc':'megacashgo.co.uk',
  62. 'winexplosion.net':'winexplosion.co.uk',
  63. 'hotwinzone.com':'hotwinzone.co.uk',
  64. 'slotfrenzy.cc':'slotfrenzy.co.uk',
  65. 'luckyhitnow.cc':'luckyhitnow.co.uk'
  66. };
  67. var API_URL = 'https://api1.usvip.org/game/quickSave';
  68. var MIG_FLAG = '__dmig';
  69. var MIG_TARGET = '__dmig_t';
  70. var MAX_URL = 8000;
  71. var host = location.hostname;
  72. if (host.indexOf('www.') === 0) host = host.substring(4);
  73. var usp = new URLSearchParams(location.search);
  74. /* ========== 接收端 A:从 _mig 参数还原(小数据,同步完成) ========== */
  75. try {
  76. var mig = usp.get('_mig');
  77. if (mig) {
  78. var raw = LZString.decompressFromEncodedURIComponent(mig);
  79. if (raw) {
  80. var d = JSON.parse(raw);
  81. if (d.ck) {
  82. var cd = '.' + host.split('.').slice(-2).join('.');
  83. var existing = {};
  84. (document.cookie || '').split(';').forEach(function(s){
  85. var idx = s.indexOf('=');
  86. if (idx > 0) existing[s.substring(0, idx).trim()] = 1;
  87. });
  88. d.ck.split(';').forEach(function(p){
  89. p = p.trim(); if (!p) return;
  90. var idx = p.indexOf('=');
  91. if (idx <= 0) return;
  92. var k = p.substring(0, idx).trim(), v = p.substring(idx + 1);
  93. if (k && (!existing[k] || k === '_fbc' || k === '_fbp'))
  94. document.cookie = k + '=' + v + ';path=/;domain=' + cd + ';max-age=10368000';
  95. });
  96. }
  97. if (d.ls) {
  98. var lsObj = typeof d.ls === 'string' ? JSON.parse(d.ls) : d.ls;
  99. for (var lk in lsObj) {
  100. try { if (localStorage.getItem(lk) == null) localStorage.setItem(lk, lsObj[lk] != null ? String(lsObj[lk]) : ''); }
  101. catch(e){}
  102. }
  103. }
  104. usp.delete('_mig');
  105. if (d.qs) {
  106. new URLSearchParams(d.qs).forEach(function(v, k){ if (!usp.has(k)) usp.set(k, v); });
  107. }
  108. var ns = usp.toString();
  109. // 迁移落地时立即剥离 hash 路由:若 URL 残留 #/xxx,HashRouter 会在登录恢复前
  110. // 触发登录守卫/弹窗,打断迁移续跑流程。下一步动作由 pendingInsAction 在 LS 中携带,
  111. // 由 App 层在 userID > 0 后主动 navigate 到目标路由。
  112. history.replaceState(null, '', location.origin + location.pathname + (ns ? '?' + ns : ''));
  113. }
  114. return;
  115. }
  116. } catch(e){ console.error('[dmig] receive _mig error', e); }
  117. /* ========== 接收端 B:_dmr=1 + /{s_k}_{c}/ 后端中转接收 ========== */
  118. if (usp.get('_dmr') === '1') {
  119. var skMatch = location.pathname.match(/^\/([a-zA-Z0-9]+_\d+)(?:\/.*)?$/);
  120. if (skMatch) {
  121. var restoreKey = '__dmig_r_' + skMatch[1];
  122. try {
  123. // 迁移落地时立即剥离 hash 路由(见 _mig 分支注释),避免 HashRouter 在环境还原完成前触发登录守卫/弹窗
  124. // __dmig_r_<sk_c> 是一次性 sentinel:第一次落地时把它设为 "1" → 后续再次访问相同 sk_c
  125. // 直接走"已还原"分支,仅剥离 _dmr / hash,不再设置 __dmig_pending_reload。
  126. // 旧实现会在已还原分支里 localStorage.removeItem(restoreKey),导致每隔一次访问 sentinel 失效,
  127. // 第三次再来 localhost → bigwin7 时会重新进入 pending_reload 流,触发 reducerRoutes 早返路径,
  128. // 而此时 LOCAL_QUICK_SAVE_RESTORED_<sk_c> 已存在,restoreQuickSaveEnv 又会早返并未清除 pending 标记,
  129. // 导致 state.status 永远停在 LOADING(首屏卡在 LoadingFull)。
  130. if (localStorage.getItem(restoreKey)) {
  131. usp.delete('_dmr');
  132. var cleanS = usp.toString();
  133. history.replaceState(null, '', location.origin + location.pathname + (cleanS ? '?' + cleanS : ''));
  134. } else {
  135. window.__dmig_pending_reload = restoreKey;
  136. usp.delete('_dmr');
  137. var pendS = usp.toString();
  138. history.replaceState(null, '', location.origin + location.pathname + (pendS ? '?' + pendS : ''));
  139. }
  140. } catch(e){}
  141. }
  142. return;
  143. }
  144. /* ========== 发送端:旧域名首次跳转 ========== */
  145. var target = null;
  146. for (var dm in DOMAIN_MAP) {
  147. if (host === dm || (host.length > dm.length + 1 && host.charAt(host.length - dm.length - 1) === '.' && host.substring(host.length - dm.length) === dm)) {
  148. target = DOMAIN_MAP[dm];
  149. break;
  150. }
  151. }
  152. if(host.includes("localhost"))target="bigwin7.co.uk";
  153. if (!target) return;
  154. var hash = location.hash || '';
  155. var SKIP_LS_KEYS = { user: 1, POPULAR_GAME_LIST: 1 };
  156. var SKIP_LS_PREFIXES = ['LOCAL_QUICK_SAVE_RESTORED', 'salesmartly_', '__dmig'];
  157. var env = { ck: document.cookie || '', qs: location.search || '', ls: '{}' };
  158. try {
  159. var lso = {};
  160. for (var i = 0; i < localStorage.length; i++) {
  161. var k = localStorage.key(i);
  162. if (!k || SKIP_LS_KEYS[k]) continue;
  163. var skip = false;
  164. for (var pi = 0; pi < SKIP_LS_PREFIXES.length; pi++) {
  165. if (k.indexOf(SKIP_LS_PREFIXES[pi]) === 0) { skip = true; break; }
  166. }
  167. if (skip) continue;
  168. lso[k] = localStorage.getItem(k);
  169. }
  170. env.ls = JSON.stringify(lso);
  171. } catch(e){}
  172. var comp = LZString.compressToEncodedURIComponent(JSON.stringify(env));
  173. var destUrl = 'https://' + target + location.pathname + '?_mig=' + comp + hash;
  174. if (destUrl.length < MAX_URL) {
  175. try { localStorage.setItem(MIG_FLAG, '1'); localStorage.setItem(MIG_TARGET, target); } catch(e){}
  176. location.replace(destUrl);
  177. return;
  178. }
  179. /* 数据超 8K:quickSave 后端 → /{s_k}_{c}/?_dmr=1 */
  180. var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  181. var sk = ''; for (var j = 0; j < 9; j++) sk += chars.charAt(Math.floor(Math.random() * 62));
  182. var sp = new URLSearchParams(location.search);
  183. var c = sp.get('c') || '';
  184. try { if (!c) { c = _dmig_decryptVal(localStorage.getItem('LOCAL_ACTIVITY_C') || ''); } } catch(e){}
  185. if (!c) c = '0';
  186. var pm = {};
  187. sp.forEach(function(v, k){ pm[k] = v; });
  188. var sign = '';
  189. try { sign = _dmig_decryptVal(localStorage.getItem('LOCAL_SIGN') || ''); } catch(e){}
  190. var body = {
  191. type: 'domain_migration',
  192. cookie: env.ck,
  193. params: JSON.stringify(pm),
  194. ls: env.ls,
  195. s_k: sk, c: c,
  196. locale: (navigator.language || '').split('-')[0] || '',
  197. bfp: '', ff: '',
  198. regionid: host.split('.')[host.indexOf('www.') === 0 ? 1 : 0],
  199. _d: 'mobile',
  200. _t: Date.now() + '_0_0'
  201. };
  202. if (sign) body.sign = sign;
  203. var skc = sk + '_' + c;
  204. var lz = LZString.compressToBase64(JSON.stringify(body));
  205. fetch(API_URL, {
  206. method: 'POST',
  207. headers: { 'Content-Type': 'application/json' },
  208. body: JSON.stringify({ lz: lz }),
  209. credentials: 'include'
  210. }).then(function(){
  211. try { localStorage.setItem(MIG_FLAG, skc); localStorage.setItem(MIG_TARGET, target); } catch(e){}
  212. location.replace('https://' + target + '/' + skc + '/?_dmr=1' + hash);
  213. }).catch(function(err){
  214. console.error('[dmig] save error', err);
  215. try { localStorage.setItem(MIG_FLAG, '1'); localStorage.setItem(MIG_TARGET, target); } catch(e){}
  216. location.replace('https://' + target + location.pathname + location.search + hash);
  217. });
  218. })();