// 本代码源自yonggekkk
// version base on commit 43fad05dcdae3b723c53c226f8181fc5bd47223e, time is 2023-06-22 15:20:02 UTC.
// @ts-ignore
// 导入 Cloudflare Sockets API,用于建立出站 TCP 连接。
import { connect } from "cloudflare:sockets";

// 如何生成你自己的 UUID:
// [Windows] 按 "Win + R",输入 cmd 并运行: Powershell -NoExit -Command "[guid]::NewGuid()"
// 默认的用户 UUID,用于 VLESS 协议的身份验证。可以被环境变量覆盖。
let userID = "86c50e3a-5b87-49dd-bd20-03c7f2735e40";

// 备选的反向代理 IP 地址列表。
const proxyIPs = ["ts.hpc.tw"];
// 一个用于判断是否为中国大陆访问的空主机名列表(此处逻辑似乎未完整实现)。
const cn_hostnames = [''];
// 默认的 CDN IP 地址,用于生成 VLESS 配置。注意这里使用了 Unicode 转义字符来混淆字符串。
// 解码后为 'www.visa.com.sg'
let CDNIP = '\u0077\u0077\u0077\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d\u002e\u0073\u0067'

// 预设的一系列用于生成节点配置的 IP 或域名,分为 HTTP 和 HTTPS 两组。
// 同样使用 Unicode 转义字符进行混淆。
// http_ip (用于 HTTP 端口的地址)
let IP1 = '\u0077\u0077\u0077\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d' // www.visa.com
let IP2 = '\u0063\u0069\u0073\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d' // cis.visa.com
let IP3 = '\u0061\u0066\u0072\u0069\u0063\u0061\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d' // africa.visa.com
let IP4 = '\u0077\u0077\u0077\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d\u002e\u0073\u0067' // www.visa.com.sg
let IP5 = '\u0077\u0077\u0077\u002e\u0076\u0069\u0073\u0061\u0065\u0075\u0072\u006f\u0070\u0065\u002e\u0061\u0074' // www.visaeurope.at
let IP6 = '\u0077\u0077\u0077\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d\u002e\u006d\u0074' // www.visa.com.mt
let IP7 = '\u0071\u0061\u002e\u0076\u0069\u0073\u0061\u006d\u0069\u0064\u0064\u006c\u0065\u0065\u0061\u0073\u0074\u002e\u0063\u006f\u006d' // qa.visamiddleeast.com

// https_ip (用于 HTTPS/TLS 端口的地址)
let IP8 = '\u0075\u0073\u0061\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d' // usa.visa.com
let IP9 = '\u006d\u0079\u0061\u006e\u006d\u0061\u0072\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d' // myanmar.visa.com
let IP10 = '\u0077\u0077\u0077\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d\u002e\u0074\u0077' // www.visa.com.tw
let IP11 = '\u0077\u0077\u0077\u002e\u0076\u0069\u0073\u0061\u0065\u0075\u0072\u006f\u0070\u0065\u002e\u0063\u0068' // www.visaeurope.ch
let IP12 = '\u0077\u0077\u0077\u002e\u0076\u0069\u0073\u0061\u002e\u0063\u006f\u006d\u002e\u0062\u0072' // www.visa.com.br
let IP13 = '\u0077\u0077\u0077\u002e\u0076\u0069\u0073\u0061\u0073\u006f\u0075\u0074\u0068\u0065\u0061\u0073\u0074\u0065\u0075\u0072\u006f\u0070\u0065\u002e\u0063\u006f\u006d' // www.visasoutheasteurope.com

// 预设的 HTTP 端口
let PT1 = '80'
let PT2 = '8080'
let PT3 = '8880'
let PT4 = '2052'
let PT5 = '2082'
let PT6 = '2086'
let PT7 = '2095'

// 预设的 HTTPS/TLS 端口
let PT8 = '443'
let PT9 = '8443'
let PT10 = '2053'
let PT11 = '2083'
let PT12 = '2087'
let PT13 = '2096'

// 从 proxyIPs 列表中随机选择一个作为代理 IP。
let proxyIP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)];
// 从选定的 proxyIP 中提取端口,如果不存在则默认为 '443'。
let proxyPort = proxyIP.match(/:(\d+)$/) ? proxyIP.match(/:(\d+)$/)[1] : '443';
// DNS-over-HTTPS (DoH) 服务器地址,用于代理 UDP DNS 查询。
const dohURL = "https://cloudflare-dns.com/dns-query";
// 检查初始的 userID 是否为有效的 UUID 格式。
if (!isValidUUID(userID)) {
  throw new Error("uuid is not valid");
}

