diff --git a/config-sub-converter/scripts/convert-awg-to-clash.js b/config-sub-converter/scripts/convert-awg-to-clash.js index 3854e9e..2fee321 100644 --- a/config-sub-converter/scripts/convert-awg-to-clash.js +++ b/config-sub-converter/scripts/convert-awg-to-clash.js @@ -25,42 +25,67 @@ const AMZ_DEFAULTS = { * - ipv6=false => удалить IPv6 из allowed-ips (и вообще не добавлять ipv6-части) **********************/ function normalizeOptions(rawOptions) { + const opts = rawOptions ?? {}; - // rawOptions может быть - // 1) {} - // 2) { meta: { url: "..." } } - // 3) { url: "..." } + // попробуем найти URL в разных местах (Sub Store версии гуляют) const urlStr = - (rawOptions && rawOptions.meta && rawOptions.meta.url) || - rawOptions.url || + (typeof opts === "string" ? opts : "") || + opts.url || + (opts.meta && opts.meta.url) || + (opts.subscription && opts.subscription.url) || + (opts.profile && opts.profile.url) || + (opts.ctx && opts.ctx.url) || + (opts.request && opts.request.url) || ""; - // Ищем part после # - const hashIdx = urlStr.indexOf("#"); - const qstr = hashIdx >= 0 ? urlStr.slice(hashIdx + 1) : ""; - - const params = {}; - for (const part of qstr.split("&")) { - const [k, v] = part.split("="); - if (!k) continue; - params[k.trim().toLowerCase()] = (v ?? "").trim(); + // вытащить hash часть (#...) + let hash = ""; + if (typeof urlStr === "string") { + const idx = urlStr.indexOf("#"); + if (idx >= 0) hash = urlStr.slice(idx + 1); } + // иногда Sub Store может передать query прямо как объект + // пробуем дополнительно распарсить opts.query/opts.params, если они строки + const extra = + (typeof opts.query === "string" ? opts.query : "") || + (typeof opts.params === "string" ? opts.params : "") || + (typeof opts.hash === "string" ? opts.hash : "") || + ""; + + const qstr = (hash || extra || "").trim(); + + const params = {}; + if (qstr.includes("=")) { + for (const part of qstr.split("&")) { + if (!part) continue; + const [k, v] = part.split("="); + if (!k) continue; + params[k.trim().toLowerCase()] = (v ?? "").trim(); + } + } + + // ещё фоллбек: если opts.dns/opts.ipv6 передали напрямую + const directDns = opts.dns; + const directIpv6 = opts.ipv6; + const asBool = (v, def) => { - if (v === undefined || v === "") return def; - const s = String(v).toLowerCase(); - if (["1","true","yes","on"].includes(s)) return true; - if (["0","false","no","off"].includes(s)) return false; + if (v === undefined || v === null || v === "") return def; + if (typeof v === "boolean") return v; + const s = String(v).toLowerCase().trim(); + if (["1", "true", "yes", "y", "on"].includes(s)) return true; + if (["0", "false", "no", "n", "off"].includes(s)) return false; return def; }; return { - dns: asBool(params.dns, true), - ipv6: asBool(params.ipv6, true), + dns: asBool(params.dns ?? directDns, true), + ipv6: asBool(params.ipv6 ?? directIpv6, true), }; } + /********************** * Parsing WG INI blocks **********************/