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 03b041348..25c70f6e4 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" @@ -4,9 +4,10 @@ import { connect } from 'cloudflare:sockets'; let userID = ''; let proxyIP = ''; let sub = ''; -let subconverter = 'SUBAPI.fxxk.dedyn.io'; -let subconfig = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini_MultiMode.ini"; +let subConverter = 'SUBAPI.fxxk.dedyn.io'; +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 enableSocks = false; @@ -29,6 +30,7 @@ let addressesnotls = []; let addressesnotlsapi = []; let addressescsv = []; let DLS = 8; +let remarkIndex = 1;//CSV备注所在列偏移量 let FileName = atob('ZWRnZXR1bm5lbA=='); let BotToken; let ChatID; @@ -36,11 +38,12 @@ let proxyhosts = []; let proxyhostsURL = ''; let RproxyIP = 'false'; let httpsPorts = ["2053","2083","2087","2096","8443"]; -let 有效时间 = 7;//有效时间 单位:天 -let 更新时间 = 3;//更新时间 +let 有效时间 = 7; +let 更新时间 = 3; let userIDLow; let userIDTime = ""; let proxyIPPool = []; +let path = '/?ed=2560'; export default { async fetch(request, env, ctx) { try { @@ -56,8 +59,11 @@ export default { userID = env.UUID; } + subEmoji = env.SUBEMOJI || env.EMOJI || subEmoji; + if(subEmoji == '0') subEmoji = 'false'; + if (!userID) { - return new Response('请设置你的UUID变量,或尝试重试部署,检查变量是否成效?', { + return new Response('请设置你的UUID变量,或尝试重试部署,检查变量是否生效?', { status: 404, headers: { "Content-Type": "text/plain;charset=utf-8", @@ -88,14 +94,14 @@ export default { socks5Address = socks5Address.split('//')[1] || socks5Address; if (env.CFPORTS) httpsPorts = await 整理(env.CFPORTS); sub = env.SUB || sub; - subconverter = env.SUBAPI || subconverter; - if( subconverter.includes("http://") ){ - subconverter = subconverter.split("//")[1]; + subConverter = env.SUBAPI || subConverter; + if( subConverter.includes("http://") ){ + subConverter = subConverter.split("//")[1]; subProtocol = 'http'; } else { - subconverter = subconverter.split("//")[1] || subconverter; + subConverter = subConverter.split("//")[1] || subConverter; } - subconfig = env.SUBCONFIG || subconfig; + subConfig = env.SUBCONFIG || subConfig; if (socks5Address) { try { parsedSocks5Address = socks5AddressParser(socks5Address); @@ -116,6 +122,7 @@ export default { if (env.ADDNOTLSAPI) addressesnotlsapi = await 整理(env.ADDNOTLSAPI); if (env.ADDCSV) addressescsv = await 整理(env.ADDCSV); DLS = env.DLS || DLS; + remarkIndex = env.CSVREMARK || remarkIndex; BotToken = env.TGTOKEN || BotToken; ChatID = env.TGID || ChatID; if(env.GO2SOCKS5) go2Socks5s = await 整理(env.GO2SOCKS5); @@ -125,6 +132,16 @@ export default { FileName = env.SUBNAME || FileName; if (url.searchParams.has('notls')) noTLS = 'true'; if (!upgradeHeader || upgradeHeader !== 'websocket') { + if (url.searchParams.has('proxyip')) { + path = `/?ed=2560&proxyip=${url.searchParams.get('proxyip')}`; + RproxyIP = 'false'; + } else if (url.searchParams.has('socks5')) { + path = `/?ed=2560&socks5=${url.searchParams.get('socks5')}`; + RproxyIP = 'false'; + } else if (url.searchParams.has('socks')) { + path = `/?ed=2560&socks5=${url.searchParams.get('socks')}`; + RproxyIP = 'false'; + } const 路径 = url.pathname.toLowerCase(); if (路径 == '/') { if (env.URL302) return Response.redirect(env.URL302, 302); @@ -176,10 +193,6 @@ export default { else return new Response(``, { status: 404 }); } } else { - proxyIP = url.searchParams.get('proxyip') || proxyIP; - if (new RegExp('/proxyip=', 'i').test(url.pathname)) proxyIP = url.pathname.toLowerCase().split('/proxyip=')[1]; - else if (new RegExp('/proxyip.', 'i').test(url.pathname)) proxyIP = `proxyip.${url.pathname.toLowerCase().split("/proxyip.")[1]}`; - 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)) { @@ -191,6 +204,7 @@ export default { socks5Address = `${userPassword}@${socks5Address.split('@')[1]}`; } } + if (socks5Address) { try { parsedSocks5Address = socks5AddressParser(socks5Address); @@ -204,6 +218,17 @@ export default { enableSocks = false; } + if (url.searchParams.has('proxyip')){ + proxyIP = url.searchParams.get('proxyip'); + enableSocks = false; + } else if (new RegExp('/proxyip=', 'i').test(url.pathname)) { + proxyIP = url.pathname.toLowerCase().split('/proxyip=')[1]; + enableSocks = false; + } else if (new RegExp('/proxyip.', 'i').test(url.pathname)) { + proxyIP = `proxyip.${url.pathname.toLowerCase().split("/proxyip.")[1]}`; + enableSocks = false; + } + return await 维列斯OverWSHandler(request); } } catch (err) { @@ -1151,7 +1176,7 @@ function 配置信息(UUID, 域名地址) { const 传输层协议 = 'ws'; const 伪装域名 = 域名地址; - const 路径 = '/?ed=2560'; + const 路径 = path; let 传输层安全 = ['tls',true]; const SNI = 域名地址; @@ -1196,6 +1221,9 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env if (match) { sub = match[1]; } + const subs = 整理(sub); + if (subs.length > 1) sub = subs[0]; + } else if ((addresses.length + addressesapi.length + addressesnotls.length + addressesnotlsapi.length + addressescsv.length) == 0){ // 定义 Cloudflare IP 范围的 CIDR 列表 let cfips = [ @@ -1280,6 +1308,12 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env let 订阅器 = '\n'; if (sub) { + if (enableSocks) 订阅器 += `CFCDN(访问方式): Socks5\n ${newSocks5s.join('\n ')}\n${socks5List}`; + else if (proxyIP && proxyIP != '') 订阅器 += `CFCDN(访问方式): ProxyIP\n ${proxyIPs.join('\n ')}\n`; + else if (RproxyIP == 'true') 订阅器 += `CFCDN(访问方式): 自动获取ProxyIP\n`; + else 订阅器 += `CFCDN(访问方式): 无法访问, 需要您设置 proxyIP/PROXYIP !!!\n` + 订阅器 += `\nSUB(优选订阅生成器): ${sub}`; + } else { if (enableSocks) 订阅器 += `CFCDN(访问方式): Socks5\n ${newSocks5s.join('\n ')}\n${socks5List}`; else if (proxyIP && proxyIP != '') 订阅器 += `CFCDN(访问方式): ProxyIP\n ${proxyIPs.join('\n ')}\n`; else 订阅器 += `CFCDN(访问方式): 无法访问, 需要您设置 proxyIP/PROXYIP !!!\n`; @@ -1289,16 +1323,10 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env if (addressesapi.length > 0) 订阅器 += `ADDAPI(TLS优选域名&IP 的 API): \n ${addressesapi.join('\n ')}\n`; if (addressesnotlsapi.length > 0) 订阅器 += `ADDNOTLSAPI(noTLS优选域名&IP 的 API): \n ${addressesnotlsapi.join('\n ')}\n`; if (addressescsv.length > 0) 订阅器 += `ADDCSV(IPTest测速csv文件 限速 ${DLS} ): \n ${addressescsv.join('\n ')}\n`; - } else { - if (enableSocks) 订阅器 += `CFCDN(访问方式): Socks5\n ${newSocks5s.join('\n ')}\n${socks5List}`; - else if (proxyIP && proxyIP != '') 订阅器 += `CFCDN(访问方式): ProxyIP\n ${proxyIPs.join('\n ')}\n`; - else if (RproxyIP == 'true') 订阅器 += `CFCDN(访问方式): 自动获取ProxyIP\n`; - else 订阅器 += `CFCDN(访问方式): 无法访问, 需要您设置 proxyIP/PROXYIP !!!\n` - 订阅器 += `\nSUB(优选订阅生成器): ${sub}`; } if (env.KEY && _url.pathname !== `/${env.KEY}`) 订阅器 = ''; - else 订阅器 += `\nSUBAPI(订阅转换后端): ${subProtocol}://${subconverter}\nSUBCONFIG(订阅转换配置文件): ${subconfig}`; + else 订阅器 += `\nSUBAPI(订阅转换后端): ${subProtocol}://${subConverter}\nSUBCONFIG(订阅转换配置文件): ${subConfig}`; const 动态UUID = (uuid != userID) ? `TOKEN: ${uuid}\nUUIDNow: ${userID}\nUUIDLow: ${userIDLow}\n${userIDTime}TIME(动态UUID有效时间): ${有效时间} 天\nUPTIME(动态UUID更新时间): ${更新时间} 时(北京时间)\n\n` : `${userIDTime}`; return ` ################################################################ @@ -1339,7 +1367,7 @@ clash-meta ${clash} --------------------------------------------------------------- ################################################################ -${atob('dGVsZWdyYW0g5Lqk5rWB576kIOaKgOacr+Wkp+S9rH7lnKjnur/lj5HniYwhCmh0dHBzOi8vdC5tZS9DTUxpdXNzc3MKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmdpdGh1YiDpobnnm67lnLDlnYAgU3RhciFTdGFyIVN0YXIhISEKaHR0cHM6Ly9naXRodWIuY29tL2NtbGl1L2VkZ2V0dW5uZWwKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyM=')} +${decodeURIComponent(atob('dGVsZWdyYW0lMjAlRTQlQkElQTQlRTYlQjUlODElRTclQkUlQTQlMjAlRTYlOEElODAlRTYlOUMlQUYlRTUlQTQlQTclRTQlQkQlQUMlN0UlRTUlOUMlQTglRTclQkElQkYlRTUlOEYlOTElRTclODklOEMhCmh0dHBzJTNBJTJGJTJGdC5tZSUyRkNNTGl1c3NzcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KZ2l0aHViJTIwJUU5JUExJUI5JUU3JTlCJUFFJUU1JTlDJUIwJUU1JTlEJTgwJTIwU3RhciFTdGFyIVN0YXIhISEKaHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGY21saXUlMkZlZGdldHVubmVsCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQolMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjM='))} `; } else { if (typeof fetch != 'function') { @@ -1368,7 +1396,7 @@ ${atob('dGVsZWdyYW0g5Lqk5rWB576kIOaKgOacr+Wkp+S9rH7lnKjnur/lj5HniYwhCmh0dHBzOi8v fakeHostName = `${fakeHostName}.xyz` } console.log(`虚假HOST: ${fakeHostName}`); - let url = `${subProtocol}://${sub}/sub?host=${fakeHostName}&uuid=${fakeUserID + atob('JmVkZ2V0dW5uZWw9Y21saXUmcHJveHlpcD0=') + RproxyIP}`; + let url = `${subProtocol}://${sub}/sub?host=${fakeHostName}&uuid=${fakeUserID + atob('JmVkZ2V0dW5uZWw9Y21saXUmcHJveHlpcD0=') + RproxyIP}&path=${encodeURIComponent(path)}`; let isBase64 = true; if (!sub || sub == ""){ @@ -1398,17 +1426,20 @@ ${atob('dGVsZWdyYW0g5Lqk5rWB576kIOaKgOacr+Wkp+S9rH7lnKjnur/lj5HniYwhCmh0dHBzOi8v newAddressesapi = await 整理优选列表(addressesapi); newAddressescsv = await 整理测速结果('TRUE'); - url = `https://${hostName}/${fakeUserID}`; - if (hostName.includes("worker") || hostName.includes("notls") || noTLS == 'true') url += '?notls'; + url = `https://${hostName}/${fakeUserID + _url.search}`; + if (hostName.includes("worker") || hostName.includes("notls") || noTLS == 'true') { + if (_url.search) url += '¬ls'; + else url += '?notls'; + } console.log(`虚假订阅: ${url}`); } if (!userAgent.includes(('CF-Workers-SUB').toLowerCase())){ if ((userAgent.includes('clash') && !userAgent.includes('nekobox')) || ( _url.searchParams.has('clash') && !userAgent.includes('subconverter'))) { - url = `${subProtocol}://${subconverter}/sub?target=clash&url=${encodeURIComponent(url)}&insert=false&config=${encodeURIComponent(subconfig)}&emoji=true&list=false&tfo=false&scv=true&fdn=false&sort=false&new_name=true`; + url = `${subProtocol}://${subConverter}/sub?target=clash&url=${encodeURIComponent(url)}&insert=false&config=${encodeURIComponent(subConfig)}&emoji=${subEmoji}&list=false&tfo=false&scv=true&fdn=false&sort=false&new_name=true`; isBase64 = false; } else if (userAgent.includes('sing-box') || userAgent.includes('singbox') || (( _url.searchParams.has('singbox') || _url.searchParams.has('sb')) && !userAgent.includes('subconverter'))) { - url = `${subProtocol}://${subconverter}/sub?target=singbox&url=${encodeURIComponent(url)}&insert=false&config=${encodeURIComponent(subconfig)}&emoji=true&list=false&tfo=false&scv=true&fdn=false&sort=false&new_name=true`; + url = `${subProtocol}://${subConverter}/sub?target=singbox&url=${encodeURIComponent(url)}&insert=false&config=${encodeURIComponent(subConfig)}&emoji=${subEmoji}&list=false&tfo=false&scv=true&fdn=false&sort=false&new_name=true`; isBase64 = false; } } @@ -1467,24 +1498,44 @@ async function 整理优选列表(api) { // 获取响应的内容 const content = await response.value; - // 验证当前apiUrl是否带有'proxyip=true' - if (api[index].includes('proxyip=true')) { - // 如果URL带有'proxyip=true',则将内容添加到proxyIPPool - proxyIPPool = proxyIPPool.concat((await 整理(content)).map(item => { - const baseItem = item.split('#')[0] || item; - if (baseItem.includes(':')) { - const port = baseItem.split(':')[1]; - if (!httpsPorts.includes(port)) { - return baseItem; - } - } else { - return `${baseItem}:443`; + const lines = content.split(/\r?\n/); + let 节点备注 = ''; + let 测速端口 = '443'; + + if (lines[0].split(',').length > 3){ + const idMatch = api[index].match(/id=([^&]*)/); + if (idMatch) 节点备注 = idMatch[1]; + + const portMatch = api[index].match(/port=([^&]*)/); + if (portMatch) 测速端口 = portMatch[1]; + + for (let i = 1; i < lines.length; i++) { + const columns = lines[i].split(',')[0]; + if(columns){ + newapi += `${columns}:${测速端口}${节点备注 ? `#${节点备注}` : ''}\n`; + if (api[index].includes('proxyip=true')) proxyIPPool.push(`${columns}:${测速端口}`); } - return null; // 不符合条件时返回 null - }).filter(Boolean)); // 过滤掉 null 值 + } + } else { + // 验证当前apiUrl是否带有'proxyip=true' + if (api[index].includes('proxyip=true')) { + // 如果URL带有'proxyip=true',则将内容添加到proxyIPPool + proxyIPPool = proxyIPPool.concat((await 整理(content)).map(item => { + const baseItem = item.split('#')[0] || item; + if (baseItem.includes(':')) { + const port = baseItem.split(':')[1]; + if (!httpsPorts.includes(port)) { + return baseItem; + } + } else { + return `${baseItem}:443`; + } + return null; // 不符合条件时返回 null + }).filter(Boolean)); // 过滤掉 null 值 + } + // 将内容添加到newapi中 + newapi += content + '\n'; } - // 将内容添加到newapi中 - newapi += content + '\n'; } } } catch (error) { @@ -1530,7 +1581,7 @@ async function 整理测速结果(tls) { const ipAddressIndex = 0;// IP地址在 CSV 头部的位置 const portIndex = 1;// 端口在 CSV 头部的位置 - const dataCenterIndex = tlsIndex + 1; // 数据中心是 TLS 的后一个字段 + const dataCenterIndex = tlsIndex + remarkIndex; // 数据中心是 TLS 的后一个字段 if (tlsIndex === -1) { console.error('CSV文件缺少必需的字段'); @@ -1617,7 +1668,7 @@ function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newA if (port == "-1") port = "80"; let 伪装域名 = host ; - let 最终路径 = '/?ed=2560' ; + let 最终路径 = path ; let 节点备注 = ''; const 协议类型 = atob(啥啥啥_写的这是啥啊); @@ -1674,7 +1725,7 @@ function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newA if (port == "-1") port = "443"; let 伪装域名 = host ; - let 最终路径 = '/?ed=2560' ; + let 最终路径 = path ; let 节点备注 = ''; const matchingProxyIP = proxyIPPool.find(proxyIP => proxyIP.includes(address)); if (matchingProxyIP) 最终路径 += `&proxyip=${matchingProxyIP}`;