«من حرفهایام! پایگاه IP دارم! IPtest رو میشناسم! فایل csv تست سرعت هم دارم!»
«من حرفهایام! پایگاه IP دارم! IPtest رو میشناسم! فایل csv تست سرعت هم دارم!»
「 Pages Github 部署方法 」
「 Workers 部署方法 」
If you see this page, the nginx web server is successfully installed and 266 | working. Further configuration is required.
267 | 268 |For online documentation and support please refer to
269 | nginx.org.
270 | Commercial support is available at
271 | nginx.com.
Thank you for using nginx.
274 | 275 | 276 | ` 277 | return text; 278 | } 279 | 280 | function surge(content, url, path) { 281 | let 每行内容; 282 | if (content.includes('\r\n')) { 283 | 每行内容 = content.split('\r\n'); 284 | } else { 285 | 每行内容 = content.split('\n'); 286 | } 287 | 288 | let 输出内容 = ""; 289 | for (let x of 每行内容) { 290 | if (x.includes(atob('PSB0cm9qYW4s'))) { 291 | const host = x.split("sni=")[1].split(",")[0]; 292 | const 备改内容 = `skip-cert-verify=true, tfo=false, udp-relay=false`; 293 | const 正确内容 = `skip-cert-verify=true, ws=true, ws-path=${path}, ws-headers=Host:"${host}", tfo=false, udp-relay=false`; 294 | 输出内容 += x.replace(new RegExp(备改内容, 'g'), 正确内容).replace("[", "").replace("]", "") + '\n'; 295 | } else { 296 | 输出内容 += x + '\n'; 297 | } 298 | } 299 | 300 | 输出内容 = `#!MANAGED-CONFIG ${url.href} interval=86400 strict=false` + 输出内容.substring(输出内容.indexOf('\n')); 301 | return 输出内容; 302 | } 303 | 304 | function getRandomProxyByMatch(CC, socks5Data) { 305 | // 将匹配字符串转换为小写 306 | const lowerCaseMatch = CC.toLowerCase(); 307 | 308 | // 过滤出所有以指定匹配字符串结尾的代理字符串 309 | let filteredProxies = socks5Data.filter(proxy => proxy.toLowerCase().endsWith(`#${lowerCaseMatch}`)); 310 | 311 | // 如果没有匹配的代理,尝试匹配 "US" 312 | if (filteredProxies.length === 0) { 313 | filteredProxies = socks5Data.filter(proxy => proxy.toLowerCase().endsWith(`#us`)); 314 | } 315 | 316 | // 如果还是没有匹配的代理,从整个代理列表中随机选择一个 317 | if (filteredProxies.length === 0) { 318 | return socks5Data[Math.floor(Math.random() * socks5Data.length)]; 319 | } 320 | 321 | // 从匹配的代理中随机选择一个并返回 322 | const randomProxy = filteredProxies[Math.floor(Math.random() * filteredProxies.length)]; 323 | return randomProxy; 324 | } 325 | 326 | async function MD5MD5(text) { 327 | const encoder = new TextEncoder(); 328 | 329 | const firstPass = await crypto.subtle.digest('MD5', encoder.encode(text)); 330 | const firstPassArray = Array.from(new Uint8Array(firstPass)); 331 | const firstHex = firstPassArray.map(b => b.toString(16).padStart(2, '0')).join(''); 332 | 333 | const secondPass = await crypto.subtle.digest('MD5', encoder.encode(firstHex.slice(7, 27))); 334 | const secondPassArray = Array.from(new Uint8Array(secondPass)); 335 | const secondHex = secondPassArray.map(b => b.toString(16).padStart(2, '0')).join(''); 336 | 337 | return secondHex.toLowerCase(); 338 | } 339 | 340 | function revertFakeInfo(content, userID, hostName) { 341 | content = content.replace(new RegExp(fakeUserID, 'g'), userID).replace(new RegExp(fakeHostName, 'g'), hostName); 342 | return content; 343 | } 344 | 345 | function generateFakeInfo(content, userID, hostName) { 346 | content = content.replace(new RegExp(userID, 'g'), fakeUserID).replace(new RegExp(hostName, 'g'), fakeHostName); 347 | return content; 348 | } 349 | 350 | function isValidIPv4(address) { 351 | const ipv4Regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; 352 | return ipv4Regex.test(address); 353 | } 354 | 355 | function 生成动态UUID(密钥) { 356 | const 时区偏移 = 8; // 北京时间相对于UTC的时区偏移+8小时 357 | const 起始日期 = new Date(2007, 6, 7, 更新时间, 0, 0); // 固定起始日期为2007年7月7日的凌晨3点 358 | const 一周的毫秒数 = 1000 * 60 * 60 * 24 * 有效时间; 359 | 360 | function 获取当前周数() { 361 | const 现在 = new Date(); 362 | const 调整后的现在 = new Date(现在.getTime() + 时区偏移 * 60 * 60 * 1000); 363 | const 时间差 = Number(调整后的现在) - Number(起始日期); 364 | return Math.ceil(时间差 / 一周的毫秒数); 365 | } 366 | 367 | function 生成UUID(基础字符串) { 368 | const 哈希缓冲区 = new TextEncoder().encode(基础字符串); 369 | return crypto.subtle.digest('SHA-256', 哈希缓冲区).then((哈希) => { 370 | const 哈希数组 = Array.from(new Uint8Array(哈希)); 371 | const 十六进制哈希 = 哈希数组.map(b => b.toString(16).padStart(2, '0')).join(''); 372 | return `${十六进制哈希.substr(0, 8)}-${十六进制哈希.substr(8, 4)}-4${十六进制哈希.substr(13, 3)}-${(parseInt(十六进制哈希.substr(16, 2), 16) & 0x3f | 0x80).toString(16)}${十六进制哈希.substr(18, 2)}-${十六进制哈希.substr(20, 12)}`; 373 | }); 374 | } 375 | 376 | const 当前周数 = 获取当前周数(); // 获取当前周数 377 | const 结束时间 = new Date(起始日期.getTime() + 当前周数 * 一周的毫秒数); 378 | 379 | // 生成两个 UUID 380 | const 当前UUIDPromise = 生成UUID(密钥 + 当前周数); 381 | const 上一个UUIDPromise = 生成UUID(密钥 + (当前周数 - 1)); 382 | 383 | // 格式化到期时间 384 | const 到期时间UTC = new Date(结束时间.getTime() - 时区偏移 * 60 * 60 * 1000); // UTC时间 385 | const 到期时间字符串 = `到期时间(UTC): ${到期时间UTC.toISOString().slice(0, 19).replace('T', ' ')} (UTC+8): ${结束时间.toISOString().slice(0, 19).replace('T', ' ')}\n`; 386 | 387 | return Promise.all([当前UUIDPromise, 上一个UUIDPromise, 到期时间字符串]); 388 | } 389 | 390 | async function getLink(重新汇总所有链接) { 391 | let 节点LINK = []; 392 | let 订阅链接 = []; 393 | for (let x of 重新汇总所有链接) { 394 | if (x.toLowerCase().startsWith('http')) { 395 | 订阅链接.push(x); 396 | } else { 397 | 节点LINK.push(x); 398 | } 399 | } 400 | 401 | if (订阅链接 && 订阅链接.length !== 0) { 402 | function base64Decode(str) { 403 | const bytes = new Uint8Array(atob(str).split('').map(c => c.charCodeAt(0))); 404 | const decoder = new TextDecoder('utf-8'); 405 | return decoder.decode(bytes); 406 | } 407 | const controller = new AbortController(); // 创建一个AbortController实例,用于取消请求 408 | 409 | const timeout = setTimeout(() => { 410 | controller.abort(); // 2秒后取消所有请求 411 | }, 2000); 412 | 413 | try { 414 | // 使用Promise.allSettled等待所有API请求完成,无论成功或失败 415 | const responses = await Promise.allSettled(订阅链接.map(apiUrl => fetch(apiUrl, { 416 | method: 'get', 417 | headers: { 418 | 'Accept': 'text/html,application/xhtml+xml,application/xml;', 419 | 'User-Agent': `\u0076\u0032\u0072\u0061\u0079\u004e\u002f${FileName + atob('IGNtbGl1L1dvcmtlclZsZXNzMnN1Yg==')}` 420 | }, 421 | signal: controller.signal // 将AbortController的信号量添加到fetch请求中 422 | }).then(response => response.ok ? response.text() : Promise.reject()))); 423 | 424 | // 遍历所有响应 425 | const modifiedResponses = responses.map((response, index) => { 426 | // 检查是否请求成功 427 | return { 428 | status: response.status, 429 | value: response.status === 'fulfilled' ? response.value : null, 430 | apiUrl: 订阅链接[index] // 将原始的apiUrl添加到返回对象中 431 | }; 432 | }); 433 | 434 | console.log(modifiedResponses); // 输出修改后的响应数组 435 | 436 | for (const response of modifiedResponses) { 437 | // 检查响应状态是否为'fulfilled' 438 | if (response.status === 'fulfilled') { 439 | const content = await response.value || 'null'; // 获取响应的内容 440 | if (content.includes('://')) { 441 | const lines = content.includes('\r\n') ? content.split('\r\n') : content.split('\n'); 442 | 节点LINK = 节点LINK.concat(lines); 443 | } else { 444 | const 尝试base64解码内容 = base64Decode(content); 445 | if (尝试base64解码内容.includes('://')) { 446 | const lines = 尝试base64解码内容.includes('\r\n') ? 尝试base64解码内容.split('\r\n') : 尝试base64解码内容.split('\n'); 447 | 节点LINK = 节点LINK.concat(lines); 448 | } 449 | } 450 | } 451 | } 452 | } catch (error) { 453 | console.error(error); // 捕获并输出错误信息 454 | } finally { 455 | clearTimeout(timeout); // 清除定时器 456 | } 457 | } 458 | 459 | return 节点LINK; 460 | } 461 | 462 | function utf8ToBase64(str) { 463 | return btoa(unescape(encodeURIComponent(str))); 464 | } 465 | 466 | export default { 467 | async fetch(request, env) { 468 | if (env.TOKEN) 快速订阅访问入口 = await 整理(env.TOKEN); 469 | BotToken = env.TGTOKEN || BotToken; 470 | ChatID = env.TGID || ChatID; 471 | subConverter = env.SUBAPI || subConverter; 472 | subConfig = env.SUBCONFIG || subConfig; 473 | FileName = env.SUBNAME || FileName; 474 | socks5DataURL = env.SOCKS5DATA || socks5DataURL; 475 | if (env.CMPROXYIPS) 匹配PROXYIP = await 整理(env.CMPROXYIPS);; 476 | if (env.CFPORTS) httpsPorts = await 整理(env.CFPORTS); 477 | EndPS = env.PS || EndPS; 478 | 网站图标 = env.ICO ? `` : ''; 479 | 网站头像 = env.PNG ? `