// 导出 Worker 的主处理对象。
export default {
  /**
   * Worker 的 fetch 事件处理器,处理所有进入的 HTTP 请求。
   * @param {Request} request - 入站的请求对象。
   * @param {object} env - Cloudflare 的环境变量。
   * @param {any} ctx - 执行上下文。
   * @returns {Promise<Response>} - 返回一个响应对象。
   */
  async fetch(request, env, ctx) {
    try {
      // 尝试从环境变量中获取 `proxyip`。
      const { proxyip } = env;
      // 优先使用环境变量中的 `uuid`,否则使用代码中预设的 `userID`。
      userID = env.uuid || userID;
			// 如果环境变量中设置了 `proxyip`。
			if (proxyip) {
				// 处理 IPv6 地址和端口,格式如 `[IPv6]:port`。
				if (proxyip.includes(']:')) {
					let lastColonIndex = proxyip.lastIndexOf(':');
					proxyPort = proxyip.slice(lastColonIndex + 1);
					proxyIP = proxyip.slice(0, lastColonIndex);
					
				} else if (!proxyip.includes(']:') && !proxyip.includes(']')) {
					// 处理 IPv4 或域名和端口,格式如 `IP:port`。
					[proxyIP, proxyPort = '443'] = proxyip.split(':');
				} else {
					// 仅有 IP 或域名,端口默认为 443。
					proxyPort = '443';
					proxyIP = proxyip;
				}				
			} else {
				// 如果环境变量中没有 `proxyip`,则使用代码中预设的 `proxyIP`。
				// 同样处理 IPv6 和 IPv4 的情况。
				if (proxyIP.includes(']:')) {
					let lastColonIndex = proxyIP.lastIndexOf(':');
					proxyPort = proxyIP.slice(lastColonIndex + 1);
					proxyIP = proxyIP.slice(0, lastColonIndex);	
				} else {
					// 使用正则表达式解析 IP 和端口,更稳健。
					const match = proxyIP.match(/^(.*?)(?::(\d+))?$/);
					proxyIP = match[1];
					proxyPort = match[2] || '443';
					console.log("IP:", proxyIP, "Port:", proxyPort);
				}
			}
			console.log('ProxyIP:', proxyIP);
			console.log('ProxyPort:', proxyPort);
            // 从环境变量中读取并覆盖预设的 IP 和端口,实现高度自定义。
      CDNIP = env.cdnip || CDNIP;
	  IP1 = env.ip1 || IP1;
	  IP2 = env.ip2 || IP2;
	  IP3 = env.ip3 || IP3;
	  IP4 = env.ip4 || IP4;
	  IP5 = env.ip5 || IP5;
	  IP6 = env.ip6 || IP6;
	  IP7 = env.ip7 || IP7;
	  IP8 = env.ip8 || IP8;
	  IP9 = env.ip9 || IP9;
	  IP10 = env.ip10 || IP10;
	  IP11 = env.ip11 || IP11;
	  IP12 = env.ip12 || IP12;
	  IP13 = env.ip13 || IP13;
	  PT1 = env.pt1 || PT1;
	  PT2 = env.pt2 || PT2;
	  PT3 = env.pt3 || PT3;
	  PT4 = env.pt4 || PT4;
	  PT5 = env.pt5 || PT5;
	  PT6 = env.pt6 || PT6;
	  PT7 = env.pt7 || PT7;
	  PT8 = env.pt8 || PT8;
	  PT9 = env.pt9 || PT9;
	  PT10 = env.pt10 || PT10;
	  PT11 = env.pt11 || PT11;
	  PT12 = env.pt12 || PT12;
	  PT13 = env.pt13 || PT13;
      // 获取请求头中的 'Upgrade' 字段,用于判断是否为 WebSocket 升级请求。
      const upgradeHeader = request.headers.get("Upgrade");
      // 解析请求的 URL。
      const url = new URL(request.url);
      // 如果不是 WebSocket 升级请求,则判断为配置获取请求或普通网页访问。
      if (!upgradeHeader || upgradeHeader !== "websocket") {
        const url = new URL(request.url);
        // 根据 URL 路径进行路由。
        switch (url.pathname) {
          // 路径为 `/<uuid>`,返回主配置页面(HTML 格式)。
          case `/${userID}`: {
            // 解码混淆的函数名 getvlessConfig
            const \u0076\u006c\u0065\u0073\u0073Config = get\u0076\u006c\u0065\u0073\u0073Config(userID, request.headers.get("Host"));
            return new Response(`${\u0076\u006c\u0065\u0073\u0073Config}`, {
              status: 200,
              headers: {
                "Content-Type": "text/html;charset=utf-8",
              },
            });
          }
          // 路径为 `/<uuid>/ty`,返回通用格式的订阅内容 (Base64 编码)。
		  case `/${userID}/ty`: {
			const tyConfig = gettyConfig(userID, request.headers.get('Host'));
			return new Response(`${tyConfig}`, {
				status: 200,
				headers: {
					"Content-Type": "text/plain;charset=utf-8",
				}
			});
		}
        // 路径为 `/<uuid>/cl`,返回 Clash-meta 格式的订阅配置 (YAML)。
		case `/${userID}/cl`: {
			const clConfig = getclConfig(userID, request.headers.get('Host'));
			return new Response(`${clConfig}`, {
				status: 200,
				headers: {
					"Content-Type": "text/plain;charset=utf-8",
				}
			});
		}
        // 路径为 `/<uuid>/sb`,返回 Sing-box 格式的订阅配置 (JSON)。
		case `/${userID}/sb`: {
			const sbConfig = getsbConfig(userID, request.headers.get('Host'));
			return new Response(`${sbConfig}`, {
				status: 200,
				headers: {
					"Content-Type": "application/json;charset=utf-8",
				}
			});
		}
        // 以下为针对 pages/自定义域名 的订阅链接,只包含 TLS 节点
		case `/${userID}/pty`: {
			const ptyConfig = getptyConfig(userID, request.headers.get('Host'));
			return new Response(`${ptyConfig}`, {
				status: 200,
				headers: {
					"Content-Type": "text/plain;charset=utf-8",
				}
			});
		}
		case `/${userID}/pcl`: {
			const pclConfig = getpclConfig(userID, request.headers.get('Host'));
			return new Response(`${pclConfig}`, {
				status: 200,
				headers: {
					"Content-Type": "text/plain;charset=utf-8",
				}
			});
		}
		case `/${userID}/psb`: {
			const psbConfig = getpsbConfig(userID, request.headers.get('Host'));
			return new Response(`${psbConfig}`, {
				status: 200,
				headers: {
					"Content-Type": "application/json;charset=utf-8",
				}
			});
		}
          // 对于其他所有路径
          default:
            // 此处可以返回一个 404 Not Found 页面。
            // 当前逻辑是反向代理到一个随机的网站。
            if (cn_hostnames.includes('')) {
              // 这个判断条件 `cn_hostnames.includes('')` 永远为真,
              // 意图可能是判断来访 IP 是否来自中国,但目前实现会直接返回请求的 cf 信息。
            return new Response(JSON.stringify(request.cf, null, 4), {
              status: 200,
              headers: {
                "Content-Type": "application/json;charset=utf-8",
              },
            });
            }
            // 从 cn_hostnames 列表中随机选择一个主机名(当前列表为空)。
            const randomHostname = cn_hostnames[Math.floor(Math.random() * cn_hostnames.length)];
            const newHeaders = new Headers(request.headers);
            // 修改请求头,伪造客户端 IP 和来源。
            newHeaders.set("cf-connecting-ip", "1.2.3.4");
            newHeaders.set("x-forwarded-for", "1.2.3.4");
            newHeaders.set("x-real-ip", "1.2.3.4");
            newHeaders.set("referer", "https://www.google.com/search?q=edtunnel");
            // 构建代理请求的 URL。
            const proxyUrl = "https://" + randomHostname + url.pathname + url.search;
            // 创建一个新的请求对象,用于向上游服务器发起请求。
            let modifiedRequest = new Request(proxyUrl, {
              method: request.method,
              headers: newHeaders,
              body: request.body,
              redirect: "manual", // 手动处理重定向。
            });
            // 发起代理请求。
            const proxyResponse = await fetch(modifiedRequest, { redirect: "manual" });
            // 如果上游服务器返回 301 或 302 重定向,则返回 403 Forbidden。
            if ([301, 302].includes(proxyResponse.status)) {
              return new Response(`Redirects to ${randomHostname} are not allowed.`, {
                status: 403,
                statusText: "Forbidden",
              });
            }
            // 返回上游服务器的响应。
            return proxyResponse;
        }
      } else {
      // 如果是 WebSocket 升级请求
			// 允许通过 URL 路径临时指定代理 IP,格式如 `/path?pyip=<ip:port>`
			if(url.pathname.includes('/pyip='))
			{
				const tmp_ip=url.pathname.split("=")[1];
				// 验证 IP 格式(当前函数 isValidIP 逻辑简单,实际只检查非空)
				if(isValidIP(tmp_ip))
				{
					proxyIP=tmp_ip;
					// 解析 IP 和端口
					if (proxyIP.includes(']:')) {
						let lastColonIndex = proxyIP.lastIndexOf(':');
						proxyPort = proxyIP.slice(lastColonIndex + 1);
						proxyIP = proxyIP.slice(0, lastColonIndex);	
					} else if (!proxyIP.includes(']:') && !proxyIP.includes(']')) {
						[proxyIP, proxyPort = '443'] = proxyIP.split(':');
					} else {
						proxyPort = '443';
					}
				}	
			}
        // 调用 WebSocket 处理器。函数名 `vlessOverWSHandler` 被混淆。
        return await \u0076\u006c\u0065\u0073\u0073OverWSHandler(request);
		}
    } catch (err) {
      // 捕获任何在处理过程中发生的错误,并返回错误信息。
      /** @type {Error} */ let e = err;
      return new Response(e.toString());
    }
  },
};

