diff --git "a/\346\230\216\346\226\207\346\272\220\347\240\201.js" "b/\346\230\216\346\226\207\346\272\220\347\240\201.js"
index f78787c1..bb7c6040 100644
--- "a/\346\230\216\346\226\207\346\272\220\347\240\201.js"
+++ "b/\346\230\216\346\226\207\346\272\220\347\240\201.js"
@@ -3,19 +3,19 @@ import { connect } from "cloudflare:sockets";
let password = '';
let proxyIP = '';
-let sub = '';
+let sub = '';
let subConverter = 'SUBAPI.fxxk.dedyn.io';// clash订阅转换后端,目前使用CM的订阅转换功能。自带虚假节点信息防泄露
let subConfig = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini_MultiMode.ini"; //订阅配置文件
let subProtocol = 'https';
let subEmoji = 'true';
let socks5Address = '';
-let parsedSocks5Address = {};
+let parsedSocks5Address = {};
let enableSocks = false;
-let fakeUserID ;
-let fakeHostName ;
+let fakeUserID;
+let fakeHostName;
const expire = 4102329600;//2099-12-31
-let proxyIPs ;
+let proxyIPs;
let socks5s;
let go2Socks5s = [
'*ttvnw.net',
@@ -29,13 +29,13 @@ let addressescsv = [];
let DLS = 8;
let remarkIndex = 1;//CSV备注所在列偏移量
let FileName = 'epeius';
-let BotToken ='';
-let ChatID ='';
+let BotToken = '';
+let ChatID = '';
let proxyhosts = [];
let proxyhostsURL = '';
let RproxyIP = 'false';
-let httpsPorts = ["2053","2083","2087","2096","8443"];
-let sha224Password ;
+let httpsPorts = ["2053", "2083", "2087", "2096", "8443"];
+let sha224Password;
const regex = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[.*\]):?(\d+)?#?(.*)?$/;
let proxyIPPool = [];
let path = '/?ed=2560';
@@ -46,9 +46,9 @@ export default {
try {
const UA = request.headers.get('User-Agent') || 'null';
const userAgent = UA.toLowerCase();
- password = env.PASSWORD || env.pswd || env.UUID || env.uuid || password;
+ password = env.PASSWORD || env.pswd || env.UUID || env.uuid || env.TOKEN || password;
if (!password) {
- return new Response('请设置你的PASSWORD变量,或尝试重试部署,检查变量是否生效?', {
+ return new Response('请设置你的PASSWORD变量,或尝试重试部署,检查变量是否生效?', {
status: 404,
headers: {
"Content-Type": "text/plain;charset=utf-8",
@@ -69,9 +69,9 @@ export default {
fakeUserIDMD5.slice(16, 20),
fakeUserIDMD5.slice(20)
].join('-');
-
+
fakeHostName = `${fakeUserIDMD5.slice(6, 9)}.${fakeUserIDMD5.slice(13, 19)}`;
-
+
proxyIP = env.PROXYIP || env.proxyip || proxyIP;
proxyIPs = await ADD(proxyIP);
proxyIP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)];
@@ -89,7 +89,7 @@ export default {
RproxyIP = env.RPROXYIP || 'false';
enableSocks = true;
} catch (err) {
- /** @type {Error} */
+ /** @type {Error} */
let e = err;
console.log(e.toString());
RproxyIP = env.RPROXYIP || !proxyIP ? 'true' : 'false';
@@ -108,14 +108,14 @@ export default {
DLS = Number(env.DLS) || DLS;
remarkIndex = Number(env.CSVREMARK) || remarkIndex;
BotToken = env.TGTOKEN || BotToken;
- ChatID = env.TGID || ChatID;
+ ChatID = env.TGID || ChatID;
FileName = env.SUBNAME || FileName;
subEmoji = env.SUBEMOJI || env.EMOJI || subEmoji;
- if(subEmoji == '0') subEmoji = 'false';
- if (env.LINK) link = await ADD(env.LINK) ;
+ if (subEmoji == '0') subEmoji = 'false';
+ if (env.LINK) link = await ADD(env.LINK);
sub = env.SUB || sub;
subConverter = env.SUBAPI || subConverter;
- if (subConverter.includes("http://") ){
+ if (subConverter.includes("http://")) {
subConverter = subConverter.split("//")[1];
subProtocol = 'http';
} else {
@@ -135,65 +135,65 @@ export default {
RproxyIP = 'false';
}
switch (url.pathname) {
- case '/':
- if (env.URL302) return Response.redirect(env.URL302, 302);
- else if (env.URL) return await proxyURL(env.URL, url);
- else return new Response(JSON.stringify(request.cf, null, 4), {
- status: 200,
- headers: {
- 'content-type': 'application/json',
- },
- });
- case `/${fakeUserID}`:
- const fakeConfig = await get特洛伊Config(password, request.headers.get('Host'), sub, 'CF-Workers-SUB', RproxyIP, url, env);
- return new Response(`${fakeConfig}`, { status: 200 });
- case `/${password}/edit`:
- const html = await KV(request, env);
- return html;
- case `/${password}`:
- await sendMessage(`#获取订阅 ${FileName}`, request.headers.get('CF-Connecting-IP'), `UA: ${UA}\n域名: ${url.hostname}\n入口: ${url.pathname + url.search}`);
- const 特洛伊Config = await get特洛伊Config(password, request.headers.get('Host'), sub, UA, RproxyIP, url, env);
- const now = Date.now();
- //const timestamp = Math.floor(now / 1000);
- const today = new Date(now);
- today.setHours(0, 0, 0, 0);
- const UD = Math.floor(((now - today.getTime())/86400000) * 24 * 1099511627776 / 2);
- let pagesSum = UD;
- let workersSum = UD;
- let total = 24 * 1099511627776 ;
-
- if (userAgent && (userAgent.includes('mozilla') || userAgent.includes('subconverter'))){
- return new Response(`
${特洛伊Config}
`, {
- status: 200,
- headers: {
- "Content-Type": "text/html;charset=utf-8",
- "Profile-Update-Interval": "6",
- "Subscription-Userinfo": `upload=${pagesSum}; download=${workersSum}; total=${total}; expire=${expire}`,
- "Cache-Control": "no-store",
- }
- });
- } else {
- return new Response(`${特洛伊Config}`, {
+ case '/':
+ if (env.URL302) return Response.redirect(env.URL302, 302);
+ else if (env.URL) return await proxyURL(env.URL, url);
+ else return new Response(JSON.stringify(request.cf, null, 4), {
status: 200,
headers: {
- "Content-Disposition": `attachment; filename=${FileName}; filename*=utf-8''${encodeURIComponent(FileName)}`,
- "Content-Type": "text/plain;charset=utf-8",
- "Profile-Update-Interval": "6",
- "Subscription-Userinfo": `upload=${pagesSum}; download=${workersSum}; total=${total}; expire=${expire}`,
- }
+ 'content-type': 'application/json',
+ },
});
- }
- default:
- if (env.URL302) return Response.redirect(env.URL302, 302);
- else if (env.URL) return await proxyURL(env.URL, url);
- else return new Response('不用怀疑!你PASSWORD就是错的!!!', { status: 404 });
+ case `/${fakeUserID}`:
+ const fakeConfig = await get特洛伊Config(password, request.headers.get('Host'), sub, 'CF-Workers-SUB', RproxyIP, url, env);
+ return new Response(`${fakeConfig}`, { status: 200 });
+ case `/${password}/edit`:
+ const html = await KV(request, env);
+ return html;
+ case `/${password}`:
+ await sendMessage(`#获取订阅 ${FileName}`, request.headers.get('CF-Connecting-IP'), `UA: ${UA}\n域名: ${url.hostname}\n入口: ${url.pathname + url.search}`);
+ const 特洛伊Config = await get特洛伊Config(password, request.headers.get('Host'), sub, UA, RproxyIP, url, env);
+ const now = Date.now();
+ //const timestamp = Math.floor(now / 1000);
+ const today = new Date(now);
+ today.setHours(0, 0, 0, 0);
+ const UD = Math.floor(((now - today.getTime()) / 86400000) * 24 * 1099511627776 / 2);
+ let pagesSum = UD;
+ let workersSum = UD;
+ let total = 24 * 1099511627776;
+
+ if (userAgent && (userAgent.includes('mozilla') || userAgent.includes('subconverter'))) {
+ return new Response(`${特洛伊Config}
`, {
+ status: 200,
+ headers: {
+ "Content-Type": "text/html;charset=utf-8",
+ "Profile-Update-Interval": "6",
+ "Subscription-Userinfo": `upload=${pagesSum}; download=${workersSum}; total=${total}; expire=${expire}`,
+ "Cache-Control": "no-store",
+ }
+ });
+ } else {
+ return new Response(`${特洛伊Config}`, {
+ status: 200,
+ headers: {
+ "Content-Disposition": `attachment; filename=${FileName}; filename*=utf-8''${encodeURIComponent(FileName)}`,
+ "Content-Type": "text/plain;charset=utf-8",
+ "Profile-Update-Interval": "6",
+ "Subscription-Userinfo": `upload=${pagesSum}; download=${workersSum}; total=${total}; expire=${expire}`,
+ }
+ });
+ }
+ default:
+ if (env.URL302) return Response.redirect(env.URL302, 302);
+ else if (env.URL) return await proxyURL(env.URL, url);
+ else return new Response('不用怀疑!你PASSWORD就是错的!!!', { status: 404 });
}
} else {
socks5Address = url.searchParams.get('socks5') || socks5Address;
if (new RegExp('/socks5=', 'i').test(url.pathname)) socks5Address = url.pathname.split('5=')[1];
else if (new RegExp('/socks://', 'i').test(url.pathname) || new RegExp('/socks5://', 'i').test(url.pathname)) {
socks5Address = url.pathname.split('://')[1].split('#')[0];
- if (socks5Address.includes('@')){
+ if (socks5Address.includes('@')) {
let userPassword = socks5Address.split('@')[0];
const base64Regex = /^(?:[A-Z0-9+/]{4})*(?:[A-Z0-9+/]{2}==|[A-Z0-9+/]{3}=)?$/i;
if (base64Regex.test(userPassword) && !userPassword.includes(':')) userPassword = atob(userPassword);
@@ -206,7 +206,7 @@ export default {
parsedSocks5Address = socks5AddressParser(socks5Address);
enableSocks = true;
} catch (err) {
- /** @type {Error} */
+ /** @type {Error} */
let e = err;
console.log(e.toString());
enableSocks = false;
@@ -215,7 +215,7 @@ export default {
enableSocks = false;
}
- if (url.searchParams.has('proxyip')){
+ if (url.searchParams.has('proxyip')) {
proxyIP = url.searchParams.get('proxyip');
enableSocks = false;
} else if (new RegExp('/proxyip=', 'i').test(url.pathname)) {
@@ -348,35 +348,35 @@ async function parse特洛伊Header(buffer) {
let addressIndex = 2;
let address = "";
switch (atype) {
- case 1:
- addressLength = 4;
- address = new Uint8Array(
- socks5DataBuffer.slice(addressIndex, addressIndex + addressLength)
- ).join(".");
- break;
- case 3:
- addressLength = new Uint8Array(
- socks5DataBuffer.slice(addressIndex, addressIndex + 1)
- )[0];
- addressIndex += 1;
- address = new TextDecoder().decode(
- socks5DataBuffer.slice(addressIndex, addressIndex + addressLength)
- );
- break;
- case 4:
- addressLength = 16;
- const dataView = new DataView(socks5DataBuffer.slice(addressIndex, addressIndex + addressLength));
- const ipv6 = [];
- for (let i = 0; i < 8; i++) {
- ipv6.push(dataView.getUint16(i * 2).toString(16));
- }
- address = ipv6.join(":");
- break;
- default:
- return {
- hasError: true,
- message: `invalid addressType is ${atype}`
- };
+ case 1:
+ addressLength = 4;
+ address = new Uint8Array(
+ socks5DataBuffer.slice(addressIndex, addressIndex + addressLength)
+ ).join(".");
+ break;
+ case 3:
+ addressLength = new Uint8Array(
+ socks5DataBuffer.slice(addressIndex, addressIndex + 1)
+ )[0];
+ addressIndex += 1;
+ address = new TextDecoder().decode(
+ socks5DataBuffer.slice(addressIndex, addressIndex + addressLength)
+ );
+ break;
+ case 4:
+ addressLength = 16;
+ const dataView = new DataView(socks5DataBuffer.slice(addressIndex, addressIndex + addressLength));
+ const ipv6 = [];
+ for (let i = 0; i < 8; i++) {
+ ipv6.push(dataView.getUint16(i * 2).toString(16));
+ }
+ address = ipv6.join(":");
+ break;
+ default:
+ return {
+ hasError: true,
+ message: `invalid addressType is ${atype}`
+ };
}
if (!address) {
@@ -400,7 +400,7 @@ async function parse特洛伊Header(buffer) {
async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, log, addressType) {
async function useSocks5Pattern(address) {
- if ( go2Socks5s.includes(atob('YWxsIGlu')) || go2Socks5s.includes(atob('Kg==')) ) return true;
+ if (go2Socks5s.includes(atob('YWxsIGlu')) || go2Socks5s.includes(atob('Kg=='))) return true;
return go2Socks5s.some(pattern => {
let regexPattern = pattern.replace(/\*/g, '.*');
let regex = new RegExp(`^${regexPattern}$`, 'i');
@@ -411,10 +411,10 @@ async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawCli
log(`connected to ${address}:${port}`);
//if (/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(address)) address = `${atob('d3d3Lg==')}${address}${atob('LmlwLjA5MDIyNy54eXo=')}`;
const tcpSocket = socks ? await socks5Connect(addressType, address, port, log)
- : connect({
- hostname: address,
- port
- });
+ : connect({
+ hostname: address,
+ port
+ });
remoteSocket.value = tcpSocket;
//log(`connected to ${address}:${port}`);
const writer = tcpSocket.writable.getWriter();
@@ -446,7 +446,7 @@ async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawCli
remoteSocketToWS(tcpSocket, webSocket, null, log);
}
let useSocks = false;
- if (go2Socks5s.length > 0 && enableSocks ) useSocks = await useSocks5Pattern(addressRemote);
+ if (go2Socks5s.length > 0 && enableSocks) useSocks = await useSocks5Pattern(addressRemote);
let tcpSocket = await connectAndWrite(addressRemote, portRemote, useSocks);
remoteSocketToWS(tcpSocket, webSocket, retry, log);
}
@@ -480,7 +480,7 @@ function makeReadableWebSocketStream(webSocketServer, earlyDataHeader, log) {
controller.enqueue(earlyData);
}
},
- pull(controller) {},
+ pull(controller) { },
cancel(reason) {
if (readableStreamCancel) {
return;
@@ -497,7 +497,7 @@ async function remoteSocketToWS(remoteSocket, webSocket, retry, log) {
let hasIncomingData = false;
await remoteSocket.readable.pipeTo(
new WritableStream({
- start() {},
+ start() { },
/**
*
* @param {Uint8Array} chunk
@@ -583,7 +583,7 @@ function revertFakeInfo(content, userID, hostName, isBase64) {
async function MD5MD5(text) {
const encoder = new TextEncoder();
-
+
const firstPass = await crypto.subtle.digest('MD5', encoder.encode(text));
const firstPassArray = Array.from(new Uint8Array(firstPass));
const firstHex = firstPassArray.map(b => b.toString(16).padStart(2, '0')).join('');
@@ -591,7 +591,7 @@ async function MD5MD5(text) {
const secondPass = await crypto.subtle.digest('MD5', encoder.encode(firstHex.slice(7, 27)));
const secondPassArray = Array.from(new Uint8Array(secondPass));
const secondHex = secondPassArray.map(b => b.toString(16).padStart(2, '0')).join('');
-
+
return secondHex.toLowerCase();
}
@@ -599,14 +599,14 @@ async function ADD(内容) {
// 将制表符、双引号、单引号和换行符都替换为逗号
// 然后将连续的多个逗号替换为单个逗号
var 替换后的内容 = 内容.replace(/[ |"'\r\n]+/g, ',').replace(/,+/g, ',');
-
+
// 删除开头和结尾的逗号(如果有的话)
if (替换后的内容.charAt(0) == ',') 替换后的内容 = 替换后的内容.slice(1);
if (替换后的内容.charAt(替换后的内容.length - 1) == ',') 替换后的内容 = 替换后的内容.slice(0, 替换后的内容.length - 1);
-
+
// 使用逗号分割字符串,得到地址数组
const 地址数组 = 替换后的内容.split(',');
-
+
return 地址数组;
}
@@ -646,26 +646,26 @@ async function proxyURL(proxyURL, url) {
function 配置信息(密码, 域名地址) {
const 啥啥啥_写的这是啥啊 = 'dHJvamFu';
const 协议类型 = atob(啥啥啥_写的这是啥啊);
-
+
const 别名 = FileName;
let 地址 = 域名地址;
let 端口 = 443;
-
+
const 传输层协议 = 'ws';
const 伪装域名 = 域名地址;
const 路径 = path;
-
- let 传输层安全 = ['tls',true];
+
+ let 传输层安全 = ['tls', true];
const SNI = 域名地址;
const 指纹 = 'randomized';
-
- const v2ray = `${协议类型}://${encodeURIComponent(密码)}@${地址}:${端口}?security=${传输层安全[0]}&sni=${SNI}&alpn=h3&fp=${指纹}&allowInsecure=1&type=${传输层协议}&host=${伪装域名}&path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`
+
+ const v2ray = `${协议类型}://${encodeURIComponent(密码)}@${地址}:${端口}?security=${传输层安全[0]}&sni=${SNI}&alpn=h3&fp=${指纹}&allowInsecure=1&type=${传输层协议}&host=${伪装域名}&path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`
const clash = `- {name: ${别名}, server: ${地址}, port: ${端口}, udp: false, client-fingerprint: ${指纹}, type: ${协议类型}, password: ${密码}, sni: ${SNI}, alpn: [h3], skip-cert-verify: true, network: ${传输层协议}, ws-opts: {path: "${路径}", headers: {Host: ${伪装域名}}}}`;
- return [v2ray,clash];
+ return [v2ray, clash];
}
-let subParams = ['sub','base64','b64','clash','singbox','sb','surge'];
+let subParams = ['sub', 'base64', 'b64', 'clash', 'singbox', 'sb', 'surge'];
const cmad = decodeURIComponent(atob(`dGVsZWdyYW0lMjAlRTQlQkElQTQlRTYlQjUlODElRTclQkUlQTQlMjAlRTYlOEElODAlRTYlOUMlQUYlRTUlQTQlQTclRTQlQkQlQUMlN0UlRTUlOUMlQTglRTclQkElQkYlRTUlOEYlOTElRTclODklOEMhJTNDYnIlM0UKJTNDYSUyMGhyZWYlM0QlMjdodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlMjclM0VodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlM0MlMkZhJTNFJTNDYnIlM0UKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJTNDYnIlM0UKZ2l0aHViJTIwJUU5JUExJUI5JUU3JTlCJUFFJUU1JTlDJUIwJUU1JTlEJTgwJTIwU3RhciFTdGFyIVN0YXIhISElM0NiciUzRQolM0NhJTIwaHJlZiUzRCUyN2h0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZXBlaXVzJTI3JTNFaHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGY21saXUlMkZlcGVpdXMlM0MlMkZhJTNFJTNDYnIlM0UKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJTNDYnIlM0UKJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIzJTIz`));
async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, env) {
if (sub) {
@@ -676,7 +676,7 @@ async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, e
const subs = await ADD(sub);
if (subs.length > 1) sub = subs[0];
} else {
- if (env.KV){
+ if (env.KV) {
await 迁移地址列表(env);
const 优选地址列表 = await env.KV.get('ADD.txt');
if (优选地址列表) {
@@ -686,7 +686,7 @@ async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, e
链接地址: new Set(),
优选地址: new Set()
};
-
+
for (const 元素 of 优选地址数组) {
if (元素.startsWith('https://')) {
分类地址.接口地址.add(元素);
@@ -696,14 +696,14 @@ async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, e
分类地址.优选地址.add(元素);
}
}
-
+
addressesapi = [...分类地址.接口地址];
link = [...分类地址.链接地址];
addresses = [...分类地址.优选地址];
}
}
- if ((addresses.length + addressesapi.length + addressescsv.length) == 0){
+ if ((addresses.length + addressesapi.length + addressescsv.length) == 0) {
// 定义 Cloudflare IP 范围的 CIDR 列表
let cfips = [
'103.21.244.0/23',
@@ -718,7 +718,7 @@ async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, e
'188.114.96.0/21',
'190.93.240.0/21',
];
-
+
// 生成符合给定 CIDR 范围的随机 IP 地址
function generateRandomIPFromCIDR(cidr) {
const [base, mask] = cidr.split('/');
@@ -726,13 +726,13 @@ async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, e
const subnetMask = 32 - parseInt(mask, 10);
const maxHosts = Math.pow(2, subnetMask) - 1;
const randomHost = Math.floor(Math.random() * maxHosts);
-
+
const randomIP = baseIP.map((octet, index) => {
if (index < 2) return octet;
if (index === 2) return (octet & (255 << (subnetMask - 8))) + ((randomHost >> 8) & 255);
return (octet & (255 << subnetMask)) + (randomHost & 255);
});
-
+
return randomIP.join('.');
}
addresses = addresses.concat('127.0.0.1:1234#CFnat');
@@ -741,35 +741,35 @@ async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, e
}
const userAgent = UA.toLowerCase();
- const Config = 配置信息(password , hostName);
+ const Config = 配置信息(password, hostName);
const v2ray = Config[0];
const clash = Config[1];
let proxyhost = "";
- if (hostName.includes(".workers.dev")){
- if ( proxyhostsURL && (!proxyhosts || proxyhosts.length == 0)) {
+ if (hostName.includes(".workers.dev")) {
+ if (proxyhostsURL && (!proxyhosts || proxyhosts.length == 0)) {
try {
- const response = await fetch(proxyhostsURL);
-
+ const response = await fetch(proxyhostsURL);
+
if (!response.ok) {
console.error('获取地址时出错:', response.status, response.statusText);
return; // 如果有错误,直接返回
}
-
+
const text = await response.text();
const lines = text.split('\n');
// 过滤掉空行或只包含空白字符的行
const nonEmptyLines = lines.filter(line => line.trim() !== '');
-
+
proxyhosts = proxyhosts.concat(nonEmptyLines);
} catch (error) {
//console.error('获取地址时出错:', error);
}
- }
+ }
if (proxyhosts.length != 0) proxyhost = proxyhosts[Math.floor(Math.random() * proxyhosts.length)] + "/";
}
-
- if ( userAgent.includes('mozilla') && !subParams.some(_searchParams => _url.searchParams.has(_searchParams))) {
- let surge = `Surge订阅地址:
https://${proxyhost}${hostName}/${password}?surge`;
+
+ if (userAgent.includes('mozilla') && !subParams.some(_searchParams => _url.searchParams.has(_searchParams))) {
+ let surge = `Surge订阅地址:
https://${proxyhost}${hostName}/${password}?surge
`;
if (hostName.includes(".workers.dev")) surge = "Surge订阅必须绑定自定义域";
const newSocks5s = socks5s.map(socks5Address => {
if (socks5Address.includes('@')) return socks5Address.split('@')[1];
@@ -778,9 +778,9 @@ async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, e
});
let socks5List = '';
- if (go2Socks5s.length > 0 && enableSocks ) {
+ if (go2Socks5s.length > 0 && enableSocks) {
socks5List = `${decodeURIComponent('SOCKS5%EF%BC%88%E7%99%BD%E5%90%8D%E5%8D%95%EF%BC%89%3A%20')}`;
- if ( go2Socks5s.includes(atob('YWxsIGlu')) || go2Socks5s.includes(atob('Kg==')) ) socks5List += `${decodeURIComponent('%E6%89%80%E6%9C%89%E6%B5%81%E9%87%8F')}
`;
+ if (go2Socks5s.includes(atob('YWxsIGlu')) || go2Socks5s.includes(atob('Kg=='))) socks5List += `${decodeURIComponent('%E6%89%80%E6%9C%89%E6%B5%81%E9%87%8F')}
`;
else socks5List += `
${go2Socks5s.join('
')}
`;
}
@@ -805,25 +805,21 @@ async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, e
const 节点配置页 = `
################################################################
- Subscribe / sub 订阅地址, 支持 Base64、clash-meta、sing-box 订阅格式
+ Subscribe / sub 订阅地址, 点击链接自动 复制订阅链接 并 生成订阅二维码
---------------------------------------------------------------
自适应订阅地址:
- https://${proxyhost}${hostName}/${password}
- https://${proxyhost}${hostName}/${password}?sub
-
+ https://${proxyhost}${hostName}/${password}
+
Base64订阅地址:
- https://${proxyhost}${hostName}/${password}?b64
- https://${proxyhost}${hostName}/${password}?base64
-
+ https://${proxyhost}${hostName}/${password}?b64
+
clash订阅地址:
- https://${proxyhost}${hostName}/${password}?clash
-
+ https://${proxyhost}${hostName}/${password}?clash
+
singbox订阅地址:
- https://${proxyhost}${hostName}/${password}?sb
- https://${proxyhost}${hostName}/${password}?singbox
-
- ${surge}
-
+ https://${proxyhost}${hostName}/${password}?sb
+
+ ${surge}
实用订阅技巧∨
1. 如您使用的是 PassWall、SSR+ 等路由插件,推荐使用 Base64订阅地址 进行订阅;
@@ -840,13 +836,25 @@ async function get特洛伊Config(password, hostName, sub, UA, RproxyIP, _url, e
5. 如需指定多个参数则需要使用'&'做间隔,例如:
https://${proxyhost}${hostName}/${password}?sub=sub.google.com&proxyip=proxyip.fxxk.dedyn.io
+