mirror of
https://github.com/lush2020/edgetunnel.git
synced 2026-03-21 08:52:43 +08:00
添加二维码生成功能
This commit is contained in:
279
明文源码.js
279
明文源码.js
@@ -9,12 +9,12 @@ let subConfig = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/
|
||||
let subProtocol = 'https';
|
||||
let subEmoji = 'true';
|
||||
let socks5Address = '';
|
||||
let parsedSocks5Address = {};
|
||||
let parsedSocks5Address = {};
|
||||
let enableSocks = false;
|
||||
|
||||
let fakeUserID ;
|
||||
let fakeHostName ;
|
||||
let noTLS = 'false';
|
||||
let fakeUserID;
|
||||
let fakeHostName;
|
||||
let noTLS = 'false';
|
||||
const expire = 4102329600;//2099-12-31
|
||||
let proxyIPs;
|
||||
let socks5s;
|
||||
@@ -33,11 +33,11 @@ let DLS = 8;
|
||||
let remarkIndex = 1;//CSV备注所在列偏移量
|
||||
let FileName = atob('ZWRnZXR1bm5lbA==');
|
||||
let BotToken;
|
||||
let ChatID;
|
||||
let ChatID;
|
||||
let proxyhosts = [];
|
||||
let proxyhostsURL = '';
|
||||
let RproxyIP = 'false';
|
||||
let httpsPorts = ["2053","2083","2087","2096","8443"];
|
||||
let httpsPorts = ["2053", "2083", "2087", "2096", "8443"];
|
||||
let 有效时间 = 7;
|
||||
let 更新时间 = 3;
|
||||
let userIDLow;
|
||||
@@ -63,7 +63,7 @@ export default {
|
||||
}
|
||||
|
||||
if (!userID) {
|
||||
return new Response('请设置你的UUID变量,或尝试重试部署,检查变量是否生效?', {
|
||||
return new Response('请设置你的UUID变量,或尝试重试部署,检查变量是否生效?', {
|
||||
status: 404,
|
||||
headers: {
|
||||
"Content-Type": "text/plain;charset=utf-8",
|
||||
@@ -71,7 +71,7 @@ export default {
|
||||
});
|
||||
}
|
||||
const currentDate = new Date();
|
||||
currentDate.setHours(0, 0, 0, 0);
|
||||
currentDate.setHours(0, 0, 0, 0);
|
||||
const timestamp = Math.ceil(currentDate.getTime() / 1000);
|
||||
const fakeUserIDMD5 = await 双重哈希(`${userID}${timestamp}`);
|
||||
fakeUserID = [
|
||||
@@ -81,7 +81,7 @@ 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;
|
||||
@@ -121,14 +121,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 整理(env.LINK) ;
|
||||
if (env.LINK) link = await 整理(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 {
|
||||
@@ -172,12 +172,12 @@ export default {
|
||||
//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);
|
||||
const UD = Math.floor(((now - today.getTime()) / 86400000) * 24 * 1099511627776 / 2);
|
||||
let pagesSum = UD;
|
||||
let workersSum = UD;
|
||||
let total = 24 * 1099511627776 ;
|
||||
let total = 24 * 1099511627776;
|
||||
|
||||
if (userAgent && userAgent.includes('mozilla')){
|
||||
if (userAgent && userAgent.includes('mozilla')) {
|
||||
return new Response(`<div style="font-size:13px;">${维列斯Config}</div>`, {
|
||||
status: 200,
|
||||
headers: {
|
||||
@@ -208,7 +208,7 @@ export default {
|
||||
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);
|
||||
@@ -229,7 +229,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)) {
|
||||
@@ -360,7 +360,7 @@ async function 维列斯OverWSHandler(request) {
|
||||
|
||||
async function handleTCPOutBound(remoteSocket, addressType, addressRemote, portRemote, rawClientData, webSocket, 维列斯ResponseHeader, log,) {
|
||||
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');
|
||||
@@ -419,7 +419,7 @@ async function handleTCPOutBound(remoteSocket, addressType, addressRemote, portR
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -750,15 +750,15 @@ function base64ToArrayBuffer(base64Str) {
|
||||
// 这种变体使用 '-' 和 '_' 来代替标准 Base64 中的 '+' 和 '/'
|
||||
// JavaScript 的 atob 函数不直接支持这种变体,所以我们需要先转换
|
||||
base64Str = base64Str.replace(/-/g, '+').replace(/_/g, '/');
|
||||
|
||||
|
||||
// 使用 atob 函数解码 Base64 字符串
|
||||
// atob 将 Base64 编码的 ASCII 字符串转换为原始的二进制字符串
|
||||
const decode = atob(base64Str);
|
||||
|
||||
|
||||
// 将二进制字符串转换为 Uint8Array
|
||||
// 这是通过遍历字符串中的每个字符并获取其 Unicode 编码值(0-255)来完成的
|
||||
const arryBuffer = Uint8Array.from(decode, (c) => c.charCodeAt(0));
|
||||
|
||||
|
||||
// 返回 Uint8Array 的底层 ArrayBuffer
|
||||
// 这是实际的二进制数据,可以用于网络传输或其他二进制操作
|
||||
return { earlyData: arryBuffer.buffer, error: null };
|
||||
@@ -776,7 +776,7 @@ function base64ToArrayBuffer(base64Str) {
|
||||
function isValidUUID(uuid) {
|
||||
// 定义一个正则表达式来匹配 UUID 格式
|
||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
|
||||
|
||||
// 使用正则表达式测试 UUID 字符串
|
||||
return uuidRegex.test(uuid);
|
||||
}
|
||||
@@ -839,7 +839,7 @@ function stringify(arr, offset = 0) {
|
||||
// 验证生成的 UUID 是否有效
|
||||
if (!isValidUUID(uuid)) {
|
||||
// 原:throw TypeError("Stringified UUID is invalid");
|
||||
throw TypeError(`生成的 UUID 不符合规范 ${uuid}`);
|
||||
throw TypeError(`生成的 UUID 不符合规范 ${uuid}`);
|
||||
//uuid = userID;
|
||||
}
|
||||
return uuid;
|
||||
@@ -1108,14 +1108,14 @@ function socks5AddressParser(address) {
|
||||
*/
|
||||
function 恢复伪装信息(content, userID, hostName, isBase64) {
|
||||
if (isBase64) content = atob(content); // 如果内容是Base64编码的,先解码
|
||||
|
||||
|
||||
// 使用正则表达式全局替换('g'标志)
|
||||
// 将所有出现的假用户ID和假主机名替换为真实的值
|
||||
content = content.replace(new RegExp(fakeUserID, 'g'), userID)
|
||||
.replace(new RegExp(fakeHostName, 'g'), hostName);
|
||||
|
||||
.replace(new RegExp(fakeHostName, 'g'), hostName);
|
||||
|
||||
if (isBase64) content = btoa(content); // 如果原内容是Base64编码的,处理完后再次编码
|
||||
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -1137,7 +1137,7 @@ async function 双重哈希(文本) {
|
||||
const 第二次哈希 = await crypto.subtle.digest('MD5', 编码器.encode(第一次十六进制.slice(7, 27)));
|
||||
const 第二次哈希数组 = Array.from(new Uint8Array(第二次哈希));
|
||||
const 第二次十六进制 = 第二次哈希数组.map(字节 => 字节.toString(16).padStart(2, '0')).join('');
|
||||
|
||||
|
||||
return 第二次十六进制.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -1184,34 +1184,34 @@ async function 代理URL(代理网址, 目标网址) {
|
||||
const 啥啥啥_写的这是啥啊 = atob('ZG14bGMzTT0=');
|
||||
function 配置信息(UUID, 域名地址) {
|
||||
const 协议类型 = atob(啥啥啥_写的这是啥啊);
|
||||
|
||||
|
||||
const 别名 = FileName;
|
||||
let 地址 = 域名地址;
|
||||
let 端口 = 443;
|
||||
|
||||
const 用户ID = UUID;
|
||||
const 加密方式 = 'none';
|
||||
|
||||
|
||||
const 传输层协议 = 'ws';
|
||||
const 伪装域名 = 域名地址;
|
||||
const 路径 = path;
|
||||
|
||||
let 传输层安全 = ['tls',true];
|
||||
|
||||
let 传输层安全 = ['tls', true];
|
||||
const SNI = 域名地址;
|
||||
const 指纹 = 'randomized';
|
||||
|
||||
if (域名地址.includes('.workers.dev')){
|
||||
if (域名地址.includes('.workers.dev')) {
|
||||
地址 = atob('dmlzYS5jbg==');
|
||||
端口 = 80 ;
|
||||
传输层安全 = ['',false];
|
||||
端口 = 80;
|
||||
传输层安全 = ['', false];
|
||||
}
|
||||
|
||||
const 威图瑞 = `${协议类型}://${用户ID}@${地址}:${端口}\u003f\u0065\u006e\u0063\u0072\u0079`+'p'+`${atob('dGlvbj0=') + 加密方式}\u0026\u0073\u0065\u0063\u0075\u0072\u0069\u0074\u0079\u003d${传输层安全[0]}&sni=${SNI}&fp=${指纹}&type=${传输层协议}&host=${伪装域名}&path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`;
|
||||
const 威图瑞 = `${协议类型}://${用户ID}@${地址}:${端口}\u003f\u0065\u006e\u0063\u0072\u0079` + 'p' + `${atob('dGlvbj0=') + 加密方式}\u0026\u0073\u0065\u0063\u0075\u0072\u0069\u0074\u0079\u003d${传输层安全[0]}&sni=${SNI}&fp=${指纹}&type=${传输层协议}&host=${伪装域名}&path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`;
|
||||
const 猫猫猫 = `- {name: ${FileName}, server: ${地址}, port: ${端口}, type: ${协议类型}, uuid: ${用户ID}, tls: ${传输层安全[1]}, alpn: [h3], udp: false, sni: ${SNI}, tfo: false, skip-cert-verify: true, servername: ${伪装域名}, client-fingerprint: ${指纹}, network: ${传输层协议}, ws-opts: {path: "${路径}", headers: {${伪装域名}}}}`;
|
||||
return [威图瑞,猫猫猫];
|
||||
return [威图瑞, 猫猫猫];
|
||||
}
|
||||
|
||||
let subParams = ['sub','base64','b64','clash','singbox','sb'];
|
||||
let subParams = ['sub', 'base64', 'b64', 'clash', 'singbox', 'sb'];
|
||||
const cmad = decodeURIComponent(atob('dGVsZWdyYW0lMjAlRTQlQkElQTQlRTYlQjUlODElRTclQkUlQTQlMjAlRTYlOEElODAlRTYlOUMlQUYlRTUlQTQlQTclRTQlQkQlQUMlN0UlRTUlOUMlQTglRTclQkElQkYlRTUlOEYlOTElRTclODklOEMhJTNDYnIlM0UKJTNDYSUyMGhyZWYlM0QlMjdodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlMjclM0VodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlM0MlMkZhJTNFJTNDYnIlM0UKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJTNDYnIlM0UKZ2l0aHViJTIwJUU5JUExJUI5JUU3JTlCJUFFJUU1JTlDJUIwJUU1JTlEJTgwJTIwU3RhciFTdGFyIVN0YXIhISElM0NiciUzRQolM0NhJTIwaHJlZiUzRCUyN2h0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUyNyUzRWh0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUzQyUyRmElM0UlM0NiciUzRQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0lM0NiciUzRQolMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjM='));
|
||||
/**
|
||||
* @param {string} userID
|
||||
@@ -1229,7 +1229,7 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
const subs = await 整理(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 (优选地址列表) {
|
||||
@@ -1239,7 +1239,7 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
链接地址: new Set(),
|
||||
优选地址: new Set()
|
||||
};
|
||||
|
||||
|
||||
for (const 元素 of 优选地址数组) {
|
||||
if (元素.startsWith('https://')) {
|
||||
分类地址.接口地址.add(元素);
|
||||
@@ -1249,14 +1249,14 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
分类地址.优选地址.add(元素);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addressesapi = [...分类地址.接口地址];
|
||||
link = [...分类地址.链接地址];
|
||||
addresses = [...分类地址.优选地址];
|
||||
}
|
||||
}
|
||||
|
||||
if ((addresses.length + addressesapi.length + addressesnotls.length + addressesnotlsapi.length + addressescsv.length) == 0){
|
||||
|
||||
if ((addresses.length + addressesapi.length + addressesnotls.length + addressesnotlsapi.length + addressescsv.length) == 0) {
|
||||
// 定义 Cloudflare IP 范围的 CIDR 列表
|
||||
let cfips = [
|
||||
'103.21.244.0/23',
|
||||
@@ -1271,7 +1271,7 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
'188.114.96.0/21',
|
||||
'190.93.240.0/21',
|
||||
];
|
||||
|
||||
|
||||
// 生成符合给定 CIDR 范围的随机 IP 地址
|
||||
function generateRandomIPFromCIDR(cidr) {
|
||||
const [base, mask] = cidr.split('/');
|
||||
@@ -1279,13 +1279,13 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
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');
|
||||
@@ -1299,30 +1299,30 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
|
||||
const uuid = (_url.pathname == `/${动态UUID}`) ? 动态UUID : userID;
|
||||
const userAgent = UA.toLowerCase();
|
||||
const Config = 配置信息(userID , hostName);
|
||||
const Config = 配置信息(userID, 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)] + "/";
|
||||
}
|
||||
|
||||
@@ -1334,9 +1334,9 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
});
|
||||
|
||||
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')}<br>`;
|
||||
if (go2Socks5s.includes(atob('YWxsIGlu')) || go2Socks5s.includes(atob('Kg=='))) socks5List += `${decodeURIComponent('%E6%89%80%E6%9C%89%E6%B5%81%E9%87%8F')}<br>`;
|
||||
else socks5List += `<br> ${go2Socks5s.join('<br> ')}<br>`;
|
||||
}
|
||||
|
||||
@@ -1366,23 +1366,20 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
const 动态UUID信息 = (uuid != userID) ? `TOKEN: ${uuid}<br>UUIDNow: ${userID}<br>UUIDLow: ${userIDLow}<br>${userIDTime}TIME(动态UUID有效时间): ${有效时间} 天<br>UPTIME(动态UUID更新时间): ${更新时间} 时(北京时间)<br><br>` : `${userIDTime}`;
|
||||
const 节点配置页 = `
|
||||
################################################################<br>
|
||||
Subscribe / sub 订阅地址, 支持 Base64、clash-meta、sing-box 订阅格式<br>
|
||||
Subscribe / sub 订阅地址, 点击链接自动 <strong>复制订阅链接</strong> 并 <strong>生成订阅二维码</strong> <br>
|
||||
---------------------------------------------------------------<br>
|
||||
自适应订阅地址:<br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}</a><br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?sub')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}?sub</a><br>
|
||||
<br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?sub','qrcode_0')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}</a><br>
|
||||
<div id="qrcode_0" style="margin: 10px 10px 10px 10px;"></div>
|
||||
Base64订阅地址:<br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?b64')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}?b64</a><br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?base64')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}?base64</a><br>
|
||||
<br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?b64','qrcode_1')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}?b64</a><br>
|
||||
<div id="qrcode_1" style="margin: 10px 10px 10px 10px;"></div>
|
||||
clash订阅地址:<br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?clash')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}?clash</a><br>
|
||||
<br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?clash','qrcode_2')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}?clash</a><br>
|
||||
<div id="qrcode_2" style="margin: 10px 10px 10px 10px;"></div>
|
||||
singbox订阅地址:<br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?sb')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}?sb</a><br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?singbox')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}?singbox</a><br>
|
||||
<br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('https://${proxyhost}${hostName}/${uuid}?sb','qrcode_3')" style="color:blue;text-decoration:underline;cursor:pointer;">https://${proxyhost}${hostName}/${uuid}?sb</a><br>
|
||||
<div id="qrcode_3" style="margin: 10px 10px 10px 10px;"></div>
|
||||
<strong><a href="javascript:void(0);" id="noticeToggle" onclick="toggleNotice()">实用订阅技巧∨</a></strong><br>
|
||||
<div id="noticeContent" class="notice-content" style="display: none;">
|
||||
<strong>1.</strong> 如您使用的是 PassWall、SSR+ 等路由插件,推荐使用 <strong>Base64订阅地址</strong> 进行订阅;<br>
|
||||
@@ -1399,13 +1396,25 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
<strong>5.</strong> 如需指定多个参数则需要使用'&'做间隔,例如:<br>
|
||||
https://${proxyhost}${hostName}/${uuid}?sub=sub.google.com<strong>&</strong>proxyip=proxyip.fxxk.dedyn.io<br>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@keeex/qrcodejs-kx@1.0.2/qrcode.min.js"></script>
|
||||
<script>
|
||||
function copyToClipboard(text) {
|
||||
function copyToClipboard(text, qrcode) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
alert('已复制到剪贴板');
|
||||
}).catch(err => {
|
||||
console.error('复制失败:', err);
|
||||
});
|
||||
const qrcodeDiv = document.getElementById(qrcode);
|
||||
qrcodeDiv.innerHTML = '';
|
||||
new QRCode(qrcodeDiv, {
|
||||
text: text,
|
||||
width: 220, // 调整宽度
|
||||
height: 220, // 调整高度
|
||||
colorDark: "#000000", // 二维码颜色
|
||||
colorLight: "#ffffff", // 背景颜色
|
||||
correctLevel: QRCode.CorrectLevel.Q, // 设置纠错级别
|
||||
scale: 1 // 调整像素颗粒度
|
||||
});
|
||||
}
|
||||
|
||||
function toggleNotice() {
|
||||
@@ -1433,7 +1442,8 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
################################################################<br>
|
||||
v2ray<br>
|
||||
---------------------------------------------------------------<br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('${v2ray}')" style="color:blue;text-decoration:underline;cursor:pointer;">${v2ray}</a><br>
|
||||
<a href="javascript:void(0)" onclick="copyToClipboard('${v2ray}','qrcode_v2ray')" style="color:blue;text-decoration:underline;cursor:pointer;">${v2ray}</a><br>
|
||||
<div id="qrcode_v2ray" style="margin: 10px 10px 10px 10px;"></div>
|
||||
---------------------------------------------------------------<br>
|
||||
################################################################<br>
|
||||
clash-meta<br>
|
||||
@@ -1455,14 +1465,14 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
let newAddressesnotlscsv = [];
|
||||
|
||||
// 如果是使用默认域名,则改成一个workers的域名,订阅器会加上代理
|
||||
if (hostName.includes(".workers.dev")){
|
||||
if (hostName.includes(".workers.dev")) {
|
||||
noTLS = 'true';
|
||||
fakeHostName = `${fakeHostName}.workers.dev`;
|
||||
newAddressesnotlsapi = await 整理优选列表(addressesnotlsapi);
|
||||
newAddressesnotlscsv = await 整理测速结果('FALSE');
|
||||
} else if (hostName.includes(".pages.dev")){
|
||||
} else if (hostName.includes(".pages.dev")) {
|
||||
fakeHostName = `${fakeHostName}.pages.dev`;
|
||||
} else if (hostName.includes("worker") || hostName.includes("notls") || noTLS == 'true'){
|
||||
} else if (hostName.includes("worker") || hostName.includes("notls") || noTLS == 'true') {
|
||||
noTLS = 'true';
|
||||
fakeHostName = `notls${fakeHostName}.net`;
|
||||
newAddressesnotlsapi = await 整理优选列表(addressesnotlsapi);
|
||||
@@ -1474,22 +1484,22 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
let url = `${subProtocol}://${sub}/sub?host=${fakeHostName}&uuid=${fakeUserID + atob('JmVkZ2V0dW5uZWw9Y21saXUmcHJveHlpcD0=') + RproxyIP}&path=${encodeURIComponent(path)}`;
|
||||
let isBase64 = true;
|
||||
|
||||
if (!sub || sub == ""){
|
||||
if(hostName.includes('workers.dev')) {
|
||||
if (!sub || sub == "") {
|
||||
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);
|
||||
@@ -1498,7 +1508,7 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
// 使用Set对象去重
|
||||
proxyhosts = [...new Set(proxyhosts)];
|
||||
}
|
||||
|
||||
|
||||
newAddressesapi = await 整理优选列表(addressesapi);
|
||||
newAddressescsv = await 整理测速结果('TRUE');
|
||||
url = `https://${hostName}/${fakeUserID + _url.search}`;
|
||||
@@ -1507,27 +1517,28 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
|
||||
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'))) {
|
||||
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=${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'))) {
|
||||
} 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=${subEmoji}&list=false&tfo=false&scv=true&fdn=false&sort=false&new_name=true`;
|
||||
isBase64 = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
let content;
|
||||
if ((!sub || sub == "") && isBase64 == true) {
|
||||
content = await 生成本地订阅(fakeHostName,fakeUserID,noTLS,newAddressesapi,newAddressescsv,newAddressesnotlsapi,newAddressesnotlscsv);
|
||||
content = await 生成本地订阅(fakeHostName, fakeUserID, noTLS, newAddressesapi, newAddressescsv, newAddressesnotlsapi, newAddressesnotlscsv);
|
||||
} else {
|
||||
const response = await fetch(url ,{
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
'User-Agent': UA + atob('IENGLVdvcmtlcnMtZWRnZXR1bm5lbC9jbWxpdQ==')
|
||||
}});
|
||||
}
|
||||
});
|
||||
content = await response.text();
|
||||
}
|
||||
|
||||
@@ -1558,7 +1569,7 @@ async function 整理优选列表(api) {
|
||||
// 使用Promise.allSettled等待所有API请求完成,无论成功或失败
|
||||
// 对api数组进行遍历,对每个API地址发起fetch请求
|
||||
const responses = await Promise.allSettled(api.map(apiUrl => fetch(apiUrl, {
|
||||
method: 'get',
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;',
|
||||
'User-Agent': atob('Q0YtV29ya2Vycy1lZGdldHVubmVsL2NtbGl1')
|
||||
@@ -1577,16 +1588,16 @@ async function 整理优选列表(api) {
|
||||
let 节点备注 = '';
|
||||
let 测速端口 = '443';
|
||||
|
||||
if (lines[0].split(',').length > 3){
|
||||
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){
|
||||
if (columns) {
|
||||
newapi += `${columns}:${测速端口}${节点备注 ? `#${节点备注}` : ''}\n`;
|
||||
if (api[index].includes('proxyip=true')) proxyIPPool.push(`${columns}:${测速端口}`);
|
||||
}
|
||||
@@ -1630,39 +1641,39 @@ async function 整理测速结果(tls) {
|
||||
if (!addressescsv || addressescsv.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
let newAddressescsv = [];
|
||||
|
||||
|
||||
for (const csvUrl of addressescsv) {
|
||||
try {
|
||||
const response = await fetch(csvUrl);
|
||||
|
||||
|
||||
if (!response.ok) {
|
||||
console.error('获取CSV地址时出错:', response.status, response.statusText);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const text = await response.text();// 使用正确的字符编码解析文本内容
|
||||
let lines;
|
||||
if (text.includes('\r\n')){
|
||||
if (text.includes('\r\n')) {
|
||||
lines = text.split('\r\n');
|
||||
} else {
|
||||
lines = text.split('\n');
|
||||
}
|
||||
|
||||
|
||||
// 检查CSV头部是否包含必需字段
|
||||
const header = lines[0].split(',');
|
||||
const tlsIndex = header.indexOf('TLS');
|
||||
|
||||
|
||||
const ipAddressIndex = 0;// IP地址在 CSV 头部的位置
|
||||
const portIndex = 1;// 端口在 CSV 头部的位置
|
||||
const dataCenterIndex = tlsIndex + remarkIndex; // 数据中心是 TLS 的后一个字段
|
||||
|
||||
|
||||
if (tlsIndex === -1) {
|
||||
console.error('CSV文件缺少必需的字段');
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// 从第二行开始遍历CSV行
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
const columns = lines[i].split(',');
|
||||
@@ -1672,7 +1683,7 @@ async function 整理测速结果(tls) {
|
||||
const ipAddress = columns[ipAddressIndex];
|
||||
const port = columns[portIndex];
|
||||
const dataCenter = columns[dataCenterIndex];
|
||||
|
||||
|
||||
const formattedAddress = `${ipAddress}:${port}#${dataCenter}`;
|
||||
newAddressescsv.push(formattedAddress);
|
||||
if (csvUrl.includes('proxyip=true') && columns[tlsIndex].toUpperCase() == 'true' && !httpsPorts.includes(port)) {
|
||||
@@ -1686,16 +1697,16 @@ async function 整理测速结果(tls) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return newAddressescsv;
|
||||
}
|
||||
|
||||
function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newAddressesnotlsapi,newAddressesnotlscsv) {
|
||||
function 生成本地订阅(host, UUID, noTLS, newAddressesapi, newAddressescsv, newAddressesnotlsapi, newAddressesnotlscsv) {
|
||||
const regex = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[.*\]):?(\d+)?#?(.*)?$/;
|
||||
addresses = addresses.concat(newAddressesapi);
|
||||
addresses = addresses.concat(newAddressescsv);
|
||||
let notlsresponseBody ;
|
||||
if (noTLS == 'true'){
|
||||
let notlsresponseBody;
|
||||
if (noTLS == 'true') {
|
||||
addressesnotls = addressesnotls.concat(newAddressesnotlsapi);
|
||||
addressesnotls = addressesnotls.concat(newAddressesnotlscsv);
|
||||
const uniqueAddressesnotls = [...new Set(addressesnotls)];
|
||||
@@ -1703,7 +1714,7 @@ function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newA
|
||||
notlsresponseBody = uniqueAddressesnotls.map(address => {
|
||||
let port = "-1";
|
||||
let addressid = address;
|
||||
|
||||
|
||||
const match = addressid.match(regex);
|
||||
if (!match) {
|
||||
if (address.includes(':') && address.includes('#')) {
|
||||
@@ -1721,7 +1732,7 @@ function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newA
|
||||
address = parts[0];
|
||||
addressid = parts[1];
|
||||
}
|
||||
|
||||
|
||||
if (addressid.includes(':')) {
|
||||
addressid = addressid.split(':')[0];
|
||||
}
|
||||
@@ -1731,7 +1742,7 @@ function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newA
|
||||
addressid = match[3] || address;
|
||||
}
|
||||
|
||||
const httpPorts = ["8080","8880","2052","2082","2086","2095"];
|
||||
const httpPorts = ["8080", "8880", "2052", "2082", "2086", "2095"];
|
||||
if (!isValidIPv4(address) && port == "-1") {
|
||||
for (let httpPort of httpPorts) {
|
||||
if (address.includes(httpPort)) {
|
||||
@@ -1741,14 +1752,14 @@ function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newA
|
||||
}
|
||||
}
|
||||
if (port == "-1") port = "80";
|
||||
|
||||
let 伪装域名 = host ;
|
||||
let 最终路径 = path ;
|
||||
|
||||
let 伪装域名 = host;
|
||||
let 最终路径 = path;
|
||||
let 节点备注 = '';
|
||||
const 协议类型 = atob(啥啥啥_写的这是啥啊);
|
||||
|
||||
|
||||
const 维列斯Link = `${协议类型}://${UUID}@${address}:${port + atob('P2VuY3J5cHRpb249bm9uZSZzZWN1cml0eT0mdHlwZT13cyZob3N0PQ==') + 伪装域名}&path=${encodeURIComponent(最终路径)}#${encodeURIComponent(addressid + 节点备注)}`;
|
||||
|
||||
|
||||
return 维列斯Link;
|
||||
|
||||
}).join('\n');
|
||||
@@ -1779,7 +1790,7 @@ function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newA
|
||||
address = parts[0];
|
||||
addressid = parts[1];
|
||||
}
|
||||
|
||||
|
||||
if (addressid.includes(':')) {
|
||||
addressid = addressid.split(':')[0];
|
||||
}
|
||||
@@ -1798,27 +1809,27 @@ function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newA
|
||||
}
|
||||
}
|
||||
if (port == "-1") port = "443";
|
||||
|
||||
let 伪装域名 = host ;
|
||||
let 最终路径 = path ;
|
||||
|
||||
let 伪装域名 = host;
|
||||
let 最终路径 = path;
|
||||
let 节点备注 = '';
|
||||
const matchingProxyIP = proxyIPPool.find(proxyIP => proxyIP.includes(address));
|
||||
if (matchingProxyIP) 最终路径 += `&proxyip=${matchingProxyIP}`;
|
||||
|
||||
if(proxyhosts.length > 0 && (伪装域名.includes('.workers.dev'))) {
|
||||
|
||||
if (proxyhosts.length > 0 && (伪装域名.includes('.workers.dev'))) {
|
||||
最终路径 = `/${伪装域名}${最终路径}`;
|
||||
伪装域名 = proxyhosts[Math.floor(Math.random() * proxyhosts.length)];
|
||||
节点备注 = ` 已启用临时域名中转服务,请尽快绑定自定义域!`;
|
||||
}
|
||||
|
||||
|
||||
const 协议类型 = atob(啥啥啥_写的这是啥啊);
|
||||
const 维列斯Link = `${协议类型}://${UUID}@${address}:${port + atob('P2VuY3J5cHRpb249bm9uZSZzZWN1cml0eT10bHMmc25pPQ==') + 伪装域名}&fp=random&type=ws&host=${伪装域名}&path=${encodeURIComponent(最终路径)}#${encodeURIComponent(addressid + 节点备注)}`;
|
||||
|
||||
|
||||
return 维列斯Link;
|
||||
}).join('\n');
|
||||
|
||||
let base64Response = responseBody; // 重新进行 Base64 编码
|
||||
if(noTLS == 'true') base64Response += `\n${notlsresponseBody}`;
|
||||
if (noTLS == 'true') base64Response += `\n${notlsresponseBody}`;
|
||||
if (link.length > 0) base64Response += '\n' + link.join('\n');
|
||||
return btoa(base64Response);
|
||||
}
|
||||
@@ -1827,14 +1838,14 @@ async function 整理(内容) {
|
||||
// 将制表符、双引号、单引号和换行符都替换为逗号
|
||||
// 然后将连续的多个逗号替换为单个逗号
|
||||
var 替换后的内容 = 内容.replace(/[ |"'\r\n]+/g, ',').replace(/,+/g, ',');
|
||||
|
||||
|
||||
// 删除开头和结尾的逗号(如果有的话)
|
||||
if (替换后的内容.charAt(0) == ',') 替换后的内容 = 替换后的内容.slice(1);
|
||||
if (替换后的内容.charAt(替换后的内容.length - 1) == ',') 替换后的内容 = 替换后的内容.slice(0, 替换后的内容.length - 1);
|
||||
|
||||
|
||||
// 使用逗号分割字符串,得到地址数组
|
||||
const 地址数组 = 替换后的内容.split(',');
|
||||
|
||||
|
||||
return 地址数组;
|
||||
}
|
||||
|
||||
@@ -1908,7 +1919,7 @@ function 生成动态UUID(密钥) {
|
||||
async function 迁移地址列表(env, txt = 'ADD.txt') {
|
||||
const 旧数据 = await env.KV.get(`/${txt}`);
|
||||
const 新数据 = await env.KV.get(txt);
|
||||
|
||||
|
||||
if (旧数据 && !新数据) {
|
||||
// 写入新位置
|
||||
await env.KV.put(txt, 旧数据);
|
||||
@@ -1933,11 +1944,11 @@ async function KV(request, env, txt = 'ADD.txt') {
|
||||
return new Response("保存失败: " + error.message, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GET请求部分
|
||||
let content = '';
|
||||
let hasKV = !!env.KV;
|
||||
|
||||
|
||||
if (hasKV) {
|
||||
try {
|
||||
content = await env.KV.get(txt) || '';
|
||||
@@ -1946,7 +1957,7 @@ async function KV(request, env, txt = 'ADD.txt') {
|
||||
content = '读取数据时发生错误: ' + error.message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const html = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -2021,7 +2032,7 @@ async function KV(request, env, txt = 'ADD.txt') {
|
||||
---------------------------------------------------------------<br>
|
||||
<strong><a href="javascript:void(0);" id="noticeToggle" onclick="toggleNotice()">注意事项∨</a></strong><br>
|
||||
<div id="noticeContent" class="notice-content">
|
||||
${decodeURIComponent(atob('JTA5JTA5JTA5JTA5JTA5JTNDc3Ryb25nJTNFMS4lM0MlMkZzdHJvbmclM0UlMjBBRERBUEklMjAlRTUlQTYlODIlRTYlOUUlOUMlRTYlOTglQUYlRTUlOEYlOEQlRTQlQkIlQTNJUCVFRiVCQyU4QyVFNSU4RiVBRiVFNCVCRCU5QyVFNCVCOCVCQVBST1hZSVAlRTclOUElODQlRTglQUYlOUQlRUYlQkMlOEMlRTUlOEYlQUYlRTUlQjAlODYlMjIlM0Zwcm94eWlwJTNEdHJ1ZSUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGYWRkcmVzc2VzYXBpLnR4dCUzQ3N0cm9uZyUzRSUzRnByb3h5aXAlM0R0cnVlJTNDJTJGc3Ryb25nJTNFJTNDYnIlM0UlM0NiciUzRQolMDklMDklMDklMDklMDklM0NzdHJvbmclM0UyLiUzQyUyRnN0cm9uZyUzRSUyMEFEREFQSSUyMCVFNSVBNiU4MiVFNiU5RSU5QyVFNiU5OCVBRiUyMCUzQ2ElMjBocmVmJTNEJTI3aHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGWElVMiUyRkNsb3VkZmxhcmVTcGVlZFRlc3QlMjclM0VDbG91ZGZsYXJlU3BlZWRUZXN0JTNDJTJGYSUzRSUyMCVFNyU5QSU4NCUyMGNzdiUyMCVFNyVCQiU5MyVFNiU5RSU5QyVFNiU5NiU4NyVFNCVCQiVCNiVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZyZWZzJTJGaGVhZHMlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NiciUzRSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCLSUyMCVFNSVBNiU4MiVFOSU5QyU4MCVFNiU4QyU4NyVFNSVBRSU5QTIwNTMlRTclQUIlQUYlRTUlOEYlQTMlRTUlOEYlQUYlRTUlQjAlODYlMjIlM0Zwb3J0JTNEMjA1MyUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZyZWZzJTJGaGVhZHMlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NzdHJvbmclM0UlM0Zwb3J0JTNEMjA1MyUzQyUyRnN0cm9uZyUzRSUzQ2JyJTNFJTNDYnIlM0UKJTA5JTA5JTA5JTA5JTA5JTI2bmJzcCUzQiUyNm5ic3AlM0ItJTIwJUU1JUE2JTgyJUU5JTlDJTgwJUU2JThDJTg3JUU1JUFFJTlBJUU4JThBJTgyJUU3JTgyJUI5JUU1JUE0JTg3JUU2JUIzJUE4JUU1JThGJUFGJUU1JUIwJTg2JTIyJTNGaWQlM0RDRiVFNCVCQyU5OCVFOSU4MCU4OSUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZyZWZzJTJGaGVhZHMlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NzdHJvbmclM0UlM0ZpZCUzRENGJUU0JUJDJTk4JUU5JTgwJTg5JTNDJTJGc3Ryb25nJTNFJTNDYnIlM0UlM0NiciUzRQolMDklMDklMDklMDklMDklMjZuYnNwJTNCJTI2bmJzcCUzQi0lMjAlRTUlQTYlODIlRTklOUMlODAlRTYlOEMlODclRTUlQUUlOUElRTUlQTQlOUElRTQlQjglQUElRTUlOEYlODIlRTYlOTUlQjAlRTUlODglOTklRTklOUMlODAlRTglQTYlODElRTQlQkQlQkYlRTclOTQlQTglMjclMjYlMjclRTUlODElOUElRTklOTclQjQlRTklOUElOTQlRUYlQkMlOEMlRTQlQkUlOEIlRTUlQTYlODIlRUYlQkMlOUElM0NiciUzRQolMDklMDklMDklMDklMDklMjZuYnNwJTNCJTI2bmJzcCUzQmh0dHBzJTNBJTJGJTJGcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSUyRmNtbGl1JTJGV29ya2VyVmxlc3Myc3ViJTJGcmVmcyUyRmhlYWRzJTJGbWFpbiUyRkNsb3VkZmxhcmVTcGVlZFRlc3QuY3N2JTNGaWQlM0RDRiVFNCVCQyU5OCVFOSU4MCU4OSUzQ3N0cm9uZyUzRSUyNiUzQyUyRnN0cm9uZyUzRXBvcnQlM0QyMDUzJTNDYnIlM0U='))}
|
||||
${decodeURIComponent(atob('JTA5JTA5JTA5JTA5JTA5JTNDc3Ryb25nJTNFMS4lM0MlMkZzdHJvbmclM0UlMjBBRERBUEklMjAlRTUlQTYlODIlRTYlOUUlOUMlRTYlOTglQUYlRTUlOEYlOEQlRTQlQkIlQTNJUCVFRiVCQyU4QyVFNSU4RiVBRiVFNCVCRCU5QyVFNCVCOCVCQVBST1hZSVAlRTclOUElODQlRTglQUYlOUQlRUYlQkMlOEMlRTUlOEYlQUYlRTUlQjAlODYlMjIlM0Zwcm94eWlwJTNEdHJ1ZSUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGYWRkcmVzc2VzYXBpLnR4dCUzQ3N0cm9uZyUzRSUzRnByb3h5aXAlM0R0cnVlJTNDJTJGc3Ryb25nJTNFJTNDYnIlM0UlM0NiciUzRQolMDklMDklMDklMDklMDklM0NzdHJvbmclM0UyLiUzQyUyRnN0cm9uZyUzRSUyMEFEREFQSSUyMCVFNSVBNiU4MiVFNiU5RSU5QyVFNiU5OCVBRiUyMCUzQ2ElMjBocmVmJTNEJTI3aHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGWElVMiUyRkNsb3VkZmxhcmVTcGVlZFRlc3QlMjclM0VDbG91ZGZsYXJlU3BlZWRUZXN0JTNDJTJGYSUzRSUyMCVFNyU5QSU4NCUyMGNzdiUyMCVFNyVCQiU5MyVFNiU5RSU5QyVFNiU5NiU4NyVFNCVCQiVCNiVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NiciUzRSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCLSUyMCVFNSVBNiU4MiVFOSU5QyU4MCVFNiU4QyU4NyVFNSVBRSU5QTIwNTMlRTclQUIlQUYlRTUlOEYlQTMlRTUlOEYlQUYlRTUlQjAlODYlMjIlM0Zwb3J0JTNEMjA1MyUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NzdHJvbmclM0UlM0Zwb3J0JTNEMjA1MyUzQyUyRnN0cm9uZyUzRSUzQ2JyJTNFJTNDYnIlM0UKJTA5JTA5JTA5JTA5JTA5JTI2bmJzcCUzQiUyNm5ic3AlM0ItJTIwJUU1JUE2JTgyJUU5JTlDJTgwJUU2JThDJTg3JUU1JUFFJTlBJUU4JThBJTgyJUU3JTgyJUI5JUU1JUE0JTg3JUU2JUIzJUE4JUU1JThGJUFGJUU1JUIwJTg2JTIyJTNGaWQlM0RDRiVFNCVCQyU5OCVFOSU4MCU4OSUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NzdHJvbmclM0UlM0ZpZCUzRENGJUU0JUJDJTk4JUU5JTgwJTg5JTNDJTJGc3Ryb25nJTNFJTNDYnIlM0UlM0NiciUzRQolMDklMDklMDklMDklMDklMjZuYnNwJTNCJTI2bmJzcCUzQi0lMjAlRTUlQTYlODIlRTklOUMlODAlRTYlOEMlODclRTUlQUUlOUElRTUlQTQlOUElRTQlQjglQUElRTUlOEYlODIlRTYlOTUlQjAlRTUlODglOTklRTklOUMlODAlRTglQTYlODElRTQlQkQlQkYlRTclOTQlQTglMjclMjYlMjclRTUlODElOUElRTklOTclQjQlRTklOUElOTQlRUYlQkMlOEMlRTQlQkUlOEIlRTUlQTYlODIlRUYlQkMlOUElM0NiciUzRQolMDklMDklMDklMDklMDklMjZuYnNwJTNCJTI2bmJzcCUzQmh0dHBzJTNBJTJGJTJGcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSUyRmNtbGl1JTJGV29ya2VyVmxlc3Myc3ViJTJGbWFpbiUyRkNsb3VkZmxhcmVTcGVlZFRlc3QuY3N2JTNGaWQlM0RDRiVFNCVCQyU5OCVFOSU4MCU4OSUzQ3N0cm9uZyUzRSUyNiUzQyUyRnN0cm9uZyUzRXBvcnQlM0QyMDUzJTNDYnIlM0U='))}
|
||||
</div>
|
||||
<div class="editor-container">
|
||||
${hasKV ? `
|
||||
@@ -2170,13 +2181,13 @@ async function KV(request, env, txt = 'ADD.txt') {
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
|
||||
return new Response(html, {
|
||||
headers: { "Content-Type": "text/html;charset=utf-8" }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('处理请求时发生错误:', error);
|
||||
return new Response("服务器错误: " + error.message, {
|
||||
return new Response("服务器错误: " + error.message, {
|
||||
status: 500,
|
||||
headers: { "Content-Type": "text/plain;charset=utf-8" }
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user