/**
 * 检查给定的字符串是否为有效的 IP(此函数实现过于简单,仅检查是否为任意字符串)。
 * @param {string} ip - 要检查的 IP 字符串。
 * @returns {boolean} - 返回 true。
 */
function isValidIP(ip) {
    var reg = /^[\s\S]*$/;
    return reg.test(ip);
}

/**
 * 处理 VLESS over WebSocket 的核心函数。
 * @param {Request} request - 客户端发来的 WebSocket 升级请求。
 */
async function \u0076\u006c\u0065\u0073\u0073OverWSHandler(request) {
  // 创建一个 WebSocket 对,一个用于客户端,一个用于 Worker 内部。
  const webSocketPair = new WebSocketPair();
  const [client, webSocket] = Object.values(webSocketPair);

  // 接受 WebSocket 连接。
  webSocket.accept();

  let address = "";
  let portWithRandomLog = "";
  // 定义一个日志函数,方便调试。
  const log = (/** @type {string} */ info, /** @type {string | undefined} */ event) => {
    console.log(`[${address}:${portWithRandomLog}] ${info}`, event || "");
  };
  // 获取 "sec-websocket-protocol" 头,用于 WebSocket 的 0-RTT (早期数据)。
  const earlyDataHeader = request.headers.get("sec-websocket-protocol") || "";

  // 创建一个可读流,用于从 WebSocket 中读取客户端发送的数据。
  const readableWebSocketStream = makeReadableWebSocketStream(webSocket, earlyDataHeader, log);

  /** @type {{ value: any | null }} */
  // 一个包装器,用于持有到目标服务器的 TCP socket 连接。
  let remoteSocketWapper = {
    value: null,
  };
  let udpStreamWrite = null; // 用于写入 UDP 数据的函数。
  let isDns = false; // 标记当前是否为 DNS 请求。

  // 将 WebSocket 的可读流通过管道连接到一个可写流,处理从客户端到目标服务器的数据流。
  readableWebSocketStream
    .pipeTo(
      new WritableStream({
        // 当有数据块写入时被调用。
        async write(chunk, controller) {
          // 如果是 DNS 请求并且 UDP 写入函数已准备好,则直接写入。
          if (isDns && udpStreamWrite) {
            return udpStreamWrite(chunk);
          }
          // 如果已经建立了到目标服务器的连接,则直接将数据写入该连接。
          if (remoteSocketWapper.value) {
            const writer = remoteSocketWapper.value.writable.getWriter();
            await writer.write(chunk);
            writer.releaseLock();
            return;
          }

          // 如果是第一个数据块,需要解析 VLESS 头部信息。
          // 函数名 `processcloudflareHeader` 被混淆。
          const {
            hasError, // 是否有错误
            message, // 错误信息
            portRemote = 443, // 目标端口
            addressRemote = "", // 目标地址
            rawDataIndex, // 原始负载数据的起始索引
            cloudflareVersion = new Uint8Array([0, 0]), // VLESS 版本
            isUDP, // 是否为 UDP 请求
          } = await processcloudflareHeader(chunk, userID);
          address = addressRemote;
          portWithRandomLog = `${portRemote}--${Math.random()} ${isUDP ? "udp " : "tcp "} `;
          // 如果解析头部出错,则抛出异常,关闭连接。
          if (hasError) {
            throw new Error(message);
            return;
          }
          // 如果是 UDP 请求,目前只支持 DNS (端口 53)。
          if (isUDP) {
            if (portRemote === 53) {
              isDns = true;
            } else {
              // 对于非 DNS 的 UDP 请求,抛出错误。
              throw new Error("UDP proxy only enable for DNS which is port 53");
              return;
            }
          }
          // 构建 VLESS 响应头部。
          const cloudflareResponseHeader = new Uint8Array([cloudflareVersion[0], 0]);
          // 提取真正的请求数据(去除了 VLESS 头部)。
          const rawClientData = chunk.slice(rawDataIndex);

          // 如果是 DNS 请求,则使用 UDP 出站处理器。
          if (isDns) {
            const { write } = await handleUDPOutBound(webSocket, cloudflareResponseHeader, log);
            udpStreamWrite = write;
            udpStreamWrite(rawClientData); // 将第一个数据块写入 UDP 处理器。
            return;
          }
          // 否则,使用 TCP 出站处理器。
          handleTCPOutBound(
            remoteSocketWapper,
            addressRemote,
            portRemote,
            rawClientData,
            webSocket,
            cloudflareResponseHeader,
            log
          );
        },
        // 流关闭时的回调。
        close() {
          log(`readableWebSocketStream is close`);
        },
        // 流异常终止时的回调。
        abort(reason) {
          log(`readableWebSocketStream is abort`, JSON.stringify(reason));
        },
      })
    )
    // 捕获管道处理过程中的任何错误。
    .catch((err) => {
      log("readableWebSocketStream pipeTo error", err);
    });

  // 返回一个 101 Switching Protocols 响应,并将 `client` WebSocket 返回给客户端,
  // 完成 WebSocket 握手。
  return new Response(null, {
    status: 101,
    webSocket: client,
  });
}

