<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta content="width=device-width, initial-scale=1.0" name="viewport" />
    <title>sub2clash</title>

    <!-- Bootstrap CSS -->
    <link
      crossorigin="anonymous"
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
      integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
      rel="stylesheet"
    />

    <!-- Bootstrap JS -->
    <script
      crossorigin="anonymous"
      integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
    ></script>

    <!-- Axios -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

    <style>
      .container {
        max-width: 800px;
      }

      .btn-xs {
        padding: 2px 2px; /* 调整内边距以减小按钮大小 */
        font-size: 10px; /* 设置字体大小 */
        line-height: 1.2; /* 调整行高 */
        border-radius: 3px; /* 可选的边框半径调整 */
        height: 25px;
        width: 25px;
      }
    </style>
  </head>

  <body class="bg-light">
    <div class="container mt-5">
      <div class="mb-4">
        <h2>sub2clash</h2>
        <span class="text-muted fst-italic"
          >通用订阅链接转 Clash(Meta) 配置工具
          <a
            href="https://github.com/nitezs/sub2clash#clash-meta"
            target="_blank"
            >使用文档</a
          ></span
        >
      </div>

      <form id="apiForm">
        <!-- API Endpoint -->
        <div class="form-group mb-3">
          <label for="endpoint">客户端类型:</label>
          <select class="form-control" id="endpoint" name="endpoint">
            <option value="clash">Clash</option>
            <option value="meta">Clash.Meta</option>
          </select>
        </div>

        <!-- Subscription Link -->
        <div class="form-group mb-3">
          <label for="sub">订阅链接:</label>
          <textarea
            class="form-control"
            id="sub"
            name="sub"
            placeholder="每行输入一个订阅链接"
            rows="5"
          ></textarea>
        </div>

        <!-- Proxy Link -->
        <div class="form-group mb-3">
          <label for="proxy">节点分享链接:</label>
          <textarea
            class="form-control"
            id="proxy"
            name="proxy"
            placeholder="每行输入一个节点分享链接"
            rows="5"
          ></textarea>
        </div>

        <!-- Refresh -->
        <div class="form-check mb-3">
          <input
            class="form-check-input"
            id="refresh"
            name="refresh"
            type="checkbox"
          />
          <label class="form-check-label" for="refresh">强制刷新配置</label>
        </div>

        <!-- Template -->
        <div class="form-group mb-3">
          <label for="template">模板链接或名称(可选):</label>
          <input
            class="form-control"
            id="template"
            name="template"
            placeholder="输入外部模板链接或内部模板名称"
            type="text"
          />
        </div>

        <!-- Rule Provider -->
        <div class="form-group mb-3" id="ruleProviderGroup">
          <label>Rule Provider:</label>
          <button
            class="btn btn-primary mb-1 btn-xs"
            onclick="addRuleProvider()"
            type="button"
          >
            +
          </button>
        </div>

        <!-- Rule -->
        <div class="form-group mb-3" id="ruleGroup">
          <label>规则:</label>
          <button
            class="btn btn-primary mb-1 btn-xs"
            onclick="addRule()"
            type="button"
          >
            +
          </button>
        </div>

        <!-- Auto Test -->
        <div class="form-check mb-3">
          <input
            class="form-check-input"
            id="autoTest"
            name="autoTest"
            type="checkbox"
          />
          <label class="form-check-label" for="autoTest"
            >国家策略组自动测速</label
          >
        </div>

        <!-- Lazy -->
        <div class="form-check mb-3">
          <input
            class="form-check-input"
            id="lazy"
            name="lazy"
            type="checkbox"
          />
          <label class="form-check-label" for="lazy">自动测速启用 lazy</label>
        </div>

        <!-- Sort -->
        <div class="form-group mb-3">
          <label for="sort">国家策略组排序策略:</label>
          <select class="form-control" id="sort" name="sort">
            <option value="nameasc">名称(升序)</option>
            <option value="namedesc">名称(降序)</option>
            <option value="sizeasc">节点数量(升序)</option>
            <option value="sizedesc">节点数量(降序)</option>
          </select>
        </div>

        <!-- Remove -->
        <div class="form-group mb-3">
          <label for="remove">删除节点:</label>
          <input
            class="form-control"
            type="text"
            name="remove"
            id="remove"
            placeholder="正则表达式"
          />
        </div>

        <!-- Rename  -->
        <div class="form-group mb-3" id="replaceGroup">
          <label>节点名称替换:</label>
          <button
            class="btn btn-primary mb-1 btn-xs"
            onclick="addReplace()"
            type="button"
          >
            +
          </button>
        </div>
      </form>

      <!-- Display the API Link -->
      <div class="form-group mb-5">
        <label for="apiLink">配置链接:</label>
        <div class="input-group mb-2">
          <input class="form-control" id="apiLink" readonly type="text" />
          <button class="btn btn-primary" onclick="generateURL()" type="button">
            生成链接
          </button>
          <button
            class="btn btn-primary"
            onclick="copyToClipboard('apiLink',this)"
            type="button"
          >
            复制链接
          </button>
        </div>
        <div class="input-group">
          <input class="form-control" id="apiShortLink" readonly type="text" />
          <input
            class="form-control"
            id="password"
            type="text"
            placeholder="密码"
          />
          <button
            class="btn btn-primary"
            onclick="generateShortLink()"
            type="button"
          >
            生成短链
          </button>
          <button
            class="btn btn-primary"
            onclick="copyToClipboard('apiShortLink',this)"
            type="button"
          >
            复制短链
          </button>
        </div>
      </div>

      <!-- footer-->
      <footer>
        <p class="text-center">
          Powered by
          <a class="link-primary" href="https://github.com/nitezs/sub2clash"
            >sub2clash</a
          >
        </p>
        <p class="text-center">Version {{.Version}}</p>
      </footer>
    </div>

    <script>
      async function copyToClipboard(elem, e) {
        const apiLinkInput = document.querySelector(`#${elem}`).value;
        try {
          await navigator.clipboard.writeText(apiLinkInput);
          let text = e.textContent;
          e.addEventListener("mouseout", function () {
            e.textContent = text;
          });
          e.textContent = "复制成功";
        } catch (err) {
          console.error("复制到剪贴板失败:", err);
        }
      }

      function createRuleProvider() {
        const div = document.createElement("div");
        div.classList.add("input-group", "mb-2");
        div.innerHTML = `
            <input type="text" class="form-control" name="ruleProvider" placeholder="Behavior">
            <input type="text" class="form-control" name="ruleProvider" placeholder="Url">
            <input type="text" class="form-control" name="ruleProvider" placeholder="Group">
            <input type="text" class="form-control" name="ruleProvider" placeholder="Prepend">
            <input type="text" class="form-control" name="ruleProvider" placeholder="Name">
            <button type="button" class="btn btn-danger" onclick="removeElement(this)">删除</button>
        `;
        return div;
      }

      function createReplace() {
        const div = document.createElement("div");
        div.classList.add("input-group", "mb-2");
        div.innerHTML = `
            <input type="text" class="form-control" name="replace" placeholder="原字符串(正则表达式)">
            <input type="text" class="form-control" name="replace" placeholder="替换为(可为空)">
            <button type="button" class="btn btn-danger" onclick="removeElement(this)">删除</button>
        `;
        return div;
      }

      function createRule() {
        const div = document.createElement("div");
        div.classList.add("input-group", "mb-2");
        div.innerHTML = `
            <input type="text" class="form-control" name="rule" placeholder="Rule">
            <input type="text" class="form-control" name="rule" placeholder="Prepend">
            <input type="text" class="form-control" name="rule" placeholder="Group">
            <button type="button" class="btn btn-danger" onclick="removeElement(this)">删除</button>
        `;
        return div;
      }

      function addRuleProvider() {
        const div = createRuleProvider();
        document.getElementById("ruleProviderGroup").appendChild(div);
      }

      function addRule() {
        const div = createRule();
        document.getElementById("ruleGroup").appendChild(div);
      }

      function addReplace() {
        const div = createReplace();
        document.getElementById("replaceGroup").appendChild(div);
      }

      function removeElement(button) {
        button.parentElement.remove();
      }

      function generateURI() {
        const queryParams = [];

        // 获取 API Endpoint
        const endpoint = document.getElementById("endpoint").value;

        // 获取并组合订阅链接
        let subLines = document
          .getElementById("sub")
          .value.split("\n")
          .filter((line) => line.trim() !== "");
        let noSub = false;
        // 去除 subLines 中空元素
        subLines = subLines.map((item) => {
          if (item !== "") {
            return item;
          }
        });
        if (subLines.length > 0) {
          queryParams.push(`sub=${encodeURIComponent(subLines.join(","))}`);
        } else {
          noSub = true;
        }

        // 获取并组合节点分享链接
        let proxyLines = document
          .getElementById("proxy")
          .value.split("\n")
          .filter((line) => line.trim() !== "");
        let noProxy = false;
        // 去除 proxyLines 中空元素
        proxyLines = proxyLines.map((item) => {
          if (item !== "") {
            return item;
          }
        });
        if (proxyLines.length > 0) {
          queryParams.push(`proxy=${encodeURIComponent(proxyLines.join(","))}`);
        } else {
          noProxy = true;
        }
        if (noSub && noProxy) {
          alert("订阅链接和节点分享链接不能同时为空!");
          return "";
        }
        // 获取复选框的值
        const refresh = document.getElementById("refresh").checked;
        queryParams.push(`refresh=${refresh ? "true" : "false"}`);
        const autoTest = document.getElementById("autoTest").checked;
        queryParams.push(`autoTest=${autoTest ? "true" : "false"}`);
        const lazy = document.getElementById("lazy").checked;
        queryParams.push(`lazy=${lazy ? "true" : "false"}`);

        // 获取模板链接或名称(如果存在)
        const template = document.getElementById("template").value;
        if (template.trim() !== "") {
          queryParams.push(`template=${encodeURIComponent(template)}`);
        }

        // 获取Rule Provider和规则
        const ruleProviders = document.getElementsByName("ruleProvider");
        const rules = document.getElementsByName("rule");
        let providers = [];
        for (let i = 0; i < ruleProviders.length / 5; i++) {
          let baseIndex = i * 5;
          let behavior = ruleProviders[baseIndex].value;
          let url = ruleProviders[baseIndex + 1].value;
          let group = ruleProviders[baseIndex + 2].value;
          let prepend = ruleProviders[baseIndex + 3].value;
          let name = ruleProviders[baseIndex + 4].value;
          // 是否存在空值
          if (
            behavior.trim() === "" ||
            url.trim() === "" ||
            group.trim() === "" ||
            prepend.trim() === "" ||
            name.trim() === ""
          ) {
            alert("Rule Provider 中存在空值,请检查后重试!");
            return "";
          }
          providers.push(`[${behavior},${url},${group},${prepend},${name}]`);
        }
        queryParams.push(
          `ruleProvider=${encodeURIComponent(providers.join(","))}`,
        );

        let ruleList = [];
        for (let i = 0; i < rules.length / 3; i++) {
          if (rules[i * 3].value.trim() !== "") {
            let rule = rules[i * 3].value;
            let prepend = rules[i * 3 + 1].value;
            let group = rules[i * 3 + 2].value;
            // 是否存在空值
            if (
              rule.trim() === "" ||
              prepend.trim() === "" ||
              group.trim() === ""
            ) {
              alert("Rule 中存在空值,请检查后重试!");
              return "";
            }
            ruleList.push(`[${rule},${prepend},${group}]`);
          }
        }
        queryParams.push(`rule=${encodeURIComponent(ruleList.join(","))}`);

        // 获取排序策略
        const sort = document.getElementById("sort").value;
        queryParams.push(`sort=${sort}`);

        // 获取删除节点的正则表达式
        const remove = document.getElementById("remove").value;
        if (remove.trim() !== "") {
          queryParams.push(`remove=${encodeURIComponent(remove)}`);
        }

        // 获取替换节点名称的正则表达式
        let replaceList = [];
        const replaces = document.getElementsByName("replace");
        for (let i = 0; i < replaces.length / 2; i++) {
          let replaceStr = `<${replaces[i * 2].value}>`;
          let replaceTo = `<${replaces[i * 2 + 1].value}>`;
          if (replaceStr.trim() === "") {
            alert("重命名设置中存在空值,请检查后重试!");
            return "";
          }
          replaceList.push(`[${replaceStr},${replaceTo}]`);
        }
        queryParams.push(
          `replace=${encodeURIComponent(replaceList.join(","))}`,
        );

        return `${endpoint}?${queryParams.join("&")}`;
      }

      function generateURL() {
        const apiLink = document.getElementById("apiLink");
        let uri = generateURI();
        if (uri === "") {
          return;
        }
        apiLink.value = `${window.location.origin}${window.location.pathname}${uri}`;
      }

      function generateShortLink() {
        const apiShortLink = document.getElementById("apiShortLink");
        const password = document.getElementById("password");
        let uri = generateURI();
        if (uri === "") {
          return;
        }
        axios
          .post(
            "./short",
            {
              url: uri,
              password: password.value.trim(),
            },
            {
              headers: {
                "Content-Type": "application/json",
              },
            },
          )
          .then((response) => {
            apiShortLink.value = `${window.location.origin}${window.location.pathname}s/${response.data}`;
          })
          .catch((error) => {
            console.log(error);
            alert("生成短链失败,请重试!");
          });
      }
    </script>
  </body>
</html>