@subconverter/core 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/dist/index.cjs +882 -505
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -22
- package/dist/index.d.ts +94 -22
- package/dist/index.js +882 -505
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -219,6 +219,16 @@ function createRulesetConfig() {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
// src/types/settings.ts
|
|
222
|
+
function parseClashFlavor(value) {
|
|
223
|
+
const normalized = (value ?? "").trim().toLowerCase();
|
|
224
|
+
if (normalized === "premium" || normalized === "original" || normalized === "classic" || normalized === "clash") {
|
|
225
|
+
return "premium";
|
|
226
|
+
}
|
|
227
|
+
if (normalized === "stash") {
|
|
228
|
+
return "stash";
|
|
229
|
+
}
|
|
230
|
+
return "mihomo";
|
|
231
|
+
}
|
|
222
232
|
var TargetFormat = /* @__PURE__ */ ((TargetFormat2) => {
|
|
223
233
|
TargetFormat2["Clash"] = "clash";
|
|
224
234
|
TargetFormat2["ClashR"] = "clashr";
|
|
@@ -247,16 +257,21 @@ function createExtraSettings() {
|
|
|
247
257
|
authorized: false,
|
|
248
258
|
autoCountry: false,
|
|
249
259
|
clashClassicalRuleset: false,
|
|
260
|
+
clashFlavor: "mihomo",
|
|
250
261
|
clashNewFieldName: true,
|
|
251
262
|
clashProxiesStyle: "flow",
|
|
252
263
|
clashProxyGroupsStyle: "flow",
|
|
253
264
|
clashScript: false,
|
|
254
|
-
countryLocale: "zh-CN",
|
|
255
265
|
countryResolver: void 0,
|
|
256
266
|
dedupe: false,
|
|
257
267
|
emojiArray: [],
|
|
258
268
|
enableRuleGenerator: true,
|
|
269
|
+
excludeCountries: [],
|
|
270
|
+
excludeRemarks: [],
|
|
271
|
+
expandRulesets: true,
|
|
259
272
|
filterDeprecated: false,
|
|
273
|
+
includeCountries: [],
|
|
274
|
+
includeRemarks: [],
|
|
260
275
|
managedConfigPrefix: "",
|
|
261
276
|
nameRegexArray: [],
|
|
262
277
|
nameRemove: [],
|
|
@@ -269,6 +284,7 @@ function createExtraSettings() {
|
|
|
269
284
|
sortFlag: false,
|
|
270
285
|
sortScript: "",
|
|
271
286
|
surgeSsrPath: "",
|
|
287
|
+
templateVars: {},
|
|
272
288
|
tfo: void 0,
|
|
273
289
|
tls13: void 0,
|
|
274
290
|
udp: void 0
|
|
@@ -492,7 +508,7 @@ function toBool(value) {
|
|
|
492
508
|
return false;
|
|
493
509
|
}
|
|
494
510
|
const normalized = value.trim().toLowerCase();
|
|
495
|
-
return normalized === "true" || normalized === "1";
|
|
511
|
+
return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on";
|
|
496
512
|
}
|
|
497
513
|
function strFind(haystack, needle) {
|
|
498
514
|
return haystack.includes(needle);
|
|
@@ -641,6 +657,23 @@ function templateVariableNames(content) {
|
|
|
641
657
|
}
|
|
642
658
|
|
|
643
659
|
// src/settings/config.ts
|
|
660
|
+
var RULESET_TYPE_PREFIXES = [
|
|
661
|
+
["surge:", "surge" /* Surge */],
|
|
662
|
+
["quanx:", "quanx" /* QuantumultX */],
|
|
663
|
+
["quantumultx:", "quanx" /* QuantumultX */],
|
|
664
|
+
["clash-domain:", "clash-domain" /* ClashDomain */],
|
|
665
|
+
["clash-ipcidr:", "clash-ipcidr" /* ClashIpCidr */],
|
|
666
|
+
["clash-classic:", "clash-classical" /* ClashClassical */],
|
|
667
|
+
["clash:", "clash-classical" /* ClashClassical */]
|
|
668
|
+
];
|
|
669
|
+
function parseRulesetSource(source) {
|
|
670
|
+
for (const [prefix, type] of RULESET_TYPE_PREFIXES) {
|
|
671
|
+
if (source.toLowerCase().startsWith(prefix)) {
|
|
672
|
+
return { type, url: source.slice(prefix.length) };
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return { url: source };
|
|
676
|
+
}
|
|
644
677
|
var GROUP_TYPE_MAP = {
|
|
645
678
|
fallback: "fallback" /* Fallback */,
|
|
646
679
|
"load-balance": "load-balance" /* LoadBalance */,
|
|
@@ -742,8 +775,10 @@ function parseExternalConfig(content) {
|
|
|
742
775
|
baseFiles: {},
|
|
743
776
|
emoji: [],
|
|
744
777
|
enableRuleGenerator: true,
|
|
778
|
+
excludeCountries: [],
|
|
745
779
|
excludeRemarks: [],
|
|
746
780
|
groups: [],
|
|
781
|
+
includeCountries: [],
|
|
747
782
|
includeRemarks: [],
|
|
748
783
|
nameRegex: [],
|
|
749
784
|
nameRemove: [],
|
|
@@ -812,6 +847,22 @@ function parseExternalConfig(content) {
|
|
|
812
847
|
result.includeRemarks.push(value);
|
|
813
848
|
}
|
|
814
849
|
break;
|
|
850
|
+
case "include_country":
|
|
851
|
+
for (const fragment of value.split(",")) {
|
|
852
|
+
const trimmed = fragment.trim().toUpperCase();
|
|
853
|
+
if (trimmed !== "") {
|
|
854
|
+
result.includeCountries.push(trimmed);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
break;
|
|
858
|
+
case "exclude_country":
|
|
859
|
+
for (const fragment of value.split(",")) {
|
|
860
|
+
const trimmed = fragment.trim().toUpperCase();
|
|
861
|
+
if (trimmed !== "") {
|
|
862
|
+
result.excludeCountries.push(trimmed);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
break;
|
|
815
866
|
case "exclude_remarks":
|
|
816
867
|
case "exclude":
|
|
817
868
|
if (value !== "") {
|
|
@@ -866,6 +917,9 @@ function listArg(query, key) {
|
|
|
866
917
|
const value = getUrlArg(query, key);
|
|
867
918
|
return value === "" ? [] : value.split(",");
|
|
868
919
|
}
|
|
920
|
+
function countryListArg(query, key) {
|
|
921
|
+
return getAllUrlArgs(query, key).flatMap((raw) => raw.split(",")).map((raw) => raw.trim().toUpperCase()).filter((raw) => raw !== "");
|
|
922
|
+
}
|
|
869
923
|
function resolveNewFieldName(query) {
|
|
870
924
|
if (boolArg(query, "legacy") || boolArg(query, "legacy_field_name") || boolArg(query, "legacy-field-name")) {
|
|
871
925
|
return false;
|
|
@@ -904,13 +958,19 @@ function createRequestSettings() {
|
|
|
904
958
|
appendType: false,
|
|
905
959
|
autoCountry: false,
|
|
906
960
|
autoExtract: false,
|
|
961
|
+
clashFlavor: "mihomo",
|
|
907
962
|
clashScript: false,
|
|
908
963
|
classicalRuleset: false,
|
|
909
964
|
dedupe: false,
|
|
965
|
+
devId: "",
|
|
910
966
|
emoji: [],
|
|
967
|
+
excludeCountries: [],
|
|
911
968
|
excludeRemarks: [],
|
|
969
|
+
expand: true,
|
|
970
|
+
filename: "",
|
|
912
971
|
filterDeprecated: false,
|
|
913
972
|
group: [],
|
|
973
|
+
includeCountries: [],
|
|
914
974
|
includeRemarks: [],
|
|
915
975
|
insert: false,
|
|
916
976
|
interval: 0,
|
|
@@ -928,6 +988,7 @@ function createRequestSettings() {
|
|
|
928
988
|
script: "",
|
|
929
989
|
scv: void 0,
|
|
930
990
|
sort: false,
|
|
991
|
+
strict: false,
|
|
931
992
|
target: "auto" /* Auto */,
|
|
932
993
|
tfo: void 0,
|
|
933
994
|
tls13: void 0,
|
|
@@ -956,6 +1017,11 @@ function parseRequestSettings(query) {
|
|
|
956
1017
|
settings.filterDeprecated = boolArg(query, "filter_deprecated");
|
|
957
1018
|
settings.newFieldName = resolveNewFieldName(query);
|
|
958
1019
|
settings.classicalRuleset = boolArg(query, "classical");
|
|
1020
|
+
settings.clashFlavor = parseClashFlavor(firstArg(query, "flavor"));
|
|
1021
|
+
settings.expand = queryBoolFlag(query, "expand") ?? true;
|
|
1022
|
+
settings.strict = boolArg(query, "strict");
|
|
1023
|
+
settings.filename = firstArg(query, "filename");
|
|
1024
|
+
settings.devId = firstArg(query, "dev_id", "dev-id", "device_id", "device-id");
|
|
959
1025
|
settings.insert = getUrlArg(query, "insert") !== "";
|
|
960
1026
|
settings.clashScript = boolArg(query, "clash_script");
|
|
961
1027
|
settings.autoExtract = boolArg(query, "auto_extract");
|
|
@@ -971,6 +1037,8 @@ function parseRequestSettings(query) {
|
|
|
971
1037
|
settings.proxyGroupsStyle = getUrlArg(query, "proxy_groups_style") || "flow";
|
|
972
1038
|
settings.includeRemarks = listArg(query, "include");
|
|
973
1039
|
settings.excludeRemarks = listArg(query, "exclude");
|
|
1040
|
+
settings.includeCountries = countryListArg(query, "include_country");
|
|
1041
|
+
settings.excludeCountries = countryListArg(query, "exclude_country");
|
|
974
1042
|
settings.userinfoUrl = firstArg(query, "userinfo_url", "userinfo-url", "userinfo");
|
|
975
1043
|
settings.userinfoProvider = firstArg(
|
|
976
1044
|
query,
|
|
@@ -1846,485 +1914,493 @@ function explodeClash(root, nodes) {
|
|
|
1846
1914
|
}
|
|
1847
1915
|
let index = nodes.length;
|
|
1848
1916
|
for (const single of list) {
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
const port = asString(get(single, "port"));
|
|
1853
|
-
let underlyingProxy = asString(get(single, "underlying-proxy"));
|
|
1854
|
-
if (underlyingProxy === "") {
|
|
1855
|
-
underlyingProxy = asString(get(single, "dialer-proxy"));
|
|
1856
|
-
}
|
|
1857
|
-
if (port === "" || port === "0") {
|
|
1858
|
-
continue;
|
|
1859
|
-
}
|
|
1860
|
-
const udp = asTri(get(single, "udp"));
|
|
1861
|
-
const tfo = asTri(get(single, "fast-open"));
|
|
1862
|
-
const scv = asTri(get(single, "skip-cert-verify"));
|
|
1863
|
-
const node = createProxy();
|
|
1864
|
-
let group2 = "";
|
|
1865
|
-
switch (proxyType) {
|
|
1866
|
-
case "vmess": {
|
|
1867
|
-
group2 = DEFAULT_GROUPS.v2ray;
|
|
1868
|
-
const id = asString(get(single, "uuid"));
|
|
1869
|
-
const aid = asString(get(single, "alterId"));
|
|
1870
|
-
const cipher = asString(get(single, "cipher"));
|
|
1871
|
-
const net = get(single, "network") !== void 0 ? asString(get(single, "network")) : "tcp";
|
|
1872
|
-
const sni = asString(get(single, "servername"));
|
|
1873
|
-
let path = "";
|
|
1874
|
-
let host = "";
|
|
1875
|
-
let edge = "";
|
|
1876
|
-
switch (net) {
|
|
1877
|
-
case "http":
|
|
1878
|
-
path = asString(get(get(get(single, "http-opts"), "path"), 0));
|
|
1879
|
-
host = asString(get(get(get(get(single, "http-opts"), "headers"), "Host"), 0));
|
|
1880
|
-
edge = "";
|
|
1881
|
-
break;
|
|
1882
|
-
case "ws":
|
|
1883
|
-
if (get(single, "ws-opts") !== void 0) {
|
|
1884
|
-
const wsOpts = get(single, "ws-opts");
|
|
1885
|
-
path = get(wsOpts, "path") !== void 0 ? asString(get(wsOpts, "path")) : "/";
|
|
1886
|
-
host = asString(get(get(wsOpts, "headers"), "Host"));
|
|
1887
|
-
edge = asString(get(get(wsOpts, "headers"), "Edge"));
|
|
1888
|
-
} else {
|
|
1889
|
-
path = get(single, "ws-path") !== void 0 ? asString(get(single, "ws-path")) : "/";
|
|
1890
|
-
host = asString(get(get(single, "ws-headers"), "Host"));
|
|
1891
|
-
edge = asString(get(get(single, "ws-headers"), "Edge"));
|
|
1892
|
-
}
|
|
1893
|
-
break;
|
|
1894
|
-
case "h2":
|
|
1895
|
-
path = asString(get(get(single, "h2-opts"), "path"));
|
|
1896
|
-
host = asString(get(get(get(single, "h2-opts"), "host"), 0));
|
|
1897
|
-
edge = "";
|
|
1898
|
-
break;
|
|
1899
|
-
case "grpc":
|
|
1900
|
-
host = asString(get(single, "servername"));
|
|
1901
|
-
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
1902
|
-
edge = "";
|
|
1903
|
-
break;
|
|
1904
|
-
default:
|
|
1905
|
-
break;
|
|
1906
|
-
}
|
|
1907
|
-
const tls = asBool(get(single, "tls")) ? "tls" : "";
|
|
1908
|
-
vmessConstruct(node, {
|
|
1909
|
-
add: server,
|
|
1910
|
-
aid,
|
|
1911
|
-
cipher,
|
|
1912
|
-
edge,
|
|
1913
|
-
group: group2,
|
|
1914
|
-
host,
|
|
1915
|
-
id,
|
|
1916
|
-
net,
|
|
1917
|
-
path,
|
|
1918
|
-
port,
|
|
1919
|
-
remark: ps,
|
|
1920
|
-
scv,
|
|
1921
|
-
sni,
|
|
1922
|
-
tfo,
|
|
1923
|
-
tls,
|
|
1924
|
-
type: "",
|
|
1925
|
-
udp,
|
|
1926
|
-
underlyingProxy
|
|
1927
|
-
});
|
|
1928
|
-
break;
|
|
1917
|
+
try {
|
|
1918
|
+
if (parseClashNode(single, nodes, index)) {
|
|
1919
|
+
index += 1;
|
|
1929
1920
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
if (
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1921
|
+
} catch {
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
function parseClashNode(single, nodes, index) {
|
|
1926
|
+
const proxyType = asString(get(single, "type")).toLowerCase();
|
|
1927
|
+
const ps = asString(get(single, "name"));
|
|
1928
|
+
const server = asString(get(single, "server"));
|
|
1929
|
+
const port = asString(get(single, "port"));
|
|
1930
|
+
let underlyingProxy = asString(get(single, "underlying-proxy"));
|
|
1931
|
+
if (underlyingProxy === "") {
|
|
1932
|
+
underlyingProxy = asString(get(single, "dialer-proxy"));
|
|
1933
|
+
}
|
|
1934
|
+
if (port === "" || port === "0") {
|
|
1935
|
+
return false;
|
|
1936
|
+
}
|
|
1937
|
+
const udp = asTri(get(single, "udp"));
|
|
1938
|
+
const tfo = asTri(get(single, "fast-open"));
|
|
1939
|
+
const scv = asTri(get(single, "skip-cert-verify"));
|
|
1940
|
+
const node = createProxy();
|
|
1941
|
+
let group2 = "";
|
|
1942
|
+
switch (proxyType) {
|
|
1943
|
+
case "vmess": {
|
|
1944
|
+
group2 = DEFAULT_GROUPS.v2ray;
|
|
1945
|
+
const id = asString(get(single, "uuid"));
|
|
1946
|
+
const aid = asString(get(single, "alterId"));
|
|
1947
|
+
const cipher = asString(get(single, "cipher"));
|
|
1948
|
+
const net = get(single, "network") !== void 0 ? asString(get(single, "network")) : "tcp";
|
|
1949
|
+
const sni = asString(get(single, "servername"));
|
|
1950
|
+
let path = "";
|
|
1951
|
+
let host = "";
|
|
1952
|
+
let edge = "";
|
|
1953
|
+
switch (net) {
|
|
1954
|
+
case "http":
|
|
1955
|
+
path = asString(get(get(get(single, "http-opts"), "path"), 0));
|
|
1956
|
+
host = asString(get(get(get(get(single, "http-opts"), "headers"), "Host"), 0));
|
|
1957
|
+
edge = "";
|
|
1958
|
+
break;
|
|
1959
|
+
case "ws":
|
|
1960
|
+
if (get(single, "ws-opts") !== void 0) {
|
|
1961
|
+
const wsOpts = get(single, "ws-opts");
|
|
1962
|
+
path = get(wsOpts, "path") !== void 0 ? asString(get(wsOpts, "path")) : "/";
|
|
1963
|
+
host = asString(get(get(wsOpts, "headers"), "Host"));
|
|
1964
|
+
edge = asString(get(get(wsOpts, "headers"), "Edge"));
|
|
1965
|
+
} else {
|
|
1966
|
+
path = get(single, "ws-path") !== void 0 ? asString(get(single, "ws-path")) : "/";
|
|
1967
|
+
host = asString(get(get(single, "ws-headers"), "Host"));
|
|
1968
|
+
edge = asString(get(get(single, "ws-headers"), "Edge"));
|
|
1974
1969
|
}
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
remark: ps,
|
|
1989
|
-
scv,
|
|
1990
|
-
server,
|
|
1991
|
-
tfo,
|
|
1992
|
-
udp,
|
|
1993
|
-
underlyingProxy
|
|
1994
|
-
});
|
|
1995
|
-
break;
|
|
1996
|
-
}
|
|
1997
|
-
case "socks5": {
|
|
1998
|
-
group2 = DEFAULT_GROUPS.socks;
|
|
1999
|
-
const user = asString(get(single, "username"));
|
|
2000
|
-
const password = asString(get(single, "password"));
|
|
2001
|
-
socksConstruct(node, {
|
|
2002
|
-
group: group2,
|
|
2003
|
-
password,
|
|
2004
|
-
port,
|
|
2005
|
-
remark: ps,
|
|
2006
|
-
server,
|
|
2007
|
-
underlyingProxy,
|
|
2008
|
-
username: user
|
|
2009
|
-
});
|
|
2010
|
-
break;
|
|
2011
|
-
}
|
|
2012
|
-
case "ssr": {
|
|
2013
|
-
group2 = DEFAULT_GROUPS.ssr;
|
|
2014
|
-
let cipher = asString(get(single, "cipher"));
|
|
2015
|
-
if (cipher === "dummy") {
|
|
2016
|
-
cipher = "none";
|
|
2017
|
-
}
|
|
2018
|
-
const password = asString(get(single, "password"));
|
|
2019
|
-
const protocol = asString(get(single, "protocol"));
|
|
2020
|
-
const obfs = asString(get(single, "obfs"));
|
|
2021
|
-
const protocolParam = get(single, "protocol-param") !== void 0 ? asString(get(single, "protocol-param")) : asString(get(single, "protocolparam"));
|
|
2022
|
-
const obfsParam = get(single, "obfs-param") !== void 0 ? asString(get(single, "obfs-param")) : asString(get(single, "obfsparam"));
|
|
2023
|
-
ssrConstruct(node, {
|
|
2024
|
-
group: group2,
|
|
2025
|
-
method: cipher,
|
|
2026
|
-
obfs,
|
|
2027
|
-
obfsParam,
|
|
2028
|
-
password,
|
|
2029
|
-
port,
|
|
2030
|
-
protocol,
|
|
2031
|
-
protocolParam,
|
|
2032
|
-
remark: ps,
|
|
2033
|
-
scv,
|
|
2034
|
-
server,
|
|
2035
|
-
tfo,
|
|
2036
|
-
udp,
|
|
2037
|
-
underlyingProxy
|
|
2038
|
-
});
|
|
2039
|
-
break;
|
|
2040
|
-
}
|
|
2041
|
-
case "http": {
|
|
2042
|
-
group2 = DEFAULT_GROUPS.http;
|
|
2043
|
-
const user = asString(get(single, "username"));
|
|
2044
|
-
const password = asString(get(single, "password"));
|
|
2045
|
-
const tls = asString(get(single, "tls"));
|
|
2046
|
-
httpConstruct(node, {
|
|
2047
|
-
group: group2,
|
|
2048
|
-
password,
|
|
2049
|
-
port,
|
|
2050
|
-
remark: ps,
|
|
2051
|
-
scv,
|
|
2052
|
-
server,
|
|
2053
|
-
tfo,
|
|
2054
|
-
tls: tls === "true",
|
|
2055
|
-
underlyingProxy,
|
|
2056
|
-
username: user
|
|
2057
|
-
});
|
|
2058
|
-
break;
|
|
1970
|
+
break;
|
|
1971
|
+
case "h2":
|
|
1972
|
+
path = asString(get(get(single, "h2-opts"), "path"));
|
|
1973
|
+
host = asString(get(get(get(single, "h2-opts"), "host"), 0));
|
|
1974
|
+
edge = "";
|
|
1975
|
+
break;
|
|
1976
|
+
case "grpc":
|
|
1977
|
+
host = asString(get(single, "servername"));
|
|
1978
|
+
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
1979
|
+
edge = "";
|
|
1980
|
+
break;
|
|
1981
|
+
default:
|
|
1982
|
+
break;
|
|
2059
1983
|
}
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
1984
|
+
const tls = asBool(get(single, "tls")) ? "tls" : "";
|
|
1985
|
+
vmessConstruct(node, {
|
|
1986
|
+
add: server,
|
|
1987
|
+
aid,
|
|
1988
|
+
cipher,
|
|
1989
|
+
edge,
|
|
1990
|
+
group: group2,
|
|
1991
|
+
host,
|
|
1992
|
+
id,
|
|
1993
|
+
net,
|
|
1994
|
+
path,
|
|
1995
|
+
port,
|
|
1996
|
+
remark: ps,
|
|
1997
|
+
scv,
|
|
1998
|
+
sni,
|
|
1999
|
+
tfo,
|
|
2000
|
+
tls,
|
|
2001
|
+
type: "",
|
|
2002
|
+
udp,
|
|
2003
|
+
underlyingProxy
|
|
2004
|
+
});
|
|
2005
|
+
break;
|
|
2006
|
+
}
|
|
2007
|
+
case "ss": {
|
|
2008
|
+
group2 = DEFAULT_GROUPS.ss;
|
|
2009
|
+
let cipher = asString(get(single, "cipher"));
|
|
2010
|
+
const password = asString(get(single, "password"));
|
|
2011
|
+
let plugin = "";
|
|
2012
|
+
let pluginOption = "";
|
|
2013
|
+
let pluginMode = "";
|
|
2014
|
+
let pluginHost = "";
|
|
2015
|
+
let pluginMux = "";
|
|
2016
|
+
let pluginTls = "";
|
|
2017
|
+
let path = "";
|
|
2018
|
+
if (get(single, "plugin") !== void 0) {
|
|
2019
|
+
const pluginName = asString(get(single, "plugin")).toLowerCase();
|
|
2020
|
+
const pluginOpts = get(single, "plugin-opts");
|
|
2021
|
+
if (pluginName === "obfs") {
|
|
2022
|
+
plugin = "obfs-local";
|
|
2023
|
+
pluginMode = asString(get(pluginOpts, "mode"));
|
|
2024
|
+
pluginHost = asString(get(pluginOpts, "host"));
|
|
2025
|
+
} else if (pluginName === "v2ray-plugin") {
|
|
2026
|
+
plugin = "v2ray-plugin";
|
|
2027
|
+
pluginMode = asString(get(pluginOpts, "mode"));
|
|
2028
|
+
pluginHost = asString(get(pluginOpts, "host"));
|
|
2029
|
+
pluginTls = asBool(get(pluginOpts, "tls")) ? "tls;" : "";
|
|
2030
|
+
path = asString(get(pluginOpts, "path"));
|
|
2031
|
+
pluginMux = asBool(get(pluginOpts, "mux")) ? "mux=4;" : "";
|
|
2077
2032
|
}
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
udp,
|
|
2091
|
-
underlyingProxy
|
|
2092
|
-
});
|
|
2093
|
-
break;
|
|
2094
|
-
}
|
|
2095
|
-
case "snell": {
|
|
2096
|
-
group2 = DEFAULT_GROUPS.snell;
|
|
2097
|
-
const password = asString(get(single, "psk"));
|
|
2098
|
-
const obfs = asString(get(get(single, "obfs-opts"), "mode"));
|
|
2099
|
-
const host = asString(get(get(single, "obfs-opts"), "host"));
|
|
2100
|
-
const version = asString(get(single, "version"));
|
|
2101
|
-
snellConstruct(node, {
|
|
2102
|
-
group: group2,
|
|
2103
|
-
host,
|
|
2104
|
-
obfs,
|
|
2105
|
-
password,
|
|
2106
|
-
port,
|
|
2107
|
-
remark: ps,
|
|
2108
|
-
scv,
|
|
2109
|
-
server,
|
|
2110
|
-
tfo,
|
|
2111
|
-
udp,
|
|
2112
|
-
underlyingProxy,
|
|
2113
|
-
version: toInt(version)
|
|
2114
|
-
});
|
|
2115
|
-
break;
|
|
2116
|
-
}
|
|
2117
|
-
case "wireguard": {
|
|
2118
|
-
group2 = DEFAULT_GROUPS.wireguard;
|
|
2119
|
-
const publicKey = asString(get(single, "public-key"));
|
|
2120
|
-
const privateKey = asString(get(single, "private-key"));
|
|
2121
|
-
const dns = get(single, "dns");
|
|
2122
|
-
const dnsServers = Array.isArray(dns) ? dns.map((d) => String(d)) : dns ? [String(dns)] : [];
|
|
2123
|
-
const mtu = asString(get(single, "mtu"));
|
|
2124
|
-
const psk = asString(get(single, "preshared-key"));
|
|
2125
|
-
const ip = asString(get(single, "ip"));
|
|
2126
|
-
const ipv6 = asString(get(single, "ipv6"));
|
|
2127
|
-
wireGuardConstruct(node, {
|
|
2128
|
-
dnsServers,
|
|
2129
|
-
group: group2,
|
|
2130
|
-
keepAlive: "0",
|
|
2131
|
-
mtu,
|
|
2132
|
-
port,
|
|
2133
|
-
preSharedKey: psk,
|
|
2134
|
-
privateKey,
|
|
2135
|
-
publicKey,
|
|
2136
|
-
remark: ps,
|
|
2137
|
-
selfIp: ip,
|
|
2138
|
-
selfIpv6: ipv6,
|
|
2139
|
-
server,
|
|
2140
|
-
testUrl: "",
|
|
2141
|
-
udp,
|
|
2142
|
-
underlyingProxy
|
|
2143
|
-
});
|
|
2144
|
-
break;
|
|
2145
|
-
}
|
|
2146
|
-
case "hysteria": {
|
|
2147
|
-
group2 = DEFAULT_GROUPS.hysteria;
|
|
2148
|
-
const ports = asString(get(single, "ports"));
|
|
2149
|
-
const protocol = asString(get(single, "protocol"));
|
|
2150
|
-
const obfsProtocol = asString(get(single, "obfs-protocol"));
|
|
2151
|
-
const up = asString(get(single, "up"));
|
|
2152
|
-
const upSpeed = asString(get(single, "up-speed"));
|
|
2153
|
-
const down = asString(get(single, "down"));
|
|
2154
|
-
const downSpeed = asString(get(single, "down-speed"));
|
|
2155
|
-
const auth = asString(get(single, "auth"));
|
|
2156
|
-
let authStr = asString(get(single, "auth-str"));
|
|
2157
|
-
if (authStr === "") {
|
|
2158
|
-
authStr = asString(get(single, "auth_str"));
|
|
2033
|
+
} else if (get(single, "obfs") !== void 0) {
|
|
2034
|
+
plugin = "obfs-local";
|
|
2035
|
+
pluginMode = asString(get(single, "obfs"));
|
|
2036
|
+
pluginHost = asString(get(single, "obfs-host"));
|
|
2037
|
+
}
|
|
2038
|
+
if (plugin === "simple-obfs" || plugin === "obfs-local") {
|
|
2039
|
+
pluginOption = `obfs=${pluginMode}`;
|
|
2040
|
+
pluginOption += pluginHost === "" ? "" : `;obfs-host=${pluginHost}`;
|
|
2041
|
+
} else if (plugin === "v2ray-plugin") {
|
|
2042
|
+
pluginOption = `mode=${pluginMode};${pluginTls}${pluginMux}`;
|
|
2043
|
+
if (pluginHost !== "") {
|
|
2044
|
+
pluginOption += `host=${pluginHost};`;
|
|
2159
2045
|
}
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
const fingerprint = asString(get(single, "fingerprint"));
|
|
2163
|
-
const alpnValue = get(single, "alpn");
|
|
2164
|
-
const alpn = Array.isArray(alpnValue) ? asString(alpnValue[0]) : asString(alpnValue);
|
|
2165
|
-
const ca = asString(get(single, "ca"));
|
|
2166
|
-
const caStr = asString(get(single, "ca-str"));
|
|
2167
|
-
const recvWindowConn = asString(get(single, "recv-window-conn"));
|
|
2168
|
-
const recvWindow = asString(get(single, "recv-window"));
|
|
2169
|
-
let disableMtuDiscovery = asString(get(single, "disable-mtu-discovery"));
|
|
2170
|
-
if (disableMtuDiscovery === "") {
|
|
2171
|
-
disableMtuDiscovery = asString(get(single, "disable_mtu_discovery"));
|
|
2046
|
+
if (path !== "") {
|
|
2047
|
+
pluginOption += `path=${path};`;
|
|
2172
2048
|
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
alpn,
|
|
2176
|
-
auth,
|
|
2177
|
-
authStr,
|
|
2178
|
-
ca,
|
|
2179
|
-
caStr,
|
|
2180
|
-
disableMtuDiscovery,
|
|
2181
|
-
down,
|
|
2182
|
-
downSpeed,
|
|
2183
|
-
fingerprint,
|
|
2184
|
-
group: group2,
|
|
2185
|
-
hopInterval,
|
|
2186
|
-
obfs,
|
|
2187
|
-
obfsProtocol,
|
|
2188
|
-
port,
|
|
2189
|
-
ports,
|
|
2190
|
-
protocol,
|
|
2191
|
-
recvWindow,
|
|
2192
|
-
recvWindowConn,
|
|
2193
|
-
remark: ps,
|
|
2194
|
-
scv,
|
|
2195
|
-
server,
|
|
2196
|
-
sni,
|
|
2197
|
-
tfo,
|
|
2198
|
-
underlyingProxy,
|
|
2199
|
-
up,
|
|
2200
|
-
upSpeed
|
|
2201
|
-
});
|
|
2202
|
-
break;
|
|
2203
|
-
}
|
|
2204
|
-
case "hysteria2": {
|
|
2205
|
-
group2 = DEFAULT_GROUPS.hysteria2;
|
|
2206
|
-
const ports = asString(get(single, "ports"));
|
|
2207
|
-
const up = asString(get(single, "up"));
|
|
2208
|
-
const down = asString(get(single, "down"));
|
|
2209
|
-
let password = asString(get(single, "password"));
|
|
2210
|
-
if (password === "") {
|
|
2211
|
-
password = asString(get(single, "auth"));
|
|
2049
|
+
if (pluginMux !== "") {
|
|
2050
|
+
pluginOption += `mux=${pluginMux};`;
|
|
2212
2051
|
}
|
|
2213
|
-
const obfs = asString(get(single, "obfs"));
|
|
2214
|
-
const obfsPassword = asString(get(single, "obfs-password"));
|
|
2215
|
-
const sni = asString(get(single, "sni"));
|
|
2216
|
-
const fingerprint = asString(get(single, "fingerprint"));
|
|
2217
|
-
const alpnValue = get(single, "alpn");
|
|
2218
|
-
const alpn = Array.isArray(alpnValue) ? asString(alpnValue[0]) : asString(alpnValue);
|
|
2219
|
-
const ca = asString(get(single, "ca"));
|
|
2220
|
-
const caStr = asString(get(single, "ca-str"));
|
|
2221
|
-
const cwnd = asString(get(single, "cwnd"));
|
|
2222
|
-
const hopInterval = asString(get(single, "hop-interval"));
|
|
2223
|
-
hysteria2Construct(node, {
|
|
2224
|
-
alpn,
|
|
2225
|
-
ca,
|
|
2226
|
-
caStr,
|
|
2227
|
-
cwnd,
|
|
2228
|
-
down,
|
|
2229
|
-
fingerprint,
|
|
2230
|
-
group: group2,
|
|
2231
|
-
hopInterval,
|
|
2232
|
-
obfs,
|
|
2233
|
-
obfsPassword,
|
|
2234
|
-
password,
|
|
2235
|
-
port,
|
|
2236
|
-
ports,
|
|
2237
|
-
remark: ps,
|
|
2238
|
-
scv,
|
|
2239
|
-
server,
|
|
2240
|
-
sni,
|
|
2241
|
-
tfo,
|
|
2242
|
-
underlyingProxy,
|
|
2243
|
-
up
|
|
2244
|
-
});
|
|
2245
|
-
break;
|
|
2246
|
-
}
|
|
2247
|
-
case "anytls": {
|
|
2248
|
-
group2 = DEFAULT_GROUPS.anytls;
|
|
2249
|
-
const password = asString(get(single, "password"));
|
|
2250
|
-
const sni = asString(get(single, "sni"));
|
|
2251
|
-
anyTlsConstruct(node, {
|
|
2252
|
-
group: group2,
|
|
2253
|
-
password,
|
|
2254
|
-
port,
|
|
2255
|
-
remark: ps,
|
|
2256
|
-
scv,
|
|
2257
|
-
server,
|
|
2258
|
-
sni,
|
|
2259
|
-
tfo,
|
|
2260
|
-
udp,
|
|
2261
|
-
underlyingProxy
|
|
2262
|
-
});
|
|
2263
|
-
break;
|
|
2264
2052
|
}
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
const tls = asString(get(single, "tls"));
|
|
2270
|
-
let path = "";
|
|
2271
|
-
let host = "";
|
|
2272
|
-
if (net === "ws") {
|
|
2273
|
-
path = asString(get(get(single, "ws-opts"), "path"));
|
|
2274
|
-
host = asString(get(get(get(single, "ws-opts"), "headers"), "Host"));
|
|
2275
|
-
} else if (net === "grpc") {
|
|
2276
|
-
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
2277
|
-
}
|
|
2278
|
-
const alpnValue = get(single, "alpn");
|
|
2279
|
-
vlessConstruct(node, {
|
|
2280
|
-
alpn: Array.isArray(alpnValue) ? alpnValue.map((a) => String(a)) : void 0,
|
|
2281
|
-
encryption: asString(get(single, "encryption")),
|
|
2282
|
-
fingerprint: asString(get(single, "client-fingerprint")),
|
|
2283
|
-
flow: asString(get(single, "flow")),
|
|
2284
|
-
group: group2,
|
|
2285
|
-
host,
|
|
2286
|
-
network: net,
|
|
2287
|
-
path,
|
|
2288
|
-
port,
|
|
2289
|
-
remark: ps,
|
|
2290
|
-
scv,
|
|
2291
|
-
server,
|
|
2292
|
-
sni: asString(get(single, "servername")),
|
|
2293
|
-
tfo,
|
|
2294
|
-
tls: tls === "true" ? "tls" : "",
|
|
2295
|
-
udp,
|
|
2296
|
-
underlyingProxy,
|
|
2297
|
-
userId
|
|
2298
|
-
});
|
|
2299
|
-
break;
|
|
2053
|
+
if (cipher === "AEAD_CHACHA20_POLY1305") {
|
|
2054
|
+
cipher = "chacha20-ietf-poly1305";
|
|
2055
|
+
} else if (cipher.includes("AEAD")) {
|
|
2056
|
+
cipher = cipher.replace(/AEAD_/g, "").replace(/_/g, "-").toLowerCase();
|
|
2300
2057
|
}
|
|
2301
|
-
|
|
2302
|
-
group2
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2058
|
+
ssConstruct(node, {
|
|
2059
|
+
group: group2,
|
|
2060
|
+
method: cipher,
|
|
2061
|
+
password,
|
|
2062
|
+
plugin,
|
|
2063
|
+
pluginOption,
|
|
2064
|
+
port,
|
|
2065
|
+
remark: ps,
|
|
2066
|
+
scv,
|
|
2067
|
+
server,
|
|
2068
|
+
tfo,
|
|
2069
|
+
udp,
|
|
2070
|
+
underlyingProxy
|
|
2071
|
+
});
|
|
2072
|
+
break;
|
|
2073
|
+
}
|
|
2074
|
+
case "socks5": {
|
|
2075
|
+
group2 = DEFAULT_GROUPS.socks;
|
|
2076
|
+
const user = asString(get(single, "username"));
|
|
2077
|
+
const password = asString(get(single, "password"));
|
|
2078
|
+
socksConstruct(node, {
|
|
2079
|
+
group: group2,
|
|
2080
|
+
password,
|
|
2081
|
+
port,
|
|
2082
|
+
remark: ps,
|
|
2083
|
+
server,
|
|
2084
|
+
underlyingProxy,
|
|
2085
|
+
username: user
|
|
2086
|
+
});
|
|
2087
|
+
break;
|
|
2088
|
+
}
|
|
2089
|
+
case "ssr": {
|
|
2090
|
+
group2 = DEFAULT_GROUPS.ssr;
|
|
2091
|
+
let cipher = asString(get(single, "cipher"));
|
|
2092
|
+
if (cipher === "dummy") {
|
|
2093
|
+
cipher = "none";
|
|
2094
|
+
}
|
|
2095
|
+
const password = asString(get(single, "password"));
|
|
2096
|
+
const protocol = asString(get(single, "protocol"));
|
|
2097
|
+
const obfs = asString(get(single, "obfs"));
|
|
2098
|
+
const protocolParam = get(single, "protocol-param") !== void 0 ? asString(get(single, "protocol-param")) : asString(get(single, "protocolparam"));
|
|
2099
|
+
const obfsParam = get(single, "obfs-param") !== void 0 ? asString(get(single, "obfs-param")) : asString(get(single, "obfsparam"));
|
|
2100
|
+
ssrConstruct(node, {
|
|
2101
|
+
group: group2,
|
|
2102
|
+
method: cipher,
|
|
2103
|
+
obfs,
|
|
2104
|
+
obfsParam,
|
|
2105
|
+
password,
|
|
2106
|
+
port,
|
|
2107
|
+
protocol,
|
|
2108
|
+
protocolParam,
|
|
2109
|
+
remark: ps,
|
|
2110
|
+
scv,
|
|
2111
|
+
server,
|
|
2112
|
+
tfo,
|
|
2113
|
+
udp,
|
|
2114
|
+
underlyingProxy
|
|
2115
|
+
});
|
|
2116
|
+
break;
|
|
2117
|
+
}
|
|
2118
|
+
case "http": {
|
|
2119
|
+
group2 = DEFAULT_GROUPS.http;
|
|
2120
|
+
const user = asString(get(single, "username"));
|
|
2121
|
+
const password = asString(get(single, "password"));
|
|
2122
|
+
const tls = asString(get(single, "tls"));
|
|
2123
|
+
httpConstruct(node, {
|
|
2124
|
+
group: group2,
|
|
2125
|
+
password,
|
|
2126
|
+
port,
|
|
2127
|
+
remark: ps,
|
|
2128
|
+
scv,
|
|
2129
|
+
server,
|
|
2130
|
+
tfo,
|
|
2131
|
+
tls: tls === "true",
|
|
2132
|
+
underlyingProxy,
|
|
2133
|
+
username: user
|
|
2134
|
+
});
|
|
2135
|
+
break;
|
|
2136
|
+
}
|
|
2137
|
+
case "trojan": {
|
|
2138
|
+
group2 = DEFAULT_GROUPS.trojan;
|
|
2139
|
+
const password = asString(get(single, "password"));
|
|
2140
|
+
const host = asString(get(single, "sni"));
|
|
2141
|
+
let net = asString(get(single, "network"));
|
|
2142
|
+
let path = "";
|
|
2143
|
+
switch (net) {
|
|
2144
|
+
case "grpc":
|
|
2145
|
+
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
2146
|
+
break;
|
|
2147
|
+
case "ws":
|
|
2148
|
+
path = asString(get(get(single, "ws-opts"), "path"));
|
|
2149
|
+
break;
|
|
2150
|
+
default:
|
|
2151
|
+
net = "tcp";
|
|
2152
|
+
path = "";
|
|
2153
|
+
break;
|
|
2320
2154
|
}
|
|
2321
|
-
|
|
2322
|
-
|
|
2155
|
+
trojanConstruct(node, {
|
|
2156
|
+
group: group2,
|
|
2157
|
+
host,
|
|
2158
|
+
network: net,
|
|
2159
|
+
password,
|
|
2160
|
+
path,
|
|
2161
|
+
port,
|
|
2162
|
+
remark: ps,
|
|
2163
|
+
scv,
|
|
2164
|
+
server,
|
|
2165
|
+
tfo,
|
|
2166
|
+
tlsSecure: true,
|
|
2167
|
+
udp,
|
|
2168
|
+
underlyingProxy
|
|
2169
|
+
});
|
|
2170
|
+
break;
|
|
2323
2171
|
}
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2172
|
+
case "snell": {
|
|
2173
|
+
group2 = DEFAULT_GROUPS.snell;
|
|
2174
|
+
const password = asString(get(single, "psk"));
|
|
2175
|
+
const obfs = asString(get(get(single, "obfs-opts"), "mode"));
|
|
2176
|
+
const host = asString(get(get(single, "obfs-opts"), "host"));
|
|
2177
|
+
const version = asString(get(single, "version"));
|
|
2178
|
+
snellConstruct(node, {
|
|
2179
|
+
group: group2,
|
|
2180
|
+
host,
|
|
2181
|
+
obfs,
|
|
2182
|
+
password,
|
|
2183
|
+
port,
|
|
2184
|
+
remark: ps,
|
|
2185
|
+
scv,
|
|
2186
|
+
server,
|
|
2187
|
+
tfo,
|
|
2188
|
+
udp,
|
|
2189
|
+
underlyingProxy,
|
|
2190
|
+
version: toInt(version)
|
|
2191
|
+
});
|
|
2192
|
+
break;
|
|
2193
|
+
}
|
|
2194
|
+
case "wireguard": {
|
|
2195
|
+
group2 = DEFAULT_GROUPS.wireguard;
|
|
2196
|
+
const publicKey = asString(get(single, "public-key"));
|
|
2197
|
+
const privateKey = asString(get(single, "private-key"));
|
|
2198
|
+
const dns = get(single, "dns");
|
|
2199
|
+
const dnsServers = Array.isArray(dns) ? dns.map((d) => String(d)) : dns ? [String(dns)] : [];
|
|
2200
|
+
const mtu = asString(get(single, "mtu"));
|
|
2201
|
+
const psk = asString(get(single, "preshared-key"));
|
|
2202
|
+
const ip = asString(get(single, "ip"));
|
|
2203
|
+
const ipv6 = asString(get(single, "ipv6"));
|
|
2204
|
+
wireGuardConstruct(node, {
|
|
2205
|
+
dnsServers,
|
|
2206
|
+
group: group2,
|
|
2207
|
+
keepAlive: "0",
|
|
2208
|
+
mtu,
|
|
2209
|
+
port,
|
|
2210
|
+
preSharedKey: psk,
|
|
2211
|
+
privateKey,
|
|
2212
|
+
publicKey,
|
|
2213
|
+
remark: ps,
|
|
2214
|
+
selfIp: ip,
|
|
2215
|
+
selfIpv6: ipv6,
|
|
2216
|
+
server,
|
|
2217
|
+
testUrl: "",
|
|
2218
|
+
udp,
|
|
2219
|
+
underlyingProxy
|
|
2220
|
+
});
|
|
2221
|
+
break;
|
|
2222
|
+
}
|
|
2223
|
+
case "hysteria": {
|
|
2224
|
+
group2 = DEFAULT_GROUPS.hysteria;
|
|
2225
|
+
const ports = asString(get(single, "ports"));
|
|
2226
|
+
const protocol = asString(get(single, "protocol"));
|
|
2227
|
+
const obfsProtocol = asString(get(single, "obfs-protocol"));
|
|
2228
|
+
const up = asString(get(single, "up"));
|
|
2229
|
+
const upSpeed = asString(get(single, "up-speed"));
|
|
2230
|
+
const down = asString(get(single, "down"));
|
|
2231
|
+
const downSpeed = asString(get(single, "down-speed"));
|
|
2232
|
+
const auth = asString(get(single, "auth"));
|
|
2233
|
+
let authStr = asString(get(single, "auth-str"));
|
|
2234
|
+
if (authStr === "") {
|
|
2235
|
+
authStr = asString(get(single, "auth_str"));
|
|
2236
|
+
}
|
|
2237
|
+
const obfs = asString(get(single, "obfs"));
|
|
2238
|
+
const sni = asString(get(single, "sni"));
|
|
2239
|
+
const fingerprint = asString(get(single, "fingerprint"));
|
|
2240
|
+
const alpnValue = get(single, "alpn");
|
|
2241
|
+
const alpn = Array.isArray(alpnValue) ? asString(alpnValue[0]) : asString(alpnValue);
|
|
2242
|
+
const ca = asString(get(single, "ca"));
|
|
2243
|
+
const caStr = asString(get(single, "ca-str"));
|
|
2244
|
+
const recvWindowConn = asString(get(single, "recv-window-conn"));
|
|
2245
|
+
const recvWindow = asString(get(single, "recv-window"));
|
|
2246
|
+
let disableMtuDiscovery = asString(get(single, "disable-mtu-discovery"));
|
|
2247
|
+
if (disableMtuDiscovery === "") {
|
|
2248
|
+
disableMtuDiscovery = asString(get(single, "disable_mtu_discovery"));
|
|
2249
|
+
}
|
|
2250
|
+
const hopInterval = asString(get(single, "hop-interval"));
|
|
2251
|
+
hysteriaConstruct(node, {
|
|
2252
|
+
alpn,
|
|
2253
|
+
auth,
|
|
2254
|
+
authStr,
|
|
2255
|
+
ca,
|
|
2256
|
+
caStr,
|
|
2257
|
+
disableMtuDiscovery,
|
|
2258
|
+
down,
|
|
2259
|
+
downSpeed,
|
|
2260
|
+
fingerprint,
|
|
2261
|
+
group: group2,
|
|
2262
|
+
hopInterval,
|
|
2263
|
+
obfs,
|
|
2264
|
+
obfsProtocol,
|
|
2265
|
+
port,
|
|
2266
|
+
ports,
|
|
2267
|
+
protocol,
|
|
2268
|
+
recvWindow,
|
|
2269
|
+
recvWindowConn,
|
|
2270
|
+
remark: ps,
|
|
2271
|
+
scv,
|
|
2272
|
+
server,
|
|
2273
|
+
sni,
|
|
2274
|
+
tfo,
|
|
2275
|
+
underlyingProxy,
|
|
2276
|
+
up,
|
|
2277
|
+
upSpeed
|
|
2278
|
+
});
|
|
2279
|
+
break;
|
|
2280
|
+
}
|
|
2281
|
+
case "hysteria2": {
|
|
2282
|
+
group2 = DEFAULT_GROUPS.hysteria2;
|
|
2283
|
+
const ports = asString(get(single, "ports"));
|
|
2284
|
+
const up = asString(get(single, "up"));
|
|
2285
|
+
const down = asString(get(single, "down"));
|
|
2286
|
+
let password = asString(get(single, "password"));
|
|
2287
|
+
if (password === "") {
|
|
2288
|
+
password = asString(get(single, "auth"));
|
|
2289
|
+
}
|
|
2290
|
+
const obfs = asString(get(single, "obfs"));
|
|
2291
|
+
const obfsPassword = asString(get(single, "obfs-password"));
|
|
2292
|
+
const sni = asString(get(single, "sni"));
|
|
2293
|
+
const fingerprint = asString(get(single, "fingerprint"));
|
|
2294
|
+
const alpnValue = get(single, "alpn");
|
|
2295
|
+
const alpn = Array.isArray(alpnValue) ? asString(alpnValue[0]) : asString(alpnValue);
|
|
2296
|
+
const ca = asString(get(single, "ca"));
|
|
2297
|
+
const caStr = asString(get(single, "ca-str"));
|
|
2298
|
+
const cwnd = asString(get(single, "cwnd"));
|
|
2299
|
+
const hopInterval = asString(get(single, "hop-interval"));
|
|
2300
|
+
hysteria2Construct(node, {
|
|
2301
|
+
alpn,
|
|
2302
|
+
ca,
|
|
2303
|
+
caStr,
|
|
2304
|
+
cwnd,
|
|
2305
|
+
down,
|
|
2306
|
+
fingerprint,
|
|
2307
|
+
group: group2,
|
|
2308
|
+
hopInterval,
|
|
2309
|
+
obfs,
|
|
2310
|
+
obfsPassword,
|
|
2311
|
+
password,
|
|
2312
|
+
port,
|
|
2313
|
+
ports,
|
|
2314
|
+
remark: ps,
|
|
2315
|
+
scv,
|
|
2316
|
+
server,
|
|
2317
|
+
sni,
|
|
2318
|
+
tfo,
|
|
2319
|
+
underlyingProxy,
|
|
2320
|
+
up
|
|
2321
|
+
});
|
|
2322
|
+
break;
|
|
2323
|
+
}
|
|
2324
|
+
case "anytls": {
|
|
2325
|
+
group2 = DEFAULT_GROUPS.anytls;
|
|
2326
|
+
const password = asString(get(single, "password"));
|
|
2327
|
+
const sni = asString(get(single, "sni"));
|
|
2328
|
+
anyTlsConstruct(node, {
|
|
2329
|
+
group: group2,
|
|
2330
|
+
password,
|
|
2331
|
+
port,
|
|
2332
|
+
remark: ps,
|
|
2333
|
+
scv,
|
|
2334
|
+
server,
|
|
2335
|
+
sni,
|
|
2336
|
+
tfo,
|
|
2337
|
+
udp,
|
|
2338
|
+
underlyingProxy
|
|
2339
|
+
});
|
|
2340
|
+
break;
|
|
2341
|
+
}
|
|
2342
|
+
case "vless": {
|
|
2343
|
+
group2 = DEFAULT_GROUPS.v2ray;
|
|
2344
|
+
const userId = asString(get(single, "uuid"));
|
|
2345
|
+
const net = asString(get(single, "network"));
|
|
2346
|
+
const tls = asString(get(single, "tls"));
|
|
2347
|
+
let path = "";
|
|
2348
|
+
let host = "";
|
|
2349
|
+
if (net === "ws") {
|
|
2350
|
+
path = asString(get(get(single, "ws-opts"), "path"));
|
|
2351
|
+
host = asString(get(get(get(single, "ws-opts"), "headers"), "Host"));
|
|
2352
|
+
} else if (net === "grpc") {
|
|
2353
|
+
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
2354
|
+
}
|
|
2355
|
+
const alpnValue = get(single, "alpn");
|
|
2356
|
+
vlessConstruct(node, {
|
|
2357
|
+
alpn: Array.isArray(alpnValue) ? alpnValue.map((a) => String(a)) : void 0,
|
|
2358
|
+
encryption: asString(get(single, "encryption")),
|
|
2359
|
+
fingerprint: asString(get(single, "client-fingerprint")),
|
|
2360
|
+
flow: asString(get(single, "flow")),
|
|
2361
|
+
group: group2,
|
|
2362
|
+
host,
|
|
2363
|
+
network: net,
|
|
2364
|
+
path,
|
|
2365
|
+
port,
|
|
2366
|
+
remark: ps,
|
|
2367
|
+
scv,
|
|
2368
|
+
server,
|
|
2369
|
+
sni: asString(get(single, "servername")),
|
|
2370
|
+
tfo,
|
|
2371
|
+
tls: tls === "true" ? "tls" : "",
|
|
2372
|
+
udp,
|
|
2373
|
+
underlyingProxy,
|
|
2374
|
+
userId
|
|
2375
|
+
});
|
|
2376
|
+
break;
|
|
2377
|
+
}
|
|
2378
|
+
case "tuic": {
|
|
2379
|
+
group2 = DEFAULT_GROUPS.v2ray;
|
|
2380
|
+
const alpnValue = get(single, "alpn");
|
|
2381
|
+
tuicConstruct(node, {
|
|
2382
|
+
alpn: Array.isArray(alpnValue) ? alpnValue.map((a) => String(a)) : void 0,
|
|
2383
|
+
congestionControl: asString(get(single, "congestion-controller")),
|
|
2384
|
+
group: group2,
|
|
2385
|
+
password: asString(get(single, "password")),
|
|
2386
|
+
port,
|
|
2387
|
+
remark: ps,
|
|
2388
|
+
scv,
|
|
2389
|
+
server,
|
|
2390
|
+
sni: asString(get(single, "sni")),
|
|
2391
|
+
tfo,
|
|
2392
|
+
udp,
|
|
2393
|
+
underlyingProxy,
|
|
2394
|
+
userId: asString(get(single, "uuid"))
|
|
2395
|
+
});
|
|
2396
|
+
break;
|
|
2397
|
+
}
|
|
2398
|
+
default:
|
|
2399
|
+
return false;
|
|
2327
2400
|
}
|
|
2401
|
+
node.id = index;
|
|
2402
|
+
nodes.push(node);
|
|
2403
|
+
return true;
|
|
2328
2404
|
}
|
|
2329
2405
|
function parseRawSections(text) {
|
|
2330
2406
|
const sections = [];
|
|
@@ -3932,7 +4008,10 @@ function explodeSs(ss, node) {
|
|
|
3932
4008
|
const secret = match[1];
|
|
3933
4009
|
server = match[2];
|
|
3934
4010
|
port = match[3];
|
|
3935
|
-
const
|
|
4011
|
+
const raw = urlDecode(secret);
|
|
4012
|
+
const decoded = firstMatch(urlSafeBase64Decode(raw), "(\\S+?):(\\S+)");
|
|
4013
|
+
const plaintext = firstMatch(raw, "(\\S+?):(\\S+)");
|
|
4014
|
+
const secretMatch = decoded && isSsCipher(decoded[1]) ? decoded : plaintext ?? decoded;
|
|
3936
4015
|
if (!secretMatch) {
|
|
3937
4016
|
return;
|
|
3938
4017
|
}
|
|
@@ -4397,6 +4476,157 @@ function explodeAnyTls(link, node) {
|
|
|
4397
4476
|
udp: udp === "" ? void 0 : parseTri(udp)
|
|
4398
4477
|
});
|
|
4399
4478
|
}
|
|
4479
|
+
function explodeSnell(link, node) {
|
|
4480
|
+
let body = link.slice(8);
|
|
4481
|
+
let remark = "";
|
|
4482
|
+
let addition = "";
|
|
4483
|
+
const hashPos = body.lastIndexOf("#");
|
|
4484
|
+
if (hashPos !== -1) {
|
|
4485
|
+
remark = urlDecode(body.slice(hashPos + 1));
|
|
4486
|
+
body = body.slice(0, hashPos);
|
|
4487
|
+
}
|
|
4488
|
+
const qpos = body.lastIndexOf("?");
|
|
4489
|
+
if (qpos !== -1) {
|
|
4490
|
+
addition = body.slice(qpos + 1);
|
|
4491
|
+
body = body.slice(0, qpos);
|
|
4492
|
+
}
|
|
4493
|
+
const match = /^(.*?)@(.*)[:](\d+)$/.exec(body);
|
|
4494
|
+
if (!match) {
|
|
4495
|
+
return;
|
|
4496
|
+
}
|
|
4497
|
+
const password = match[1];
|
|
4498
|
+
const server = match[2];
|
|
4499
|
+
const port = match[3];
|
|
4500
|
+
if (password === "" || port === "" || port === "0") {
|
|
4501
|
+
return;
|
|
4502
|
+
}
|
|
4503
|
+
const obfs = getUrlArg(addition, "obfs");
|
|
4504
|
+
const host = getUrlArg(addition, "host");
|
|
4505
|
+
const version = getUrlArg(addition, "version");
|
|
4506
|
+
const udp = getUrlArg(addition, "udp");
|
|
4507
|
+
const tfo = getUrlArg(addition, "tfo");
|
|
4508
|
+
const scv = getUrlArg(addition, "skip-cert-verify");
|
|
4509
|
+
if (remark === "") {
|
|
4510
|
+
remark = `${server}:${port}`;
|
|
4511
|
+
}
|
|
4512
|
+
snellConstruct(node, {
|
|
4513
|
+
group: DEFAULT_GROUPS.snell,
|
|
4514
|
+
host,
|
|
4515
|
+
obfs: obfs === "" ? "none" : obfs,
|
|
4516
|
+
password,
|
|
4517
|
+
port,
|
|
4518
|
+
remark,
|
|
4519
|
+
scv: scv === "" ? void 0 : parseTri(scv),
|
|
4520
|
+
server,
|
|
4521
|
+
tfo: tfo === "" ? void 0 : parseTri(tfo),
|
|
4522
|
+
udp: udp === "" ? void 0 : parseTri(udp),
|
|
4523
|
+
version: version === "" ? 1 : toInt(version)
|
|
4524
|
+
});
|
|
4525
|
+
}
|
|
4526
|
+
function explodeHysteria(link, node) {
|
|
4527
|
+
let body = link.slice(11);
|
|
4528
|
+
let remark = "";
|
|
4529
|
+
let addition = "";
|
|
4530
|
+
const hashPos = body.lastIndexOf("#");
|
|
4531
|
+
if (hashPos !== -1) {
|
|
4532
|
+
remark = urlDecode(body.slice(hashPos + 1));
|
|
4533
|
+
body = body.slice(0, hashPos);
|
|
4534
|
+
}
|
|
4535
|
+
const qpos = body.lastIndexOf("?");
|
|
4536
|
+
if (qpos !== -1) {
|
|
4537
|
+
addition = body.slice(qpos + 1);
|
|
4538
|
+
body = body.slice(0, qpos);
|
|
4539
|
+
}
|
|
4540
|
+
const match = /^(.*)[:](\d+)$/.exec(body);
|
|
4541
|
+
if (!match) {
|
|
4542
|
+
return;
|
|
4543
|
+
}
|
|
4544
|
+
const server = match[1];
|
|
4545
|
+
const port = match[2];
|
|
4546
|
+
if (server === "" || port === "0") {
|
|
4547
|
+
return;
|
|
4548
|
+
}
|
|
4549
|
+
const auth = getUrlArg(addition, "auth");
|
|
4550
|
+
const protocol = getUrlArg(addition, "protocol");
|
|
4551
|
+
const upSpeed = getUrlArg(addition, "upmbps");
|
|
4552
|
+
const downSpeed = getUrlArg(addition, "downmbps");
|
|
4553
|
+
const alpn = getUrlArg(addition, "alpn");
|
|
4554
|
+
const obfs = getUrlArg(addition, "obfs");
|
|
4555
|
+
const obfsProtocol = getUrlArg(addition, "obfsParam");
|
|
4556
|
+
const sni = getUrlArg(addition, "peer");
|
|
4557
|
+
const insecure = getUrlArg(addition, "insecure");
|
|
4558
|
+
if (remark === "") {
|
|
4559
|
+
remark = `${server}:${port}`;
|
|
4560
|
+
}
|
|
4561
|
+
hysteriaConstruct(node, {
|
|
4562
|
+
alpn,
|
|
4563
|
+
authStr: auth,
|
|
4564
|
+
downSpeed,
|
|
4565
|
+
group: DEFAULT_GROUPS.hysteria,
|
|
4566
|
+
obfs,
|
|
4567
|
+
obfsProtocol,
|
|
4568
|
+
port,
|
|
4569
|
+
protocol: protocol === "" ? "udp" : protocol,
|
|
4570
|
+
remark,
|
|
4571
|
+
scv: insecure === "" ? void 0 : parseTri(insecure),
|
|
4572
|
+
server,
|
|
4573
|
+
sni: sni === "" ? server : sni,
|
|
4574
|
+
upSpeed
|
|
4575
|
+
});
|
|
4576
|
+
}
|
|
4577
|
+
function explodeWireguard(link, node) {
|
|
4578
|
+
const normalized = link.replace(/^(wg|wireguard):\/\//, "wireguard://");
|
|
4579
|
+
let body = normalized.slice(13);
|
|
4580
|
+
let remark = "";
|
|
4581
|
+
let addition = "";
|
|
4582
|
+
const hashPos = body.lastIndexOf("#");
|
|
4583
|
+
if (hashPos !== -1) {
|
|
4584
|
+
remark = urlDecode(body.slice(hashPos + 1));
|
|
4585
|
+
body = body.slice(0, hashPos);
|
|
4586
|
+
}
|
|
4587
|
+
const qpos = body.lastIndexOf("?");
|
|
4588
|
+
if (qpos !== -1) {
|
|
4589
|
+
addition = body.slice(qpos + 1);
|
|
4590
|
+
body = body.slice(0, qpos);
|
|
4591
|
+
}
|
|
4592
|
+
const match = /^(?:(.*)@)?\[?(.*?)]?:(\d+)$/.exec(body);
|
|
4593
|
+
if (!match) {
|
|
4594
|
+
return;
|
|
4595
|
+
}
|
|
4596
|
+
const server = match[2];
|
|
4597
|
+
const port = match[3];
|
|
4598
|
+
if (server === "" || port === "0") {
|
|
4599
|
+
return;
|
|
4600
|
+
}
|
|
4601
|
+
const privateKey = getUrlArg(addition, "privateKey") || getUrlArg(addition, "privatekey");
|
|
4602
|
+
const publicKey = getUrlArg(addition, "publicKey") || getUrlArg(addition, "publickey");
|
|
4603
|
+
if (privateKey === "" || publicKey === "") {
|
|
4604
|
+
return;
|
|
4605
|
+
}
|
|
4606
|
+
const presharedKey = getUrlArg(addition, "presharedKey");
|
|
4607
|
+
const selfIp = getUrlArg(addition, "selfIP");
|
|
4608
|
+
const selfIpv6 = getUrlArg(addition, "selfIPv6");
|
|
4609
|
+
const mtu = getUrlArg(addition, "mtu");
|
|
4610
|
+
const keepAlive = getUrlArg(addition, "keepAlive");
|
|
4611
|
+
const dns = getUrlArg(addition, "dns");
|
|
4612
|
+
if (remark === "") {
|
|
4613
|
+
remark = `${server}:${port}`;
|
|
4614
|
+
}
|
|
4615
|
+
wireGuardConstruct(node, {
|
|
4616
|
+
dnsServers: dns === "" ? ["1.1.1.1"] : dns.split(",").map((s) => s.trim()),
|
|
4617
|
+
group: DEFAULT_GROUPS.wireguard,
|
|
4618
|
+
keepAlive: keepAlive === "" ? 25 : toInt(keepAlive),
|
|
4619
|
+
mtu: mtu === "" ? 1420 : toInt(mtu),
|
|
4620
|
+
port,
|
|
4621
|
+
preSharedKey: presharedKey,
|
|
4622
|
+
privateKey,
|
|
4623
|
+
publicKey,
|
|
4624
|
+
remark,
|
|
4625
|
+
selfIp: selfIp === "" ? "10.0.0.2" : selfIp,
|
|
4626
|
+
selfIpv6,
|
|
4627
|
+
server
|
|
4628
|
+
});
|
|
4629
|
+
}
|
|
4400
4630
|
function explodeVless(link, node) {
|
|
4401
4631
|
let body = link.slice(8);
|
|
4402
4632
|
let remark = "";
|
|
@@ -4520,6 +4750,12 @@ function explode(link, node) {
|
|
|
4520
4750
|
explodeVless(link, node);
|
|
4521
4751
|
} else if (startsWith(link, "tuic://")) {
|
|
4522
4752
|
explodeTuic(link, node);
|
|
4753
|
+
} else if (startsWith(link, "snell://")) {
|
|
4754
|
+
explodeSnell(link, node);
|
|
4755
|
+
} else if (startsWith(link, "hysteria://")) {
|
|
4756
|
+
explodeHysteria(link, node);
|
|
4757
|
+
} else if (startsWith(link, "wg://") || startsWith(link, "wireguard://")) {
|
|
4758
|
+
explodeWireguard(link, node);
|
|
4523
4759
|
} else if (link.includes("hysteria2://") || link.includes("hy2://")) {
|
|
4524
4760
|
explodeHysteria2(link, node);
|
|
4525
4761
|
} else if (startsWith(link, "anytls://")) {
|
|
@@ -4916,7 +5152,11 @@ function normalizeRegionCode(code) {
|
|
|
4916
5152
|
const upper = code.trim().toUpperCase();
|
|
4917
5153
|
return /^[A-Z]{2}$/.test(upper) ? upper : "";
|
|
4918
5154
|
}
|
|
4919
|
-
function
|
|
5155
|
+
function normalizeCountryCode(code) {
|
|
5156
|
+
const upper = normalizeRegionCode(code);
|
|
5157
|
+
return upper !== "" && isRegionCode(upper) ? upper : void 0;
|
|
5158
|
+
}
|
|
5159
|
+
function displayName(code, locale) {
|
|
4920
5160
|
const upper = normalizeRegionCode(code);
|
|
4921
5161
|
if (upper === "") {
|
|
4922
5162
|
return code.trim();
|
|
@@ -4959,8 +5199,8 @@ function buildAliasRegex() {
|
|
|
4959
5199
|
}
|
|
4960
5200
|
};
|
|
4961
5201
|
for (const code of REGION_CODES) {
|
|
4962
|
-
add(
|
|
4963
|
-
add(
|
|
5202
|
+
add(displayName(code, "zh-CN"));
|
|
5203
|
+
add(displayName(code, "en"));
|
|
4964
5204
|
add(regionFlag(code));
|
|
4965
5205
|
}
|
|
4966
5206
|
for (const alias of EXTRA_ALIASES) {
|
|
@@ -5000,13 +5240,13 @@ function hasRegionName(remark) {
|
|
|
5000
5240
|
}
|
|
5001
5241
|
return false;
|
|
5002
5242
|
}
|
|
5003
|
-
function formatCountryRemark(remark, code
|
|
5004
|
-
const
|
|
5243
|
+
function formatCountryRemark(remark, code) {
|
|
5244
|
+
const normalized = normalizeCountryCode(code);
|
|
5005
5245
|
const trimmed = remark.trim();
|
|
5006
|
-
if (
|
|
5246
|
+
if (normalized === void 0) {
|
|
5007
5247
|
return trimmed;
|
|
5008
5248
|
}
|
|
5009
|
-
return trimmed === "" ?
|
|
5249
|
+
return trimmed === "" ? normalized : `${normalized}-${trimmed}`;
|
|
5010
5250
|
}
|
|
5011
5251
|
|
|
5012
5252
|
// src/generator/nodes.ts
|
|
@@ -5020,6 +5260,10 @@ function toRegex(pattern) {
|
|
|
5020
5260
|
function regFind(value, pattern) {
|
|
5021
5261
|
return toRegex(pattern).test(value);
|
|
5022
5262
|
}
|
|
5263
|
+
var REGEX_BLACKLIST = ["(.*)*"];
|
|
5264
|
+
function isBlacklistedPattern(pattern) {
|
|
5265
|
+
return REGEX_BLACKLIST.includes(pattern);
|
|
5266
|
+
}
|
|
5023
5267
|
function regMatch2(value, pattern) {
|
|
5024
5268
|
const match = toRegex(pattern).exec(value);
|
|
5025
5269
|
return match !== null && match[0] === value;
|
|
@@ -5265,7 +5509,7 @@ function nodeRename(node, renameArray) {
|
|
|
5265
5509
|
node.remark = original;
|
|
5266
5510
|
}
|
|
5267
5511
|
}
|
|
5268
|
-
function addCountryPrefix(node, resolve
|
|
5512
|
+
function addCountryPrefix(node, resolve) {
|
|
5269
5513
|
const remark = node.remark.trim();
|
|
5270
5514
|
if (hasRegionName(remark)) {
|
|
5271
5515
|
return node.remark;
|
|
@@ -5274,7 +5518,31 @@ function addCountryPrefix(node, resolve, locale = "zh-CN") {
|
|
|
5274
5518
|
if (code === void 0 || code === "") {
|
|
5275
5519
|
return node.remark;
|
|
5276
5520
|
}
|
|
5277
|
-
return formatCountryRemark(remark, code
|
|
5521
|
+
return formatCountryRemark(remark, code);
|
|
5522
|
+
}
|
|
5523
|
+
function filterNodesByCountry(nodes, resolve, include, exclude) {
|
|
5524
|
+
const includeSet = new Set(
|
|
5525
|
+
include.map((code) => normalizeCountryCode(code)).filter((code) => code !== void 0)
|
|
5526
|
+
);
|
|
5527
|
+
const excludeSet = new Set(
|
|
5528
|
+
exclude.map((code) => normalizeCountryCode(code)).filter((code) => code !== void 0)
|
|
5529
|
+
);
|
|
5530
|
+
if (includeSet.size === 0 && excludeSet.size === 0) {
|
|
5531
|
+
return;
|
|
5532
|
+
}
|
|
5533
|
+
const kept = [];
|
|
5534
|
+
for (const node of nodes) {
|
|
5535
|
+
const code = resolve ? normalizeCountryCode(resolve(node) ?? "") : void 0;
|
|
5536
|
+
if (includeSet.size > 0 && (code === void 0 || !includeSet.has(code))) {
|
|
5537
|
+
continue;
|
|
5538
|
+
}
|
|
5539
|
+
if (code !== void 0 && excludeSet.has(code)) {
|
|
5540
|
+
continue;
|
|
5541
|
+
}
|
|
5542
|
+
kept.push(node);
|
|
5543
|
+
}
|
|
5544
|
+
nodes.length = 0;
|
|
5545
|
+
nodes.push(...kept);
|
|
5278
5546
|
}
|
|
5279
5547
|
function preprocessNodes(nodes, options) {
|
|
5280
5548
|
for (const node of nodes) {
|
|
@@ -5292,13 +5560,25 @@ function preprocessNodes(nodes, options) {
|
|
|
5292
5560
|
node.remark = addEmoji(node, options.emojiArray);
|
|
5293
5561
|
}
|
|
5294
5562
|
if (options.autoCountry && options.countryResolver) {
|
|
5295
|
-
node.remark = addCountryPrefix(
|
|
5296
|
-
node,
|
|
5297
|
-
options.countryResolver,
|
|
5298
|
-
options.countryLocale ?? "zh-CN"
|
|
5299
|
-
);
|
|
5563
|
+
node.remark = addCountryPrefix(node, options.countryResolver);
|
|
5300
5564
|
}
|
|
5301
5565
|
}
|
|
5566
|
+
filterNodesByCountry(
|
|
5567
|
+
nodes,
|
|
5568
|
+
options.countryResolver,
|
|
5569
|
+
options.includeCountries ?? [],
|
|
5570
|
+
options.excludeCountries ?? []
|
|
5571
|
+
);
|
|
5572
|
+
const includeRemarks = options.includeRemarks ?? [];
|
|
5573
|
+
const excludeRemarks = options.excludeRemarks ?? [];
|
|
5574
|
+
if (includeRemarks.length > 0 || excludeRemarks.length > 0) {
|
|
5575
|
+
const kept = nodes.filter((node) => !checkIgnore(node, excludeRemarks, includeRemarks));
|
|
5576
|
+
kept.forEach((node, index) => {
|
|
5577
|
+
node.id = index;
|
|
5578
|
+
});
|
|
5579
|
+
nodes.length = 0;
|
|
5580
|
+
nodes.push(...kept);
|
|
5581
|
+
}
|
|
5302
5582
|
if (options.sortFlag) {
|
|
5303
5583
|
nodes.sort((a, b) => a.remark < b.remark ? -1 : a.remark > b.remark ? 1 : 0);
|
|
5304
5584
|
}
|
|
@@ -5355,12 +5635,59 @@ function stripBrackets(value) {
|
|
|
5355
5635
|
function toTri(value) {
|
|
5356
5636
|
return value;
|
|
5357
5637
|
}
|
|
5638
|
+
var MIHOMO_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
5639
|
+
"ss" /* Shadowsocks */,
|
|
5640
|
+
"ssr" /* ShadowsocksR */,
|
|
5641
|
+
"vmess" /* VMess */,
|
|
5642
|
+
"trojan" /* Trojan */,
|
|
5643
|
+
"snell" /* Snell */,
|
|
5644
|
+
"http" /* HTTP */,
|
|
5645
|
+
"https" /* HTTPS */,
|
|
5646
|
+
"socks5" /* SOCKS5 */,
|
|
5647
|
+
"wireguard" /* WireGuard */,
|
|
5648
|
+
"hysteria" /* Hysteria */,
|
|
5649
|
+
"hysteria2" /* Hysteria2 */,
|
|
5650
|
+
"vless" /* VLESS */,
|
|
5651
|
+
"anytls" /* AnyTLS */,
|
|
5652
|
+
"tuic" /* TUIC */
|
|
5653
|
+
]);
|
|
5654
|
+
var PREMIUM_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
5655
|
+
"ss" /* Shadowsocks */,
|
|
5656
|
+
"ssr" /* ShadowsocksR */,
|
|
5657
|
+
"vmess" /* VMess */,
|
|
5658
|
+
"trojan" /* Trojan */,
|
|
5659
|
+
"snell" /* Snell */,
|
|
5660
|
+
"http" /* HTTP */,
|
|
5661
|
+
"https" /* HTTPS */,
|
|
5662
|
+
"socks5" /* SOCKS5 */,
|
|
5663
|
+
"wireguard" /* WireGuard */
|
|
5664
|
+
]);
|
|
5665
|
+
var STASH_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
5666
|
+
...PREMIUM_PROTOCOLS,
|
|
5667
|
+
"hysteria" /* Hysteria */,
|
|
5668
|
+
"hysteria2" /* Hysteria2 */,
|
|
5669
|
+
"vless" /* VLESS */,
|
|
5670
|
+
"tuic" /* TUIC */
|
|
5671
|
+
]);
|
|
5672
|
+
function clashCapabilities(flavor) {
|
|
5673
|
+
if (flavor === "premium") {
|
|
5674
|
+
return { clientFingerprint: false, protocols: PREMIUM_PROTOCOLS, reality: false };
|
|
5675
|
+
}
|
|
5676
|
+
if (flavor === "stash") {
|
|
5677
|
+
return { clientFingerprint: false, protocols: STASH_PROTOCOLS, reality: true };
|
|
5678
|
+
}
|
|
5679
|
+
return { clientFingerprint: true, protocols: MIHOMO_PROTOCOLS, reality: true };
|
|
5680
|
+
}
|
|
5358
5681
|
function buildClashProxy(x, settings, clashR, remark, skipCertVerify, tfo) {
|
|
5359
5682
|
const proxy = {
|
|
5360
5683
|
name: remark,
|
|
5361
5684
|
port: x.port,
|
|
5362
5685
|
server: stripBrackets(x.hostname)
|
|
5363
5686
|
};
|
|
5687
|
+
const caps = clashCapabilities(settings.clashFlavor);
|
|
5688
|
+
if (!caps.protocols.has(x.type)) {
|
|
5689
|
+
return void 0;
|
|
5690
|
+
}
|
|
5364
5691
|
switch (x.type) {
|
|
5365
5692
|
case "ss" /* Shadowsocks */: {
|
|
5366
5693
|
if (settings.filterDeprecated && x.encryptMethod === "chacha20") {
|
|
@@ -5610,7 +5937,7 @@ function buildClashProxy(x, settings, clashR, remark, skipCertVerify, tfo) {
|
|
|
5610
5937
|
if (skipCertVerify !== void 0) {
|
|
5611
5938
|
proxy["skip-cert-verify"] = skipCertVerify;
|
|
5612
5939
|
}
|
|
5613
|
-
if (x.fingerprint !== "") {
|
|
5940
|
+
if (x.fingerprint !== "" && caps.clientFingerprint) {
|
|
5614
5941
|
proxy.fingerprint = x.fingerprint;
|
|
5615
5942
|
}
|
|
5616
5943
|
if (x.alpn.length > 0) {
|
|
@@ -5665,7 +5992,7 @@ function buildClashProxy(x, settings, clashR, remark, skipCertVerify, tfo) {
|
|
|
5665
5992
|
if (skipCertVerify !== void 0) {
|
|
5666
5993
|
proxy["skip-cert-verify"] = skipCertVerify;
|
|
5667
5994
|
}
|
|
5668
|
-
if (x.fingerprint !== "") {
|
|
5995
|
+
if (x.fingerprint !== "" && caps.clientFingerprint) {
|
|
5669
5996
|
proxy.fingerprint = x.fingerprint;
|
|
5670
5997
|
}
|
|
5671
5998
|
if (x.alpn.length > 0) {
|
|
@@ -5704,10 +6031,13 @@ function buildClashProxy(x, settings, clashR, remark, skipCertVerify, tfo) {
|
|
|
5704
6031
|
if (x.serverName !== "") {
|
|
5705
6032
|
proxy.servername = x.serverName;
|
|
5706
6033
|
}
|
|
5707
|
-
if (x.fingerprint !== "") {
|
|
6034
|
+
if (x.fingerprint !== "" && caps.clientFingerprint) {
|
|
5708
6035
|
proxy["client-fingerprint"] = x.fingerprint;
|
|
5709
6036
|
}
|
|
5710
6037
|
if (x.publicKey !== "" || x.shortId !== "") {
|
|
6038
|
+
if (!caps.reality) {
|
|
6039
|
+
return void 0;
|
|
6040
|
+
}
|
|
5711
6041
|
const realityOpts = {};
|
|
5712
6042
|
if (x.publicKey !== "") {
|
|
5713
6043
|
realityOpts["public-key"] = x.publicKey;
|
|
@@ -7064,7 +7394,7 @@ function collectRuleLines(content, group2, noResolveOnly) {
|
|
|
7064
7394
|
}
|
|
7065
7395
|
return out;
|
|
7066
7396
|
}
|
|
7067
|
-
function rulesetToClashRules(rulesets) {
|
|
7397
|
+
function rulesetToClashRules(rulesets, classical = false) {
|
|
7068
7398
|
const rules = [];
|
|
7069
7399
|
for (const ruleset of rulesets) {
|
|
7070
7400
|
const content = ruleset.content;
|
|
@@ -7080,7 +7410,10 @@ function rulesetToClashRules(rulesets) {
|
|
|
7080
7410
|
rules.push(transformRuleToCommon(line, group2));
|
|
7081
7411
|
continue;
|
|
7082
7412
|
}
|
|
7083
|
-
const converted = convertRuleset(
|
|
7413
|
+
const converted = convertRuleset(
|
|
7414
|
+
content,
|
|
7415
|
+
classical && /^payload:\r?\n/.test(content) ? "clash-classical" /* ClashClassical */ : ruleset.ruleType
|
|
7416
|
+
);
|
|
7084
7417
|
for (const rawLine of converted.split(/\r?\n/)) {
|
|
7085
7418
|
let line = rawLine.trim();
|
|
7086
7419
|
if (!isRuleLine(line)) {
|
|
@@ -7097,7 +7430,7 @@ function rulesetToClashRules(rulesets) {
|
|
|
7097
7430
|
}
|
|
7098
7431
|
return rules;
|
|
7099
7432
|
}
|
|
7100
|
-
function rulesetToSurgeRules(rulesets, surgeVersion) {
|
|
7433
|
+
function rulesetToSurgeRules(rulesets, surgeVersion, expand = true) {
|
|
7101
7434
|
let section;
|
|
7102
7435
|
let allowed;
|
|
7103
7436
|
let noResolveOnly = false;
|
|
@@ -7135,6 +7468,17 @@ function rulesetToSurgeRules(rulesets, surgeVersion) {
|
|
|
7135
7468
|
continue;
|
|
7136
7469
|
}
|
|
7137
7470
|
const group2 = ruleset.ruleGroup;
|
|
7471
|
+
if (!expand && (surgeVersion > 2 || surgeVersion === -3)) {
|
|
7472
|
+
const { url } = parseRulesetSource(ruleset.rulePath);
|
|
7473
|
+
if (/^https?:\/\//i.test(url.trim()) && !ruleset.content.startsWith("[]")) {
|
|
7474
|
+
let line = `RULE-SET,${url.trim()},${group2}`;
|
|
7475
|
+
if (ruleset.updateInterval > 0) {
|
|
7476
|
+
line += `,update-interval=${ruleset.updateInterval}`;
|
|
7477
|
+
}
|
|
7478
|
+
lines.push(line);
|
|
7479
|
+
continue;
|
|
7480
|
+
}
|
|
7481
|
+
}
|
|
7138
7482
|
if (ruleset.content.startsWith("[]")) {
|
|
7139
7483
|
let line = ruleset.content.slice(2);
|
|
7140
7484
|
if (line === "MATCH") {
|
|
@@ -7899,9 +8243,24 @@ function buildOutbound(x, settings, remark) {
|
|
|
7899
8243
|
proxy = out;
|
|
7900
8244
|
break;
|
|
7901
8245
|
}
|
|
7902
|
-
// sing-box has no
|
|
8246
|
+
// sing-box has no ShadowsocksR implementation (configs using it fail
|
|
8247
|
+
// at startup), so such nodes are dropped.
|
|
7903
8248
|
case "ssr" /* ShadowsocksR */:
|
|
7904
8249
|
return void 0;
|
|
8250
|
+
case "snell" /* Snell */: {
|
|
8251
|
+
const out = { ...common, psk: x.password, type: "snell" };
|
|
8252
|
+
if (x.snellVersion) {
|
|
8253
|
+
out.version = x.snellVersion;
|
|
8254
|
+
}
|
|
8255
|
+
if (x.obfs !== "" && x.obfs !== "none") {
|
|
8256
|
+
out.obfs_mode = x.obfs;
|
|
8257
|
+
}
|
|
8258
|
+
if (x.host !== "") {
|
|
8259
|
+
out.obfs_host = x.host;
|
|
8260
|
+
}
|
|
8261
|
+
proxy = out;
|
|
8262
|
+
break;
|
|
8263
|
+
}
|
|
7905
8264
|
case "vmess" /* VMess */: {
|
|
7906
8265
|
const out = {
|
|
7907
8266
|
...common,
|
|
@@ -8184,9 +8543,12 @@ function runPreprocess(nodes, settings) {
|
|
|
8184
8543
|
preprocessNodes(nodes, {
|
|
8185
8544
|
addEmoji: settings.addEmoji,
|
|
8186
8545
|
autoCountry: settings.autoCountry,
|
|
8187
|
-
countryLocale: settings.countryLocale,
|
|
8188
8546
|
countryResolver: settings.countryResolver,
|
|
8189
8547
|
emojiArray: settings.emojiArray,
|
|
8548
|
+
excludeCountries: settings.excludeCountries,
|
|
8549
|
+
excludeRemarks: settings.excludeRemarks,
|
|
8550
|
+
includeCountries: settings.includeCountries,
|
|
8551
|
+
includeRemarks: settings.includeRemarks,
|
|
8190
8552
|
nameRegexArray: settings.nameRegexArray,
|
|
8191
8553
|
nameRemove: settings.nameRemove,
|
|
8192
8554
|
removeEmoji: settings.removeEmoji,
|
|
@@ -8202,6 +8564,7 @@ function generate(nodes, options) {
|
|
|
8202
8564
|
runPreprocess(nodes, settings);
|
|
8203
8565
|
const groups = resolveGroups(options);
|
|
8204
8566
|
const rulesets = resolveRulesets(options, settings);
|
|
8567
|
+
const baseConf = applyBaseTemplate(options.baseConf ?? "", settings);
|
|
8205
8568
|
switch (options.target) {
|
|
8206
8569
|
case "clash" /* Clash */:
|
|
8207
8570
|
case "clashr" /* ClashR */: {
|
|
@@ -8211,9 +8574,9 @@ function generate(nodes, options) {
|
|
|
8211
8574
|
}
|
|
8212
8575
|
case "surge" /* Surge */: {
|
|
8213
8576
|
const surgeVersion = options.surgeVersion ?? 5;
|
|
8214
|
-
const rules = rulesets ? rulesetToSurgeRules(rulesets, surgeVersion) : void 0;
|
|
8577
|
+
const rules = rulesets ? rulesetToSurgeRules(rulesets, surgeVersion, settings.expandRulesets) : void 0;
|
|
8215
8578
|
return toSurge(nodes, groups, settings, {
|
|
8216
|
-
baseConf
|
|
8579
|
+
baseConf,
|
|
8217
8580
|
nodeList: settings.nodeList,
|
|
8218
8581
|
rules,
|
|
8219
8582
|
version: surgeVersion
|
|
@@ -8222,7 +8585,7 @@ function generate(nodes, options) {
|
|
|
8222
8585
|
case "quanx" /* QuantumultX */: {
|
|
8223
8586
|
const rules = rulesets ? rulesetToSurgeRules(rulesets, -1) : void 0;
|
|
8224
8587
|
return toQuanX(nodes, groups, settings, {
|
|
8225
|
-
baseConf
|
|
8588
|
+
baseConf,
|
|
8226
8589
|
nodeList: settings.nodeList,
|
|
8227
8590
|
rules
|
|
8228
8591
|
});
|
|
@@ -8230,7 +8593,7 @@ function generate(nodes, options) {
|
|
|
8230
8593
|
case "quan" /* Quantumult */: {
|
|
8231
8594
|
const rules = rulesets ? rulesetToSurgeRules(rulesets, -2) : void 0;
|
|
8232
8595
|
return toQuan(nodes, groups, settings, {
|
|
8233
|
-
baseConf
|
|
8596
|
+
baseConf,
|
|
8234
8597
|
nodeList: settings.nodeList,
|
|
8235
8598
|
rules
|
|
8236
8599
|
});
|
|
@@ -8238,21 +8601,21 @@ function generate(nodes, options) {
|
|
|
8238
8601
|
case "loon" /* Loon */: {
|
|
8239
8602
|
const rules = rulesets ? rulesetToSurgeRules(rulesets, -4) : void 0;
|
|
8240
8603
|
return toLoon(nodes, groups, settings, {
|
|
8241
|
-
baseConf
|
|
8604
|
+
baseConf,
|
|
8242
8605
|
nodeList: settings.nodeList,
|
|
8243
8606
|
rules
|
|
8244
8607
|
});
|
|
8245
8608
|
}
|
|
8246
8609
|
case "singbox" /* SingBox */:
|
|
8247
8610
|
return toSingBox(nodes, groups, settings, {
|
|
8248
|
-
baseConf
|
|
8611
|
+
baseConf,
|
|
8249
8612
|
nodeList: settings.nodeList,
|
|
8250
8613
|
overwriteOriginalRules: settings.overwriteOriginalRules,
|
|
8251
8614
|
rulesets
|
|
8252
8615
|
});
|
|
8253
8616
|
case "mellow" /* Mellow */:
|
|
8254
8617
|
return toMellow(nodes, groups, settings, {
|
|
8255
|
-
baseConf
|
|
8618
|
+
baseConf,
|
|
8256
8619
|
nodeList: settings.nodeList,
|
|
8257
8620
|
overwriteOriginalRules: settings.overwriteOriginalRules,
|
|
8258
8621
|
rulesets
|
|
@@ -8270,11 +8633,11 @@ function generate(nodes, options) {
|
|
|
8270
8633
|
case "ssd" /* SSD */:
|
|
8271
8634
|
return proxyToSsd(nodes, "", "");
|
|
8272
8635
|
case "sssub" /* SSSub */:
|
|
8273
|
-
return proxyToSsSub(nodes,
|
|
8636
|
+
return proxyToSsSub(nodes, baseConf);
|
|
8274
8637
|
case "surfboard" /* Surfboard */: {
|
|
8275
|
-
const rules = rulesets ? rulesetToSurgeRules(rulesets, options.surgeVersion ?? 5) : void 0;
|
|
8638
|
+
const rules = rulesets ? rulesetToSurgeRules(rulesets, options.surgeVersion ?? 5, settings.expandRulesets) : void 0;
|
|
8276
8639
|
return toSurfboard(nodes, groups, settings, {
|
|
8277
|
-
baseConf
|
|
8640
|
+
baseConf,
|
|
8278
8641
|
nodeList: settings.nodeList,
|
|
8279
8642
|
rules
|
|
8280
8643
|
});
|
|
@@ -8287,6 +8650,12 @@ function generate(nodes, options) {
|
|
|
8287
8650
|
throw new Error(`Unsupported target format: ${options.target}`);
|
|
8288
8651
|
}
|
|
8289
8652
|
}
|
|
8653
|
+
function applyBaseTemplate(baseConf, settings) {
|
|
8654
|
+
if (baseConf === "" || !hasTemplatePlaceholders(baseConf)) {
|
|
8655
|
+
return baseConf;
|
|
8656
|
+
}
|
|
8657
|
+
return renderTemplate(baseConf, settings.templateVars);
|
|
8658
|
+
}
|
|
8290
8659
|
function toSip008(nodes, baseConf = "") {
|
|
8291
8660
|
return proxyToSsSub(nodes, baseConf);
|
|
8292
8661
|
}
|
|
@@ -8316,7 +8685,7 @@ function attachClashRules(doc, settings, rulesets) {
|
|
|
8316
8685
|
return;
|
|
8317
8686
|
}
|
|
8318
8687
|
const field = settings.clashNewFieldName ? "rules" : "Rule";
|
|
8319
|
-
const generated = rulesetToClashRules(rulesets);
|
|
8688
|
+
const generated = rulesetToClashRules(rulesets, settings.clashClassicalRuleset);
|
|
8320
8689
|
if (generated.length === 0) {
|
|
8321
8690
|
return;
|
|
8322
8691
|
}
|
|
@@ -8334,6 +8703,8 @@ export {
|
|
|
8334
8703
|
ProxyGroupType,
|
|
8335
8704
|
ProxyType,
|
|
8336
8705
|
QUANX_RULE_TYPES,
|
|
8706
|
+
REGEX_BLACKLIST,
|
|
8707
|
+
RULESET_TYPE_PREFIXES,
|
|
8337
8708
|
RulesetType,
|
|
8338
8709
|
SING_BOX_RULE_TYPES,
|
|
8339
8710
|
SSR_CIPHERS,
|
|
@@ -8365,12 +8736,14 @@ export {
|
|
|
8365
8736
|
explodeClash,
|
|
8366
8737
|
explodeHttp,
|
|
8367
8738
|
explodeHttpSub,
|
|
8739
|
+
explodeHysteria,
|
|
8368
8740
|
explodeHysteria2,
|
|
8369
8741
|
explodeKitsunebi,
|
|
8370
8742
|
explodeNetch,
|
|
8371
8743
|
explodeNetchConf,
|
|
8372
8744
|
explodeQuan,
|
|
8373
8745
|
explodeShadowrocket,
|
|
8746
|
+
explodeSnell,
|
|
8374
8747
|
explodeSocks,
|
|
8375
8748
|
explodeSs,
|
|
8376
8749
|
explodeSsAndroid,
|
|
@@ -8387,7 +8760,9 @@ export {
|
|
|
8387
8760
|
explodeVless,
|
|
8388
8761
|
explodeVmess,
|
|
8389
8762
|
explodeVmessConf,
|
|
8763
|
+
explodeWireguard,
|
|
8390
8764
|
filterNodes,
|
|
8765
|
+
filterNodesByCountry,
|
|
8391
8766
|
findSection,
|
|
8392
8767
|
fnv1a64,
|
|
8393
8768
|
fnv1a64Hex,
|
|
@@ -8409,6 +8784,7 @@ export {
|
|
|
8409
8784
|
hysteria2Construct,
|
|
8410
8785
|
hysteriaConstruct,
|
|
8411
8786
|
inferUserinfoProviderFromUrl,
|
|
8787
|
+
isBlacklistedPattern,
|
|
8412
8788
|
isBlank,
|
|
8413
8789
|
isFlattenableSsr,
|
|
8414
8790
|
isIp,
|
|
@@ -8422,9 +8798,11 @@ export {
|
|
|
8422
8798
|
nodeNameRegex,
|
|
8423
8799
|
nodeNameRemove,
|
|
8424
8800
|
nodeRename,
|
|
8801
|
+
normalizeCountryCode,
|
|
8425
8802
|
normalizeQueryKey,
|
|
8426
8803
|
normalizeUserinfoProvider,
|
|
8427
8804
|
pad2,
|
|
8805
|
+
parseClashFlavor,
|
|
8428
8806
|
parseClashText,
|
|
8429
8807
|
parseConfContent,
|
|
8430
8808
|
parseCustomProxyGroup,
|
|
@@ -8439,6 +8817,7 @@ export {
|
|
|
8439
8817
|
parseRegexMatch,
|
|
8440
8818
|
parseRequestSettings,
|
|
8441
8819
|
parseRulesetConfig,
|
|
8820
|
+
parseRulesetSource,
|
|
8442
8821
|
parseSubscription,
|
|
8443
8822
|
parseSubscriptionUserinfo,
|
|
8444
8823
|
parseTriBool,
|
|
@@ -8451,8 +8830,6 @@ export {
|
|
|
8451
8830
|
queryBoolFlag,
|
|
8452
8831
|
regMatch,
|
|
8453
8832
|
regReplace,
|
|
8454
|
-
regionDisplayName,
|
|
8455
|
-
regionFlag,
|
|
8456
8833
|
removeEmoji,
|
|
8457
8834
|
renderRawIni,
|
|
8458
8835
|
renderTemplate,
|