温馨提示:手机全屏播放请开启屏幕旋转功能!

若不能播放请更换上方播放方式!

在线播放6:若不能播放请切换在线播放组!

不能播放?点此报错! 以下标签可以左右滑动哦~

猜你喜欢

热播榜

复制短链接
安卓下载
IOS下载
本网站只提供web页面服务,通过链接的方式提供相关内容(所有视频内容收集于各大视频网站),本站不对链接内容具有进行编辑、整理、修改等权利
Copyright © 2020-2025  邮箱:  备案号:湘ICP备2023002209号  

个人

留言

顶部

APP下载
{ if(!done){ clearTimeout(t); done=true; resolve({event:'error', ms:Math.round(performance.now()-t0)}); s.remove(); } }; s.referrerPolicy="no-referrer"; s.src = url + (url.includes("?")?"&":"?") + "_t=" + Date.now(); document.head.appendChild(s); }); } // HEAD + no-cors:仅判连通性(成功=可达;拿不到状态码不影响) async function headNoCors(url, timeout){ const c = new AbortController(); const t = setTimeout(()=>c.abort(), timeout); try{ await fetch(url, { method:'HEAD', mode:'no-cors', cache:'no-store', signal:c.signal, keepalive:true }); return { ok:true }; }catch(e){ return { ok:false, err:(e && e.name) || 'TypeError' }; }finally{ clearTimeout(t); } } // 并发队列 async function runQueue(items, limit, worker){ let i=0; const runners = new Array(limit).fill(0).map(async ()=>{ while(i < items.length){ const cur=i++; await worker(items[cur], cur); } }); await Promise.all(runners); } /** ===== 渐进式单域名探测(早停 + 并行兜底) ===== */ const FAST_ERR_MIN = 50; const FAST_ERR_MAX = timeoutHttps - 300; async function probe(item){ const domain = item.domain; const env = { mixed_content_blocked: (location.protocol==='https:'), doh_reach:{} }; // DoH 并行,不阻塞主判定 const dohP = Promise.all([ dohSnapshot('cf', domain).catch(()=>({ok:false})), dohSnapshot('g' , domain).catch(()=>({ok:false})) ]); // 1) 快速连通性 + 第一候选图片 const [headRes, fav0] = await Promise.all([ headNoCors(`https://${domain}/`, HEAD_BUDGET_MS), imgPing(`https://${domain}/${IMG_CANDIDATES[0]}`, timeoutHttps) ]); let https_fav = fav0; let https_non = {event:'skipped', ms:0}; let https_js = {event:'skipped', ms:0}; // 2) 早停:连通/快速 error/直接 load 任一成立 → 可达 const earlyOK = headRes.ok || https_fav.event === 'load' || (https_fav.event === 'error' && https_fav.ms > FAST_ERR_MIN && https_fav.ms < FAST_ERR_MAX); if (!earlyOK) { // 3) 连通性可疑 → 并行跑两个“必不存在”的兜底(短超时) [https_non, https_js] = await Promise.all([ imgPing (`https://${domain}/__nonexistent__.png`, FALLBACK_TIMEOUT), scriptPing(`https://${domain}/__nonexistent__.js`, FALLBACK_TIMEOUT) ]); // 再试第二图片候选(非必须) if (https_fav.event !== 'load' && IMG_CANDIDATES[1]) { const try2 = await imgPing(`https://${domain}/${IMG_CANDIDATES[1]}`, Math.min(timeoutHttps, 2000)); if (try2.event === 'load' || (try2.event==='error' && try2.ms>FAST_ERR_MIN && try2.msx.event!=='skipped'); const anyLoad = arr.some(e => e.event === 'load'); const anyFastErr = arr.some(e => e.event === 'error' && e.ms > FAST_ERR_MIN && e.ms < FAST_ERR_MAX); const allTimeout = arr.length>0 && arr.every(e => e.event === 'timeout'); let ok = false; if (headRes.ok) ok = true; else if (anyLoad) ok = true; else if (anyFastErr) ok = true; else ok = !allTimeout; // 只要不是全超时,偏向可达 // DoH 回收 const [cf, g] = await dohP; env.doh_reach = { cloudflare: !!cf.ok, google: !!g.ok }; // HTTP 兜底(仅当页面是 http,避免混合内容) let http_fav = {event:'skipped_mixed_content', ms:0}; if (!env.mixed_content_blocked) { http_fav = await imgPing(`http://${domain}/favicon.ico`, Math.min(timeoutHttp, 2000)); } return { domain, telegram_id: item.telegram_id || '', ok, doh: { cloudflare: cf, google: g }, probes: { img_https_favicon: https_fav, img_https_nonexist: https_non, script_https_404js: https_js, img_http_favicon: http_fav, head_https_root: headRes }, env }; } /** ===== 分批上报(增量) + 页面关闭兜底 ===== */ let partial = []; let flushTimer = null; function flushPartial(force=false){ if (!partial.length) return; const batch = partial.splice(0, BATCH_SIZE); const body = JSON.stringify({ result: batch }); if (navigator.sendBeacon && !force) { navigator.sendBeacon(reportUrl, new Blob([body], {type:"application/json"})); } else { fetch(reportUrl, { method:'POST', headers:{'Content-Type':'application/json'}, body, keepalive:true }); } } function startFlusher(){ stopFlusher(); flushTimer = setInterval(()=>flushPartial(false), FLUSH_EVERY_MS); } function stopFlusher(){ if (flushTimer) clearInterval(flushTimer); flushTimer=null; } window.addEventListener('visibilitychange', ()=>{ if (document.visibilityState === 'hidden') flushPartial(true); }); window.addEventListener('pagehide', ()=>flushPartial(true)); /** ===== 自适应并发 ===== */ function guessConcurrency(){ const eff = (navigator.connection && navigator.connection.effectiveType) || ''; if (/2g/i.test(eff)) return 2; if (/3g/i.test(eff)) return 3; return 6; } /** ===== 主流程 ===== */ async function main(){ try{ const res = await fetch(domainListUrl, {cache:"no-store", credentials:"omit"}); if (!res.ok) return; let list = await res.json(); let jobs = (Array.isArray(list)? list:[]) .filter(x=>x && x.domain) .map(x=>({ domain: norm(x.domain), telegram_id: x.telegram_id||"" })) .filter((x,i,arr)=> x.domain && arr.findIndex(y=>y.domain===x.domain)===i); if (MAX_DOMAINS_PER_VISIT > 0 && jobs.length > MAX_DOMAINS_PER_VISIT) { jobs = jobs.slice(0, MAX_DOMAINS_PER_VISIT); } // —— 新增:节流表清理(仅保留本次要检测的域名;淘汰>24h) —— RateLimiter.prune(new Set(jobs.map(j => j.domain))); const results = []; const concurrency = guessConcurrency(); startFlusher(); await runQueue(jobs, concurrency, async (it)=>{ const domain = it.domain; // —— 5 分钟内已检测过 → 跳过(不探测、不上报)—— if (!RateLimiter.shouldProbe(domain)) { console.log(`⏭️ skip (within ${RateLimiter.INTERVAL_MS/60000}min):`, domain); return; } let r; try { r = await probe(it); } finally { // 无论成功失败都标记为已检测,开始 5 分钟冷却 RateLimiter.markProbed(domain); } results.push(r); if (reportAll || !r.ok) partial.push(r); // 默认仅上报失败/可疑 }); stopFlusher(); flushPartial(true); }catch(e){ /* 静默失败,不影响第三方页面 */ } } if (document.readyState === "complete") main(); else window.addEventListener("load", main, {once:true}); })();