/**
 * 检查给定的 UUID 是否存在于一个模拟的 API 响应中。
 * @param {string} targetUuid The UUID to search for.
 * @returns {Promise<boolean>} A Promise that resolves to true if the UUID is present, false otherwise.
 */
async function checkUuidInApiResponse(targetUuid) {
  try {
    // 获取模拟的 API 响应。
    const apiResponse = await getApiResponse();
    if (!apiResponse) {
      return false;
    }
    // 检查 UUID 是否在用户列表中。
    const isUuidInResponse = apiResponse.users.some((user) => user.uuid === targetUuid);
    return isUuidInResponse;
  } catch (error) {
    console.error("Error:", error);
    return false;
  }
}

/**
 * 模拟一个 API 响应,实际返回一个空的用户列表。
 * 这个功能可能是为了未来扩展多用户验证而预留的。
 */
async function getApiResponse() {
	return { users: [] };
  }

/**
 * 处理出站的 TCP 连接。
 * @param {{ value: any | null }} remoteSocket - 持有远程 TCP socket 的包装器对象。
 * @param {string} addressRemote - 目标地址。
 * @param {number} portRemote - 目标端口。
 * @param {Uint8Array} rawClientData - 第一个数据块(通常是 TLS Client Hello)。
 * @param {WebSocket} webSocket - 到客户端的 WebSocket 连接。
 * @param {Uint8Array} cloudflareResponseHeader - VLESS 响应头。
 * @param {Function} log - 日志函数。
 */
