class LinkChecker {
static PROXY_SERVERS = [
"https://cors.eu.org/",
"https://api.netnr.eu.org/link/",
"https://api.codetabs.com/v1/proxy?quest=",
"https://netnr.zme.ink/api/Open/Proxy?url="
];
static proxyIndex = 0;
static DEFAULT_TIMEOUT = 10000;
static DEFAULT_CONCURRENCY = 6;
static getProxyUrl(link) {
const proxyServer = this.PROXY_SERVERS[this.proxyIndex++];
if (this.proxyIndex >= this.PROXY_SERVERS.length) {
this.proxyIndex = 0;
}
return `${proxyServer}${encodeURIComponent(link)}`;
}
static async checkSingleLink(link, timeout = this.DEFAULT_TIMEOUT) {
const url = this.getProxyUrl(link.href);
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
const response = await fetch(url, {
signal: controller.signal
});
clearTimeout(timeoutId);
return {
link,
success: response.ok
};
} catch (error) {
return {
link,
success: false
};
}
}
static async checkLinks(
links = document.links,
concurrency = this.DEFAULT_CONCURRENCY,
timeout = this.DEFAULT_TIMEOUT
) {
const linksArray = Array.from(links);
const resultOk = [];
const resultBad = [];
let currentIndex = 0;
const processNext = async () => {
while (currentIndex < linksArray.length) {
const index = currentIndex++;
const link = linksArray[index];
try {
const result = await this.checkSingleLink(link, timeout);
if (result.success) {
resultOk.push(result.link);
} else {
resultBad.push(result.link);
}
console.debug(`ok: ${resultOk.length}, bad: ${resultBad.length}, progress: ${index + 1}/${linksArray.length}`);
} catch (error) {
resultBad.push(link);
console.debug(`ok: ${resultOk.length}, bad: ${resultBad.length}, progress: ${index + 1}/${linksArray.length}`);
}
}
};
const tasks = Array(concurrency).fill(null).map(() => processNext());
await Promise.all(tasks);
if (resultBad.length > 0) {
console.debug('坏链接列表:');
console.debug(resultBad.map(link => link.href).join('\r\n'));
}
return {
okLinks: resultOk,
badLinks: resultBad
};
}
static async init(links, concurrency, timeout) {
console.debug('开始检测链接...');
const result = await this.checkLinks(links, concurrency, timeout);
console.debug('检测完成!');
return result;
}
}
LinkChecker.init();