diff --git a/Build/build-speedtest-domainset.ts b/Build/build-speedtest-domainset.ts index 8849e14a0..ab52d57a0 100644 --- a/Build/build-speedtest-domainset.ts +++ b/Build/build-speedtest-domainset.ts @@ -9,6 +9,7 @@ import { task } from './lib/trace-runner'; import { fetchWithRetry } from './lib/fetch-retry'; import { SHARED_DESCRIPTION } from './lib/constants'; import { getGorhillPublicSuffixPromise } from './lib/get-gorhill-publicsuffix'; +import picocolors from 'picocolors'; const s = new Sema(2); @@ -21,17 +22,12 @@ const querySpeedtestApi = async (keyword: string): Promise> s.acquire() ]))[0]; - let timer = null; try { const randomUserAgent = topUserAgents[Math.floor(Math.random() * topUserAgents.length)]; const key = `fetch speedtest endpoints: ${keyword}`; console.log(key); console.time(key); - // AbortSignal.timeout() is not supported by bun. - const controller = new AbortController(); - timer = setTimeout(() => controller.abort(), 4000); - const res = await fetchWithRetry(`https://www.speedtest.net/api/js/servers?engine=js&search=${keyword}&limit=100`, { headers: { dnt: '1', @@ -39,21 +35,21 @@ const querySpeedtestApi = async (keyword: string): Promise> accept: 'application/json, text/plain, */*', 'User-Agent': randomUserAgent, 'Accept-Language': 'en-US,en;q=0.9', - 'Sec-Ch-Ua': '"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"', - 'Sec-Ch-Ua-Mobile': '?0', - 'Sec-Fetch-Dest': 'empty', - 'Sec-Fetch-Mode': 'cors', - 'Sec-Fetch-Site': 'same-origin', - 'Sec-Gpc': '1' + ...(randomUserAgent.includes('Chrome') + ? { + 'Sec-Ch-Ua-Mobile': '?0', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'Sec-Gpc': '1' + } + : {}) }, + signal: AbortSignal.timeout(1000 * 4), retry: { - retryOnAborted: true - }, - signal: controller.signal + retries: 2 + } }); - if (!res.ok) { - throw new Error(`${res.statusText}\n${await res.text()}`); - } const json = await res.json>(); @@ -64,9 +60,6 @@ const querySpeedtestApi = async (keyword: string): Promise> console.log(e); return []; } finally { - if (timer) { - clearTimeout(timer); - } s.release(); } }; @@ -116,16 +109,30 @@ export const buildSpeedtestDomainSet = task(import.meta.path, async () => { '.speedtest.leaptel.com.au', '.speedtest.windstream.net', '.speedtest.vodafone.com.au', + '.speedtest.rascom.ru', + '.speedtest.dchost.com', + '.speedtest.highnet.com', + '.speedtest.seattle.wa.limewave.net', + '.speedtest.optitel.com.au', + '.speednet.net.tr', + '.speedtest.angolacables.co.ao', + // Fast.com '.fast.com', + // MacPaw 'speedtest.macpaw.com', + // speedtestmaster '.netspeedtestmaster.com', // Google Search Result of "speedtest", powered by this '.measurement-lab.org', // Google Fiber legacy speedtest site (new fiber speedtest use speedtestcustom.com) - '.speed.googlefiber.net' + '.speed.googlefiber.net', + // librespeed + '.backend.librespeed.org' ]); - const hostnameGroups = await Promise.all([ + let timer; + + const pMap = ([ 'Hong Kong', 'Taiwan', 'China Telecom', @@ -154,15 +161,32 @@ export const buildSpeedtestDomainSet = task(import.meta.path, async () => { 'Sydney', 'Brazil', 'Turkey' - ].map(querySpeedtestApi)); - - for (const hostnames of hostnameGroups) { - if (Array.isArray(hostnames)) { - for (const hostname of hostnames) { + ]).reduce>>((pMap, keyword) => { + pMap[keyword] = querySpeedtestApi(keyword).then(hostnameGroup => { + hostnameGroup.forEach(hostname => { if (hostname) { domains.add(hostname); } - } + }); + }); + + return pMap; + }, {}); + + try { + timer = setTimeout(() => { + console.error(picocolors.red('Task timeout!')); + Object.entries(pMap).forEach(([name, p]) => { + console.log(`[${name}]`, Bun.peek.status(p)); + }); + + throw new Error('timeout'); + }, 1000 * 60 * 2); + + await Promise.all(Object.values(pMap)); + } finally { + if (timer) { + clearTimeout(timer); } } diff --git a/Build/index.ts b/Build/index.ts index e0164339a..248713e68 100644 --- a/Build/index.ts +++ b/Build/index.ts @@ -93,7 +93,6 @@ import type { TaskResult } from './lib/trace-runner'; buildStreamServicePromise, buildMicrosoftCdnPromise, buildSSPanelUIMAppProfilePromise, - downloadMockAssetsPromise ]); diff --git a/Build/lib/fetch-assets.ts b/Build/lib/fetch-assets.ts index 775bd3bc2..09600c29e 100644 --- a/Build/lib/fetch-assets.ts +++ b/Build/lib/fetch-assets.ts @@ -7,7 +7,11 @@ class CustomAbortError extends Error { } const sleepWithAbort = (ms: number, signal: AbortSignal) => new Promise((resolve, reject) => { - signal.throwIfAborted(); + if (signal.aborted) { + reject(signal.reason); + return; + } + signal.addEventListener('abort', stop); Bun.sleep(ms).then(done).catch(doReject);