async function handleTCPOutBound(
  remoteSocket,
  addressRemote,
  portRemote,
  rawClientData,
  webSocket,
  cloudflareResponseHeader,
  log
) {
  /**
   * 连接到目标服务器并写入初始数据。
   * @param {string} address - 目标地址
   * @param {number} port - 目标端口
   * @returns {Promise<any>} - 返回建立的 TCP socket。
   */
  async function connectAndWrite(address, port) {
    // 这是一个特殊的技巧:如果地址是纯 IP,则在其前后加上固定的字符串,
    // 转换成一个域名 `www.<address>.sslip.io`,这可能是为了绕过某些对纯 IP 连接的限制。
    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('LnNzbGlwLmlv')}`; // atob('d3d3Lg==') -> "www.", atob('LnNzbGlwLmlv') -> ".sslip.io"
	/** @type {any} */
    // 使用 `connect` API 建立 TCP 连接。
    const tcpSocket = connect({
      hostname: address,
      port: port,
    });
    // 将建立的连接保存到包装器中。
    remoteSocket.value = tcpSocket;
    log(`connected to ${address}:${port}`);
    // 写入第一个数据块。
    const writer = tcpSocket.writable.getWriter();
    await writer.write(rawClientData);
    writer.releaseLock();
    return tcpSocket;
  }

  // 如果直接连接目标服务器失败或无响应,则尝试连接到预设的 `proxyIP`。
  async function retry() {
    const tcpSocket = await connectAndWrite(proxyIP || addressRemote, proxyPort || portRemote);
    // 不管重试是否成功,最终都要安全地关闭 WebSocket。
    tcpSocket.closed
      .catch((error) => {
        console.log("retry tcpSocket closed error", error);
      })
      .finally(() => {
        safeCloseWebSocket(webSocket);
      });
    // 将重试后建立的连接和 WebSocket 连接起来。
    remoteSocketToWS(tcpSocket, webSocket, cloudflareResponseHeader, null, log);
  }

  // 首次尝试直接连接客户端请求的目标地址。
  const tcpSocket = await connectAndWrite(addressRemote, portRemote);

  // 将 TCP socket 的可读流和 WebSocket 的可写流连接起来,
  // 实现从目标服务器到客户端的数据转发。
  // `retry` 函数作为回调传入,在连接失败时触发。
  remoteSocketToWS(tcpSocket, webSocket, cloudflareResponseHeader, retry, log);
}

/**
 * 将 WebSocket 封装成一个 ReadableStream,使其能方便地使用 Stream API。
 * @param {WebSocket} webSocketServer - Worker 端的 WebSocket 对象。
 * @param {string} earlyDataHeader - 用于 0-RTT 的早期数据。
 * @param {(info: string)=> void} log - 日志函数。
 * @returns {ReadableStream}
 */
function makeReadableWebSocketStream(webSocketServer, earlyDataHeader, log) {
  let readableStreamCancel = false;
  const stream = new ReadableStream({
    start(controller) {
      // 监听 'message' 事件,当从客户端收到数据时,将其推入流中。
      webSocketServer.addEventListener("message", (event) => {
        if (readableStreamCancel) {
          return;
        }
        const message = event.data;
        controller.enqueue(message);
      });

      // 监听 'close' 事件,当客户端关闭连接时,也关闭流。
      webSocketServer.addEventListener("close", () => {
        safeCloseWebSocket(webSocketServer);
        if (readableStreamCancel) {
          return;
        }
        controller.close();
      });
      // 监听 'error' 事件,将错误传递给流。
      webSocketServer.addEventListener("error", (err) => {
        log("webSocketServer has error");
        controller.error(err);
      });
      // 处理 WebSocket 的 0-RTT 早期数据。
      const { earlyData, error } = base64ToArrayBuffer(earlyDataHeader);
      if (error) {
        controller.error(error);
      } else if (earlyData) {
        controller.enqueue(earlyData);
      }
    },

    pull(controller) {
      // 拉取数据的逻辑,此处为空,因为 WebSocket 是推送模型。
    },
    // 当流被取消(通常是下游的 WritableStream 出错)时的回调。
    cancel(reason) {
      if (readableStreamCancel) {
        return;
      }
      log(`ReadableStream was canceled, due to ${reason}`);
      readableStreamCancel = true;
      safeCloseWebSocket(webSocketServer); // 安全地关闭 WebSocket。
    },
  });

  return stream;
}


// VLESS 协议头部格式文档:
// https://xtls.github.io/development/protocols/cloudflare.html
// https://github.com/zizifn/excalidraw-backup/blob/main/v2ray-protocol.excalidraw

/**
 * 解析 VLESS 协议头部。
 * @param {ArrayBuffer} cloudflareBuffer - 从客户端收到的第一个数据块。
 * @param {string} userID - 用户的 UUID。
 * @returns {Promise<object>} - 返回解析结果的对象。
 */
async function processcloudflareHeader(cloudflareBuffer, userID) {
  // VLESS 头部至少需要 24 字节。
  if (cloudflareBuffer.byteLength < 24) {
    return { hasError: true, message: "invalid data" };
  }
  // 第 1 字节:协议版本
  const version = new Uint8Array(cloudflareBuffer.slice(0, 1));
  let isValidUser = false;
  let isUDP = false;
  // 接下来 16 字节:用户 UUID
  const slicedBuffer = new Uint8Array(cloudflareBuffer.slice(1, 17));
  // 将 UUID 字节数组转换为字符串。
  const slicedBufferString = stringify(slicedBuffer);

  // 支持多个 UUID,以逗号分隔。
  const uuids = userID.includes(",") ? userID.split(",") : [userID];

  // 检查 UUID 是否在模拟的 API 响应中(当前此功能无效)。
  const checkUuidInApi = await checkUuidInApiResponse(slicedBufferString);
  // 验证客户端 UUID 是否匹配。
  isValidUser = uuids.some((userUuid) => checkUuidInApi || slicedBufferString === userUuid.trim());

  console.log(`checkUuidInApi: ${await checkUuidInApiResponse(slicedBufferString)}, userID: ${slicedBufferString}`);

  if (!isValidUser) {
    return { hasError: true, message: "invalid user" };
  }

  // 第 18 字节:附加信息长度,此处跳过。
  const optLength = new Uint8Array(cloudflareBuffer.slice(17, 18))[0];

  // 附加信息后的第 1 字节:指令
  const command = new Uint8Array(cloudflareBuffer.slice(18 + optLength, 18 + optLength + 1))[0];

  // 0x01 TCP
  // 0x02 UDP
  // 0x03 MUX (不支持)
  if (command === 1) {
    // TCP
  } else if (command === 2) {
    isUDP = true;
  } else {
    return { hasError: true, message: `command ${command} is not support, command 01-tcp,02-udp,03-mux`};
  }
  // 接下来 2 字节:目标端口(大端序)
  const portIndex = 18 + optLength + 1;
  const portBuffer = cloudflareBuffer.slice(portIndex, portIndex + 2);
  const portRemote = new DataView(portBuffer).getUint16(0);

  // 接下来 1 字节:目标地址类型
  let addressIndex = portIndex + 2;
  const addressBuffer = new Uint8Array(cloudflareBuffer.slice(addressIndex, addressIndex + 1));

  // 1 -> IPv4 (长度 4)
  // 2 -> 域名 (长度由下一字节决定)
  // 3 -> IPv6 (长度 16)
  const addressType = addressBuffer[0];
  let addressLength = 0;
  let addressValueIndex = addressIndex + 1;
  let addressValue = "";
  switch (addressType) {
    case 1: // IPv4
      addressLength = 4;
      addressValue = new Uint8Array(cloudflareBuffer.slice(addressValueIndex, addressValueIndex + addressLength)).join(".");
      break;
    case 2: // 域名
      addressLength = new Uint8Array(cloudflareBuffer.slice(addressValueIndex, addressValueIndex + 1))[0];
      addressValueIndex += 1;
      addressValue = new TextDecoder().decode(cloudflareBuffer.slice(addressValueIndex, addressValueIndex + addressLength));
      break;
    case 3: // IPv6
      addressLength = 16;
      const dataView = new DataView(cloudflareBuffer.slice(addressValueIndex, addressValueIndex + addressLength));
      const ipv6 = [];
      for (let i = 0; i < 8; i++) {
        ipv6.push(dataView.getUint16(i * 2).toString(16));
      }
      addressValue = ipv6.join(":");
      break;
    default:
      return { hasError: true, message: `invild addressType is ${addressType}` };
  }
  if (!addressValue) {
    return { hasError: true, message: `addressValue is empty, addressType is ${addressType}` };
  }

  return {
    hasError: false,
    addressRemote: addressValue,
    addressType,
    portRemote,
    // 原始负载数据的起始位置
    rawDataIndex: addressValueIndex + addressLength,
    cloudflareVersion: version,
    isUDP,
  };
}

/**
 * 将远程 TCP socket 的数据流转发到 WebSocket。
 * @param {any} remoteSocket - 到目标服务器的 TCP socket。
 * @param {WebSocket} webSocket - 到客户端的 WebSocket 连接。
 * @param {ArrayBuffer} cloudflareResponseHeader - VLESS 响应头。
 * @param {(() => Promise<void>) | null} retry - 连接失败时的重试函数。
 * @param {*} log - 日志函数。
 */
async function remoteSocketToWS(remoteSocket, webSocket, cloudflareResponseHeader, retry, log) {
  // remote--> ws
  let remoteChunkCount = 0;
  let chunks = [];
  let cloudflareHeader = cloudflareResponseHeader;
  let hasIncomingData = false; // 标记是否收到了来自目标服务器的数据。
  // 将远程 socket 的可读流通过管道连接到可写流。
  await remoteSocket.readable
    .pipeTo(
      new WritableStream({
        start() {},
        /**
         * 当从目标服务器收到数据时调用。
         * @param {Uint8Array} chunk - 数据块。
         * @param {*} controller
         */
        async write(chunk, controller) {
          hasIncomingData = true;
          // 检查 WebSocket 是否仍然打开。
          if (webSocket.readyState !== WS_READY_STATE_OPEN) {
            controller.error("webSocket.readyState is not open, maybe close");
          }
          // 对于第一个数据块,需要先发送 VLESS 响应头。
          if (cloudflareHeader) {
            webSocket.send(await new Blob([cloudflareHeader, chunk]).arrayBuffer());
            cloudflareHeader = null; // 清空头部,后续不再发送。
          } else {
            // 直接转发数据。
            webSocket.send(chunk);
          }
        },
        // 远程连接关闭时的回调。
        close() {
          log(`remoteConnection!.readable is close with hasIncomingData is ${hasIncomingData}`);
        },
        // 远程连接异常终止时的回调。
        abort(reason) {
          console.error(`remoteConnection!.readable abort`, reason);
        },
      })
    )
    .catch((error) => {
      console.error(`remoteSocketToWS has exception `, error.stack || error);
      safeCloseWebSocket(webSocket);
    });

  // 如果连接建立后没有收到任何数据,并且有重试函数,则调用重试。
  // 这可以处理目标服务器不响应或连接被中间设备拦截的情况。
  if (hasIncomingData === false && retry) {
    log(`retry`);
    retry();
  }
}

/**
 * 将 Base64 字符串解码为 ArrayBuffer。
 * @param {string} base64Str
 * @returns {{earlyData: ArrayBuffer, error: Error | null}}
 */
function base64ToArrayBuffer(base64Str) {
  if (!base64Str) {
    return { error: null };
  }
  try {
    // 替换 URL-safe Base64 字符为标准字符。
    base64Str = base64Str.replace(/-/g, "+").replace(/_/g, "/");
    // 使用 atob 解码。
    const decode = atob(base64Str);
    const arryBuffer = Uint8Array.from(decode, (c) => c.charCodeAt(0));
    return { earlyData: arryBuffer.buffer, error: null };
  } catch (error) {
    return { error };
  }
}

/**
 * 验证字符串是否符合 UUID v4 格式。
 * @param {string} uuid
 */
function isValidUUID(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;
  return uuidRegex.test(uuid);
}

// WebSocket 的状态常量
const WS_READY_STATE_OPEN = 1;
const WS_READY_STATE_CLOSING = 2;
/**
 * 安全地关闭 WebSocket 连接,避免在已关闭的连接上再次调用 close() 导致异常。
 * @param {WebSocket} socket
 */
function safeCloseWebSocket(socket) {
  try {
    if (socket.readyState === WS_READY_STATE_OPEN || socket.readyState === WS_READY_STATE_CLOSING) {
      socket.close();
    }
  } catch (error) {
    console.error("safeCloseWebSocket error", error);
  }
}

// 预先计算好 0-255 的十六进制表示,用于提高 UUID 字符串化的性能。
const byteToHex = [];
for (let i = 0; i < 256; ++i) {
  byteToHex.push((i + 256).toString(16).slice(1));
}

/**
 * 将 16 字节的数组快速转换为 UUID 格式的字符串(不进行验证)。
 * @param {Uint8Array} arr - 字节数组
 * @param {number} offset - 起始偏移
 * @returns {string}
 */
function unsafeStringify(arr, offset = 0) {
  return (
    byteToHex[arr[offset + 0]] +
    byteToHex[arr[offset + 1]] +
    byteToHex[arr[offset + 2]] +
    byteToHex[arr[offset + 3]] +
    "-" +
    byteToHex[arr[offset + 4]] +
    byteToHex[arr[offset + 5]] +
    "-" +
    byteToHex[arr[offset + 6]] +
    byteToHex[arr[offset + 7]] +
    "-" +
    byteToHex[arr[offset + 8]] +
    byteToHex[arr[offset + 9]] +
    "-" +
    byteToHex[arr[offset + 10]] +
    byteToHex[arr[offset + 11]] +
    byteToHex[arr[offset + 12]] +
    byteToHex[arr[offset + 13]] +
    byteToHex[arr[offset + 14]] +
    byteToHex[arr[offset + 15]]
  ).toLowerCase();
}

/**
 * 将字节数组转换为 UUID 字符串,并进行格式验证。
 * @param {Uint8Array} arr - 字节数组
 * @param {number} offset - 起始偏移
 * @returns {string}
 */
function stringify(arr, offset = 0) {
  const uuid = unsafeStringify(arr, offset);
  if (!isValidUUID(uuid)) {
    throw TypeError("Stringified UUID is invalid");
  }
  return uuid;
}
 
/**
 * 处理出站的 UDP 流量(仅限 DNS)。
 * @param {WebSocket} webSocket - 到客户端的 WebSocket 连接。
 * @param {ArrayBuffer} cloudflareResponseHeader - VLESS 响应头。
 * @param {(string)=> void} log - 日志函数。
 * @returns {Promise<{write: (chunk: Uint8Array) => void}>} 返回一个包含 write 方法的对象。
 */
async function handleUDPOutBound(webSocket, cloudflareResponseHeader, log) {
  let iscloudflareHeaderSent = false;
  const transformStream = new TransformStream({
    start(controller) {},
    // 转换函数,处理 VLESS UDP 数据包格式。
    transform(chunk, controller) {
      // VLESS UDP 格式:[2字节长度][UDP负载]...
      for (let index = 0; index < chunk.byteLength; ) {
        // 读取 2 字节的长度信息。
        const lengthBuffer = chunk.slice(index, index + 2);
        const udpPakcetLength = new DataView(lengthBuffer).getUint16(0);
        // 读取 UDP 负载。
        const udpData = new Uint8Array(chunk.slice(index + 2, index + 2 + udpPakcetLength));
        index = index + 2 + udpPakcetLength;
        // 将解析出的 UDP 负载推入下一个流。
        controller.enqueue(udpData);
      }
    },
    flush(controller) {},
  });

  // 将转换后的流(纯 DNS 查询报文)通过管道连接到可写流。
  transformStream.readable
    .pipeTo(
      new WritableStream({
        // 当有 DNS 查询报文时调用。
        async write(chunk) {
          // 使用 fetch API 将 DNS 查询发送到 DoH 服务器。
          const resp = await fetch(
            dohURL,
            {
              method: "POST",
              headers: {
                "content-type": "application/dns-message",
              },
              body: chunk,
            }
          );
          // 获取 DoH 服务器返回的 DNS 响应。
          const dnsQueryResult = await resp.arrayBuffer();
          const udpSize = dnsQueryResult.byteLength;
          // 将 DNS 响应重新打包成 VLESS UDP 格式。
          const udpSizeBuffer = new Uint8Array([(udpSize >> 8) & 0xff, udpSize & 0xff]);
          if (webSocket.readyState === WS_READY_STATE_OPEN) {
            log(`doh success and dns message length is ${udpSize}`);
            // 如果是第一个响应包,需要附加 VLESS 响应头。
            if (iscloudflareHeaderSent) {
              webSocket.send(await new Blob([udpSizeBuffer, dnsQueryResult]).arrayBuffer());
            } else {
              webSocket.send(await new Blob([cloudflareResponseHeader, udpSizeBuffer, dnsQueryResult]).arrayBuffer());
              iscloudflareHeaderSent = true;
            }
          }
        },
      })
    )
    .catch((error) => {
      log("dns udp has error" + error);
    });

  // 获取 transformStream 的写入器。
  const writer = transformStream.writable.getWriter();

  return {
    /**
     * 返回一个 write 方法,用于接收上游传来的 VLESS UDP 数据。
     * @param {Uint8Array} chunk
     */
    write(chunk) {
      writer.write(chunk);
    },
  };
}

/**
 * 生成主配置页面(HTML)。
 * @param {string} userID - 用户 UUID。
 * @param {string | null} hostName - 当前请求的主机名。
 * @returns {string} - 返回生成的 HTML 字符串。
 */
function get\u0076\u006c\u0065\u0073\u0073Config(userID, hostName) {
  // 生成 VLESS + WS (no-tls) 和 VLESS + WS + TLS 两种单节点分享链接。
  // 注意,函数名和变量名中的 `vless` 被 Unicode 混淆。
  const w\u0076\u006c\u0065\u0073\u0073ws = `\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${CDNIP}:8880?encryption=none&security=none&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#${hostName}`;
  const p\u0076\u006c\u0065\u0073\u0073wstls = `\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${CDNIP}:8443?encryption=none&security=tls&type=ws&host=${hostName}&sni=${hostName}&fp=random&path=%2F%3Fed%3D2560#${hostName}`;
  const note = `甬哥博客地址:https://ygkkk.blogspot.com\n甬哥YouTube频道:https://www.youtube.com/@ygkkk\n甬哥TG电报群组:https://t.me/ygkkktg\n甬哥TG电报频道:https://t.me/ygkkktgpd\n\nProxyIP全局运行中:${proxyIP}:${proxyPort}`;
  // 生成各种订阅链接的 URL。
  const ty = `https://${hostName}/${userID}/ty` // 通用
  const cl = `https://${hostName}/${userID}/cl` // Clash
  const sb = `https://${hostName}/${userID}/sb` // Sing-box
  const pty = `https://${hostName}/${userID}/pty` // 通用 (TLS-only)
  const pcl = `https://${hostName}/${userID}/pcl` // Clash (TLS-only)
  const psb = `https://${hostName}/${userID}/psb` // Sing-box (TLS-only)

  // 生成包含所有 13 个节点的通用分享链接(Base64 编码)。
  const wk\u0076\u006c\u0065\u0073\u0073share = btoa(`\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP1}:${PT1}?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V1_${IP1}_${PT1}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP2}:${PT2}?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V2_${IP2}_${PT2}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP3}:${PT3}?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V3_${IP3}_${PT3}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP4}:${PT4}?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V4_${IP4}_${PT4}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP5}:${PT5}?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V5_${IP5}_${PT5}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP6}:${PT6}?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V6_${IP6}_${PT6}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP7}:${PT7}?encryption=none&security=none&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V7_${IP7}_${PT7}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP8}:${PT8}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V8_${IP8}_${PT8}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP9}:${PT9}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V9_${IP9}_${PT9}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP10}:${PT10}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V10_${IP10}_${PT10}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP11}:${PT11}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V11_${IP11}_${PT11}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP12}:${PT12}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V12_${IP12}_${PT12}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP13}:${PT13}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V13_${IP13}_${PT13}`);

  // 生成只包含 TLS 节点的通用分享链接(Base64 编码)。
  const pg\u0076\u006c\u0065\u0073\u0073share = btoa(`\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP8}:${PT8}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V8_${IP8}_${PT8}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP9}:${PT9}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V9_${IP9}_${PT9}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP10}:${PT10}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V10_${IP10}_${PT10}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP11}:${PT11}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V11_${IP11}_${PT11}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP12}:${PT12}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V12_${IP12}_${PT12}\n\u0076\u006c\u0065\u0073\u0073\u003A//${userID}\u0040${IP13}:${PT13}?encryption=none&security=tls&sni=${hostName}&fp=randomized&type=ws&host=${hostName}&path=%2F%3Fed%3D2560#CF_V13_${IP13}_${PT13}`);	
	
  // 将备注中的换行符替换为 HTML 的 <br> 标签。
  const noteshow = note.replace(/\n/g, '<br>');
  // 定义 HTML 页面的头部和样式,以及一个用于复制文本到剪贴板的 JavaScript 函数。
  const displayHtml = `
...// 此处省略了大部分 HTML 结构代码
`;
// 根据主机名是否为 workers.dev 的子域名,显示不同的页面内容。
// workers.dev 域名显示包含非 TLS 和 TLS 节点的完整版本。
if (hostName.includes("workers.dev")) {
return `
...// 此处省略了 workers.dev 域名的 HTML 结构代码
`;
  } else {
// 自定义域名或 Pages 域名只显示 TLS 节点版本。
    return `
...// 此处省略了自定义域名的 HTML 结构代码
`;
  }
}

/**
 * 生成通用订阅内容 (Base64 编码,包含所有节点)。
 * @param {string} userID 
 * @param {string} hostName 
 * @returns {string} Base64 编码的 VLESS 链接列表
 */
function gettyConfig(userID, hostName) {
	const \u0076\u006c\u0065\u0073\u0073share = btoa(`...`); // 同上,省略了所有节点的拼接
		return `${\u0076\u006c\u0065\u0073\u0073share}`
	}
/**
 * 生成 Clash-meta 订阅配置文件 (YAML 格式,包含所有节点)。
 * @param {string} userID 
 * @param {string} hostName 
 * @returns {string} YAML 格式的配置
 */
function getclConfig(userID, hostName) {
return `
port: 7890
allow-lan: true
...// 此处省略了完整的 Clash YAML 配置模板
proxies:
- name: CF_V1_${IP1}_${PT1}
  type: \u0076\u006c\u0065\u0073\u0073
  server: ${IP1.replace(/[\[\]]/g, '')}
  port: ${PT1}
  uuid: ${userID}
...// 动态填充所有节点
proxy-groups:
...// 预设的代理组
rules:
...// 预设的规则
`
}
	
/**
 * 生成 Sing-box 订阅配置文件 (JSON 格式,包含所有节点)。
 * @param {string} userID 
 * @param {string} hostName 
 * @returns {string} JSON 格式的配置
 */
function getsbConfig(userID, hostName) {
return `{
	"log": {...},
	"experimental": {...},
	"dns": {...},
	"inbounds": [...],
	"outbounds": [
		{
		  "tag": "select",
		  "type": "selector",
...// 动态填充所有节点
		},
...
	],
	"route": {...}
}`
}

/**
 * 生成通用订阅内容 (Base64 编码,仅 TLS 节点)。
 * @param {string} userID 
 * @param {string} hostName 
 * @returns {string}
 */
function getptyConfig(userID, hostName) {
	const \u0076\u006c\u0065\u0073\u0073share = btoa(`...`); // 省略了 TLS 节点的拼接
		return `${\u0076\u006c\u0065\u0073\u0073share}`
	}

/**
 * 生成 Clash-meta 订阅配置文件 (YAML 格式,仅 TLS 节点)。
 * @param {string} userID 
 * @param {string} hostName 
 * @returns {string}
 */	
function getpclConfig(userID, hostName) {
return `
...// 省略了仅包含 TLS 节点的 Clash YAML 配置
`
}

/**
 * 生成 Sing-box 订阅配置文件 (JSON 格式,仅 TLS 节点)。
 * @param {string} userID 
 * @param {string} hostName 
 * @returns {string}
 */		
function getpsbConfig(userID, hostName) {
return `{
...// 省略了仅包含 TLS 节点的 Sing-box JSON 配置
}`
}