@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.cjs
CHANGED
|
@@ -25,6 +25,8 @@ __export(index_exports, {
|
|
|
25
25
|
ProxyGroupType: () => ProxyGroupType,
|
|
26
26
|
ProxyType: () => ProxyType,
|
|
27
27
|
QUANX_RULE_TYPES: () => QUANX_RULE_TYPES,
|
|
28
|
+
REGEX_BLACKLIST: () => REGEX_BLACKLIST,
|
|
29
|
+
RULESET_TYPE_PREFIXES: () => RULESET_TYPE_PREFIXES,
|
|
28
30
|
RulesetType: () => RulesetType,
|
|
29
31
|
SING_BOX_RULE_TYPES: () => SING_BOX_RULE_TYPES,
|
|
30
32
|
SSR_CIPHERS: () => SSR_CIPHERS,
|
|
@@ -56,12 +58,14 @@ __export(index_exports, {
|
|
|
56
58
|
explodeClash: () => explodeClash,
|
|
57
59
|
explodeHttp: () => explodeHttp,
|
|
58
60
|
explodeHttpSub: () => explodeHttpSub,
|
|
61
|
+
explodeHysteria: () => explodeHysteria,
|
|
59
62
|
explodeHysteria2: () => explodeHysteria2,
|
|
60
63
|
explodeKitsunebi: () => explodeKitsunebi,
|
|
61
64
|
explodeNetch: () => explodeNetch,
|
|
62
65
|
explodeNetchConf: () => explodeNetchConf,
|
|
63
66
|
explodeQuan: () => explodeQuan,
|
|
64
67
|
explodeShadowrocket: () => explodeShadowrocket,
|
|
68
|
+
explodeSnell: () => explodeSnell,
|
|
65
69
|
explodeSocks: () => explodeSocks,
|
|
66
70
|
explodeSs: () => explodeSs,
|
|
67
71
|
explodeSsAndroid: () => explodeSsAndroid,
|
|
@@ -78,7 +82,9 @@ __export(index_exports, {
|
|
|
78
82
|
explodeVless: () => explodeVless,
|
|
79
83
|
explodeVmess: () => explodeVmess,
|
|
80
84
|
explodeVmessConf: () => explodeVmessConf,
|
|
85
|
+
explodeWireguard: () => explodeWireguard,
|
|
81
86
|
filterNodes: () => filterNodes,
|
|
87
|
+
filterNodesByCountry: () => filterNodesByCountry,
|
|
82
88
|
findSection: () => findSection,
|
|
83
89
|
fnv1a64: () => fnv1a64,
|
|
84
90
|
fnv1a64Hex: () => fnv1a64Hex,
|
|
@@ -100,6 +106,7 @@ __export(index_exports, {
|
|
|
100
106
|
hysteria2Construct: () => hysteria2Construct,
|
|
101
107
|
hysteriaConstruct: () => hysteriaConstruct,
|
|
102
108
|
inferUserinfoProviderFromUrl: () => inferUserinfoProviderFromUrl,
|
|
109
|
+
isBlacklistedPattern: () => isBlacklistedPattern,
|
|
103
110
|
isBlank: () => isBlank,
|
|
104
111
|
isFlattenableSsr: () => isFlattenableSsr,
|
|
105
112
|
isIp: () => isIp,
|
|
@@ -113,9 +120,11 @@ __export(index_exports, {
|
|
|
113
120
|
nodeNameRegex: () => nodeNameRegex,
|
|
114
121
|
nodeNameRemove: () => nodeNameRemove,
|
|
115
122
|
nodeRename: () => nodeRename,
|
|
123
|
+
normalizeCountryCode: () => normalizeCountryCode,
|
|
116
124
|
normalizeQueryKey: () => normalizeQueryKey,
|
|
117
125
|
normalizeUserinfoProvider: () => normalizeUserinfoProvider,
|
|
118
126
|
pad2: () => pad2,
|
|
127
|
+
parseClashFlavor: () => parseClashFlavor,
|
|
119
128
|
parseClashText: () => parseClashText,
|
|
120
129
|
parseConfContent: () => parseConfContent,
|
|
121
130
|
parseCustomProxyGroup: () => parseCustomProxyGroup,
|
|
@@ -130,6 +139,7 @@ __export(index_exports, {
|
|
|
130
139
|
parseRegexMatch: () => parseRegexMatch,
|
|
131
140
|
parseRequestSettings: () => parseRequestSettings,
|
|
132
141
|
parseRulesetConfig: () => parseRulesetConfig,
|
|
142
|
+
parseRulesetSource: () => parseRulesetSource,
|
|
133
143
|
parseSubscription: () => parseSubscription,
|
|
134
144
|
parseSubscriptionUserinfo: () => parseSubscriptionUserinfo,
|
|
135
145
|
parseTriBool: () => parseTriBool,
|
|
@@ -142,8 +152,6 @@ __export(index_exports, {
|
|
|
142
152
|
queryBoolFlag: () => queryBoolFlag,
|
|
143
153
|
regMatch: () => regMatch,
|
|
144
154
|
regReplace: () => regReplace,
|
|
145
|
-
regionDisplayName: () => regionDisplayName,
|
|
146
|
-
regionFlag: () => regionFlag,
|
|
147
155
|
removeEmoji: () => removeEmoji,
|
|
148
156
|
renderRawIni: () => renderRawIni,
|
|
149
157
|
renderTemplate: () => renderTemplate,
|
|
@@ -420,6 +428,16 @@ function createRulesetConfig() {
|
|
|
420
428
|
}
|
|
421
429
|
|
|
422
430
|
// src/types/settings.ts
|
|
431
|
+
function parseClashFlavor(value) {
|
|
432
|
+
const normalized = (value ?? "").trim().toLowerCase();
|
|
433
|
+
if (normalized === "premium" || normalized === "original" || normalized === "classic" || normalized === "clash") {
|
|
434
|
+
return "premium";
|
|
435
|
+
}
|
|
436
|
+
if (normalized === "stash") {
|
|
437
|
+
return "stash";
|
|
438
|
+
}
|
|
439
|
+
return "mihomo";
|
|
440
|
+
}
|
|
423
441
|
var TargetFormat = /* @__PURE__ */ ((TargetFormat2) => {
|
|
424
442
|
TargetFormat2["Clash"] = "clash";
|
|
425
443
|
TargetFormat2["ClashR"] = "clashr";
|
|
@@ -448,16 +466,21 @@ function createExtraSettings() {
|
|
|
448
466
|
authorized: false,
|
|
449
467
|
autoCountry: false,
|
|
450
468
|
clashClassicalRuleset: false,
|
|
469
|
+
clashFlavor: "mihomo",
|
|
451
470
|
clashNewFieldName: true,
|
|
452
471
|
clashProxiesStyle: "flow",
|
|
453
472
|
clashProxyGroupsStyle: "flow",
|
|
454
473
|
clashScript: false,
|
|
455
|
-
countryLocale: "zh-CN",
|
|
456
474
|
countryResolver: void 0,
|
|
457
475
|
dedupe: false,
|
|
458
476
|
emojiArray: [],
|
|
459
477
|
enableRuleGenerator: true,
|
|
478
|
+
excludeCountries: [],
|
|
479
|
+
excludeRemarks: [],
|
|
480
|
+
expandRulesets: true,
|
|
460
481
|
filterDeprecated: false,
|
|
482
|
+
includeCountries: [],
|
|
483
|
+
includeRemarks: [],
|
|
461
484
|
managedConfigPrefix: "",
|
|
462
485
|
nameRegexArray: [],
|
|
463
486
|
nameRemove: [],
|
|
@@ -470,6 +493,7 @@ function createExtraSettings() {
|
|
|
470
493
|
sortFlag: false,
|
|
471
494
|
sortScript: "",
|
|
472
495
|
surgeSsrPath: "",
|
|
496
|
+
templateVars: {},
|
|
473
497
|
tfo: void 0,
|
|
474
498
|
tls13: void 0,
|
|
475
499
|
udp: void 0
|
|
@@ -693,7 +717,7 @@ function toBool(value) {
|
|
|
693
717
|
return false;
|
|
694
718
|
}
|
|
695
719
|
const normalized = value.trim().toLowerCase();
|
|
696
|
-
return normalized === "true" || normalized === "1";
|
|
720
|
+
return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on";
|
|
697
721
|
}
|
|
698
722
|
function strFind(haystack, needle) {
|
|
699
723
|
return haystack.includes(needle);
|
|
@@ -842,6 +866,23 @@ function templateVariableNames(content) {
|
|
|
842
866
|
}
|
|
843
867
|
|
|
844
868
|
// src/settings/config.ts
|
|
869
|
+
var RULESET_TYPE_PREFIXES = [
|
|
870
|
+
["surge:", "surge" /* Surge */],
|
|
871
|
+
["quanx:", "quanx" /* QuantumultX */],
|
|
872
|
+
["quantumultx:", "quanx" /* QuantumultX */],
|
|
873
|
+
["clash-domain:", "clash-domain" /* ClashDomain */],
|
|
874
|
+
["clash-ipcidr:", "clash-ipcidr" /* ClashIpCidr */],
|
|
875
|
+
["clash-classic:", "clash-classical" /* ClashClassical */],
|
|
876
|
+
["clash:", "clash-classical" /* ClashClassical */]
|
|
877
|
+
];
|
|
878
|
+
function parseRulesetSource(source) {
|
|
879
|
+
for (const [prefix, type] of RULESET_TYPE_PREFIXES) {
|
|
880
|
+
if (source.toLowerCase().startsWith(prefix)) {
|
|
881
|
+
return { type, url: source.slice(prefix.length) };
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
return { url: source };
|
|
885
|
+
}
|
|
845
886
|
var GROUP_TYPE_MAP = {
|
|
846
887
|
fallback: "fallback" /* Fallback */,
|
|
847
888
|
"load-balance": "load-balance" /* LoadBalance */,
|
|
@@ -943,8 +984,10 @@ function parseExternalConfig(content) {
|
|
|
943
984
|
baseFiles: {},
|
|
944
985
|
emoji: [],
|
|
945
986
|
enableRuleGenerator: true,
|
|
987
|
+
excludeCountries: [],
|
|
946
988
|
excludeRemarks: [],
|
|
947
989
|
groups: [],
|
|
990
|
+
includeCountries: [],
|
|
948
991
|
includeRemarks: [],
|
|
949
992
|
nameRegex: [],
|
|
950
993
|
nameRemove: [],
|
|
@@ -1013,6 +1056,22 @@ function parseExternalConfig(content) {
|
|
|
1013
1056
|
result.includeRemarks.push(value);
|
|
1014
1057
|
}
|
|
1015
1058
|
break;
|
|
1059
|
+
case "include_country":
|
|
1060
|
+
for (const fragment of value.split(",")) {
|
|
1061
|
+
const trimmed = fragment.trim().toUpperCase();
|
|
1062
|
+
if (trimmed !== "") {
|
|
1063
|
+
result.includeCountries.push(trimmed);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
break;
|
|
1067
|
+
case "exclude_country":
|
|
1068
|
+
for (const fragment of value.split(",")) {
|
|
1069
|
+
const trimmed = fragment.trim().toUpperCase();
|
|
1070
|
+
if (trimmed !== "") {
|
|
1071
|
+
result.excludeCountries.push(trimmed);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
break;
|
|
1016
1075
|
case "exclude_remarks":
|
|
1017
1076
|
case "exclude":
|
|
1018
1077
|
if (value !== "") {
|
|
@@ -1067,6 +1126,9 @@ function listArg(query, key) {
|
|
|
1067
1126
|
const value = getUrlArg(query, key);
|
|
1068
1127
|
return value === "" ? [] : value.split(",");
|
|
1069
1128
|
}
|
|
1129
|
+
function countryListArg(query, key) {
|
|
1130
|
+
return getAllUrlArgs(query, key).flatMap((raw) => raw.split(",")).map((raw) => raw.trim().toUpperCase()).filter((raw) => raw !== "");
|
|
1131
|
+
}
|
|
1070
1132
|
function resolveNewFieldName(query) {
|
|
1071
1133
|
if (boolArg(query, "legacy") || boolArg(query, "legacy_field_name") || boolArg(query, "legacy-field-name")) {
|
|
1072
1134
|
return false;
|
|
@@ -1105,13 +1167,19 @@ function createRequestSettings() {
|
|
|
1105
1167
|
appendType: false,
|
|
1106
1168
|
autoCountry: false,
|
|
1107
1169
|
autoExtract: false,
|
|
1170
|
+
clashFlavor: "mihomo",
|
|
1108
1171
|
clashScript: false,
|
|
1109
1172
|
classicalRuleset: false,
|
|
1110
1173
|
dedupe: false,
|
|
1174
|
+
devId: "",
|
|
1111
1175
|
emoji: [],
|
|
1176
|
+
excludeCountries: [],
|
|
1112
1177
|
excludeRemarks: [],
|
|
1178
|
+
expand: true,
|
|
1179
|
+
filename: "",
|
|
1113
1180
|
filterDeprecated: false,
|
|
1114
1181
|
group: [],
|
|
1182
|
+
includeCountries: [],
|
|
1115
1183
|
includeRemarks: [],
|
|
1116
1184
|
insert: false,
|
|
1117
1185
|
interval: 0,
|
|
@@ -1129,6 +1197,7 @@ function createRequestSettings() {
|
|
|
1129
1197
|
script: "",
|
|
1130
1198
|
scv: void 0,
|
|
1131
1199
|
sort: false,
|
|
1200
|
+
strict: false,
|
|
1132
1201
|
target: "auto" /* Auto */,
|
|
1133
1202
|
tfo: void 0,
|
|
1134
1203
|
tls13: void 0,
|
|
@@ -1157,6 +1226,11 @@ function parseRequestSettings(query) {
|
|
|
1157
1226
|
settings.filterDeprecated = boolArg(query, "filter_deprecated");
|
|
1158
1227
|
settings.newFieldName = resolveNewFieldName(query);
|
|
1159
1228
|
settings.classicalRuleset = boolArg(query, "classical");
|
|
1229
|
+
settings.clashFlavor = parseClashFlavor(firstArg(query, "flavor"));
|
|
1230
|
+
settings.expand = queryBoolFlag(query, "expand") ?? true;
|
|
1231
|
+
settings.strict = boolArg(query, "strict");
|
|
1232
|
+
settings.filename = firstArg(query, "filename");
|
|
1233
|
+
settings.devId = firstArg(query, "dev_id", "dev-id", "device_id", "device-id");
|
|
1160
1234
|
settings.insert = getUrlArg(query, "insert") !== "";
|
|
1161
1235
|
settings.clashScript = boolArg(query, "clash_script");
|
|
1162
1236
|
settings.autoExtract = boolArg(query, "auto_extract");
|
|
@@ -1172,6 +1246,8 @@ function parseRequestSettings(query) {
|
|
|
1172
1246
|
settings.proxyGroupsStyle = getUrlArg(query, "proxy_groups_style") || "flow";
|
|
1173
1247
|
settings.includeRemarks = listArg(query, "include");
|
|
1174
1248
|
settings.excludeRemarks = listArg(query, "exclude");
|
|
1249
|
+
settings.includeCountries = countryListArg(query, "include_country");
|
|
1250
|
+
settings.excludeCountries = countryListArg(query, "exclude_country");
|
|
1175
1251
|
settings.userinfoUrl = firstArg(query, "userinfo_url", "userinfo-url", "userinfo");
|
|
1176
1252
|
settings.userinfoProvider = firstArg(
|
|
1177
1253
|
query,
|
|
@@ -2047,485 +2123,493 @@ function explodeClash(root, nodes) {
|
|
|
2047
2123
|
}
|
|
2048
2124
|
let index = nodes.length;
|
|
2049
2125
|
for (const single of list) {
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
const port = asString(get(single, "port"));
|
|
2054
|
-
let underlyingProxy = asString(get(single, "underlying-proxy"));
|
|
2055
|
-
if (underlyingProxy === "") {
|
|
2056
|
-
underlyingProxy = asString(get(single, "dialer-proxy"));
|
|
2057
|
-
}
|
|
2058
|
-
if (port === "" || port === "0") {
|
|
2059
|
-
continue;
|
|
2060
|
-
}
|
|
2061
|
-
const udp = asTri(get(single, "udp"));
|
|
2062
|
-
const tfo = asTri(get(single, "fast-open"));
|
|
2063
|
-
const scv = asTri(get(single, "skip-cert-verify"));
|
|
2064
|
-
const node = createProxy();
|
|
2065
|
-
let group2 = "";
|
|
2066
|
-
switch (proxyType) {
|
|
2067
|
-
case "vmess": {
|
|
2068
|
-
group2 = DEFAULT_GROUPS.v2ray;
|
|
2069
|
-
const id = asString(get(single, "uuid"));
|
|
2070
|
-
const aid = asString(get(single, "alterId"));
|
|
2071
|
-
const cipher = asString(get(single, "cipher"));
|
|
2072
|
-
const net = get(single, "network") !== void 0 ? asString(get(single, "network")) : "tcp";
|
|
2073
|
-
const sni = asString(get(single, "servername"));
|
|
2074
|
-
let path = "";
|
|
2075
|
-
let host = "";
|
|
2076
|
-
let edge = "";
|
|
2077
|
-
switch (net) {
|
|
2078
|
-
case "http":
|
|
2079
|
-
path = asString(get(get(get(single, "http-opts"), "path"), 0));
|
|
2080
|
-
host = asString(get(get(get(get(single, "http-opts"), "headers"), "Host"), 0));
|
|
2081
|
-
edge = "";
|
|
2082
|
-
break;
|
|
2083
|
-
case "ws":
|
|
2084
|
-
if (get(single, "ws-opts") !== void 0) {
|
|
2085
|
-
const wsOpts = get(single, "ws-opts");
|
|
2086
|
-
path = get(wsOpts, "path") !== void 0 ? asString(get(wsOpts, "path")) : "/";
|
|
2087
|
-
host = asString(get(get(wsOpts, "headers"), "Host"));
|
|
2088
|
-
edge = asString(get(get(wsOpts, "headers"), "Edge"));
|
|
2089
|
-
} else {
|
|
2090
|
-
path = get(single, "ws-path") !== void 0 ? asString(get(single, "ws-path")) : "/";
|
|
2091
|
-
host = asString(get(get(single, "ws-headers"), "Host"));
|
|
2092
|
-
edge = asString(get(get(single, "ws-headers"), "Edge"));
|
|
2093
|
-
}
|
|
2094
|
-
break;
|
|
2095
|
-
case "h2":
|
|
2096
|
-
path = asString(get(get(single, "h2-opts"), "path"));
|
|
2097
|
-
host = asString(get(get(get(single, "h2-opts"), "host"), 0));
|
|
2098
|
-
edge = "";
|
|
2099
|
-
break;
|
|
2100
|
-
case "grpc":
|
|
2101
|
-
host = asString(get(single, "servername"));
|
|
2102
|
-
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
2103
|
-
edge = "";
|
|
2104
|
-
break;
|
|
2105
|
-
default:
|
|
2106
|
-
break;
|
|
2107
|
-
}
|
|
2108
|
-
const tls = asBool(get(single, "tls")) ? "tls" : "";
|
|
2109
|
-
vmessConstruct(node, {
|
|
2110
|
-
add: server,
|
|
2111
|
-
aid,
|
|
2112
|
-
cipher,
|
|
2113
|
-
edge,
|
|
2114
|
-
group: group2,
|
|
2115
|
-
host,
|
|
2116
|
-
id,
|
|
2117
|
-
net,
|
|
2118
|
-
path,
|
|
2119
|
-
port,
|
|
2120
|
-
remark: ps,
|
|
2121
|
-
scv,
|
|
2122
|
-
sni,
|
|
2123
|
-
tfo,
|
|
2124
|
-
tls,
|
|
2125
|
-
type: "",
|
|
2126
|
-
udp,
|
|
2127
|
-
underlyingProxy
|
|
2128
|
-
});
|
|
2129
|
-
break;
|
|
2126
|
+
try {
|
|
2127
|
+
if (parseClashNode(single, nodes, index)) {
|
|
2128
|
+
index += 1;
|
|
2130
2129
|
}
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
if (
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2130
|
+
} catch {
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
function parseClashNode(single, nodes, index) {
|
|
2135
|
+
const proxyType = asString(get(single, "type")).toLowerCase();
|
|
2136
|
+
const ps = asString(get(single, "name"));
|
|
2137
|
+
const server = asString(get(single, "server"));
|
|
2138
|
+
const port = asString(get(single, "port"));
|
|
2139
|
+
let underlyingProxy = asString(get(single, "underlying-proxy"));
|
|
2140
|
+
if (underlyingProxy === "") {
|
|
2141
|
+
underlyingProxy = asString(get(single, "dialer-proxy"));
|
|
2142
|
+
}
|
|
2143
|
+
if (port === "" || port === "0") {
|
|
2144
|
+
return false;
|
|
2145
|
+
}
|
|
2146
|
+
const udp = asTri(get(single, "udp"));
|
|
2147
|
+
const tfo = asTri(get(single, "fast-open"));
|
|
2148
|
+
const scv = asTri(get(single, "skip-cert-verify"));
|
|
2149
|
+
const node = createProxy();
|
|
2150
|
+
let group2 = "";
|
|
2151
|
+
switch (proxyType) {
|
|
2152
|
+
case "vmess": {
|
|
2153
|
+
group2 = DEFAULT_GROUPS.v2ray;
|
|
2154
|
+
const id = asString(get(single, "uuid"));
|
|
2155
|
+
const aid = asString(get(single, "alterId"));
|
|
2156
|
+
const cipher = asString(get(single, "cipher"));
|
|
2157
|
+
const net = get(single, "network") !== void 0 ? asString(get(single, "network")) : "tcp";
|
|
2158
|
+
const sni = asString(get(single, "servername"));
|
|
2159
|
+
let path = "";
|
|
2160
|
+
let host = "";
|
|
2161
|
+
let edge = "";
|
|
2162
|
+
switch (net) {
|
|
2163
|
+
case "http":
|
|
2164
|
+
path = asString(get(get(get(single, "http-opts"), "path"), 0));
|
|
2165
|
+
host = asString(get(get(get(get(single, "http-opts"), "headers"), "Host"), 0));
|
|
2166
|
+
edge = "";
|
|
2167
|
+
break;
|
|
2168
|
+
case "ws":
|
|
2169
|
+
if (get(single, "ws-opts") !== void 0) {
|
|
2170
|
+
const wsOpts = get(single, "ws-opts");
|
|
2171
|
+
path = get(wsOpts, "path") !== void 0 ? asString(get(wsOpts, "path")) : "/";
|
|
2172
|
+
host = asString(get(get(wsOpts, "headers"), "Host"));
|
|
2173
|
+
edge = asString(get(get(wsOpts, "headers"), "Edge"));
|
|
2174
|
+
} else {
|
|
2175
|
+
path = get(single, "ws-path") !== void 0 ? asString(get(single, "ws-path")) : "/";
|
|
2176
|
+
host = asString(get(get(single, "ws-headers"), "Host"));
|
|
2177
|
+
edge = asString(get(get(single, "ws-headers"), "Edge"));
|
|
2175
2178
|
}
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
remark: ps,
|
|
2190
|
-
scv,
|
|
2191
|
-
server,
|
|
2192
|
-
tfo,
|
|
2193
|
-
udp,
|
|
2194
|
-
underlyingProxy
|
|
2195
|
-
});
|
|
2196
|
-
break;
|
|
2197
|
-
}
|
|
2198
|
-
case "socks5": {
|
|
2199
|
-
group2 = DEFAULT_GROUPS.socks;
|
|
2200
|
-
const user = asString(get(single, "username"));
|
|
2201
|
-
const password = asString(get(single, "password"));
|
|
2202
|
-
socksConstruct(node, {
|
|
2203
|
-
group: group2,
|
|
2204
|
-
password,
|
|
2205
|
-
port,
|
|
2206
|
-
remark: ps,
|
|
2207
|
-
server,
|
|
2208
|
-
underlyingProxy,
|
|
2209
|
-
username: user
|
|
2210
|
-
});
|
|
2211
|
-
break;
|
|
2212
|
-
}
|
|
2213
|
-
case "ssr": {
|
|
2214
|
-
group2 = DEFAULT_GROUPS.ssr;
|
|
2215
|
-
let cipher = asString(get(single, "cipher"));
|
|
2216
|
-
if (cipher === "dummy") {
|
|
2217
|
-
cipher = "none";
|
|
2218
|
-
}
|
|
2219
|
-
const password = asString(get(single, "password"));
|
|
2220
|
-
const protocol = asString(get(single, "protocol"));
|
|
2221
|
-
const obfs = asString(get(single, "obfs"));
|
|
2222
|
-
const protocolParam = get(single, "protocol-param") !== void 0 ? asString(get(single, "protocol-param")) : asString(get(single, "protocolparam"));
|
|
2223
|
-
const obfsParam = get(single, "obfs-param") !== void 0 ? asString(get(single, "obfs-param")) : asString(get(single, "obfsparam"));
|
|
2224
|
-
ssrConstruct(node, {
|
|
2225
|
-
group: group2,
|
|
2226
|
-
method: cipher,
|
|
2227
|
-
obfs,
|
|
2228
|
-
obfsParam,
|
|
2229
|
-
password,
|
|
2230
|
-
port,
|
|
2231
|
-
protocol,
|
|
2232
|
-
protocolParam,
|
|
2233
|
-
remark: ps,
|
|
2234
|
-
scv,
|
|
2235
|
-
server,
|
|
2236
|
-
tfo,
|
|
2237
|
-
udp,
|
|
2238
|
-
underlyingProxy
|
|
2239
|
-
});
|
|
2240
|
-
break;
|
|
2241
|
-
}
|
|
2242
|
-
case "http": {
|
|
2243
|
-
group2 = DEFAULT_GROUPS.http;
|
|
2244
|
-
const user = asString(get(single, "username"));
|
|
2245
|
-
const password = asString(get(single, "password"));
|
|
2246
|
-
const tls = asString(get(single, "tls"));
|
|
2247
|
-
httpConstruct(node, {
|
|
2248
|
-
group: group2,
|
|
2249
|
-
password,
|
|
2250
|
-
port,
|
|
2251
|
-
remark: ps,
|
|
2252
|
-
scv,
|
|
2253
|
-
server,
|
|
2254
|
-
tfo,
|
|
2255
|
-
tls: tls === "true",
|
|
2256
|
-
underlyingProxy,
|
|
2257
|
-
username: user
|
|
2258
|
-
});
|
|
2259
|
-
break;
|
|
2179
|
+
break;
|
|
2180
|
+
case "h2":
|
|
2181
|
+
path = asString(get(get(single, "h2-opts"), "path"));
|
|
2182
|
+
host = asString(get(get(get(single, "h2-opts"), "host"), 0));
|
|
2183
|
+
edge = "";
|
|
2184
|
+
break;
|
|
2185
|
+
case "grpc":
|
|
2186
|
+
host = asString(get(single, "servername"));
|
|
2187
|
+
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
2188
|
+
edge = "";
|
|
2189
|
+
break;
|
|
2190
|
+
default:
|
|
2191
|
+
break;
|
|
2260
2192
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2193
|
+
const tls = asBool(get(single, "tls")) ? "tls" : "";
|
|
2194
|
+
vmessConstruct(node, {
|
|
2195
|
+
add: server,
|
|
2196
|
+
aid,
|
|
2197
|
+
cipher,
|
|
2198
|
+
edge,
|
|
2199
|
+
group: group2,
|
|
2200
|
+
host,
|
|
2201
|
+
id,
|
|
2202
|
+
net,
|
|
2203
|
+
path,
|
|
2204
|
+
port,
|
|
2205
|
+
remark: ps,
|
|
2206
|
+
scv,
|
|
2207
|
+
sni,
|
|
2208
|
+
tfo,
|
|
2209
|
+
tls,
|
|
2210
|
+
type: "",
|
|
2211
|
+
udp,
|
|
2212
|
+
underlyingProxy
|
|
2213
|
+
});
|
|
2214
|
+
break;
|
|
2215
|
+
}
|
|
2216
|
+
case "ss": {
|
|
2217
|
+
group2 = DEFAULT_GROUPS.ss;
|
|
2218
|
+
let cipher = asString(get(single, "cipher"));
|
|
2219
|
+
const password = asString(get(single, "password"));
|
|
2220
|
+
let plugin = "";
|
|
2221
|
+
let pluginOption = "";
|
|
2222
|
+
let pluginMode = "";
|
|
2223
|
+
let pluginHost = "";
|
|
2224
|
+
let pluginMux = "";
|
|
2225
|
+
let pluginTls = "";
|
|
2226
|
+
let path = "";
|
|
2227
|
+
if (get(single, "plugin") !== void 0) {
|
|
2228
|
+
const pluginName = asString(get(single, "plugin")).toLowerCase();
|
|
2229
|
+
const pluginOpts = get(single, "plugin-opts");
|
|
2230
|
+
if (pluginName === "obfs") {
|
|
2231
|
+
plugin = "obfs-local";
|
|
2232
|
+
pluginMode = asString(get(pluginOpts, "mode"));
|
|
2233
|
+
pluginHost = asString(get(pluginOpts, "host"));
|
|
2234
|
+
} else if (pluginName === "v2ray-plugin") {
|
|
2235
|
+
plugin = "v2ray-plugin";
|
|
2236
|
+
pluginMode = asString(get(pluginOpts, "mode"));
|
|
2237
|
+
pluginHost = asString(get(pluginOpts, "host"));
|
|
2238
|
+
pluginTls = asBool(get(pluginOpts, "tls")) ? "tls;" : "";
|
|
2239
|
+
path = asString(get(pluginOpts, "path"));
|
|
2240
|
+
pluginMux = asBool(get(pluginOpts, "mux")) ? "mux=4;" : "";
|
|
2278
2241
|
}
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
udp,
|
|
2292
|
-
underlyingProxy
|
|
2293
|
-
});
|
|
2294
|
-
break;
|
|
2295
|
-
}
|
|
2296
|
-
case "snell": {
|
|
2297
|
-
group2 = DEFAULT_GROUPS.snell;
|
|
2298
|
-
const password = asString(get(single, "psk"));
|
|
2299
|
-
const obfs = asString(get(get(single, "obfs-opts"), "mode"));
|
|
2300
|
-
const host = asString(get(get(single, "obfs-opts"), "host"));
|
|
2301
|
-
const version = asString(get(single, "version"));
|
|
2302
|
-
snellConstruct(node, {
|
|
2303
|
-
group: group2,
|
|
2304
|
-
host,
|
|
2305
|
-
obfs,
|
|
2306
|
-
password,
|
|
2307
|
-
port,
|
|
2308
|
-
remark: ps,
|
|
2309
|
-
scv,
|
|
2310
|
-
server,
|
|
2311
|
-
tfo,
|
|
2312
|
-
udp,
|
|
2313
|
-
underlyingProxy,
|
|
2314
|
-
version: toInt(version)
|
|
2315
|
-
});
|
|
2316
|
-
break;
|
|
2317
|
-
}
|
|
2318
|
-
case "wireguard": {
|
|
2319
|
-
group2 = DEFAULT_GROUPS.wireguard;
|
|
2320
|
-
const publicKey = asString(get(single, "public-key"));
|
|
2321
|
-
const privateKey = asString(get(single, "private-key"));
|
|
2322
|
-
const dns = get(single, "dns");
|
|
2323
|
-
const dnsServers = Array.isArray(dns) ? dns.map((d) => String(d)) : dns ? [String(dns)] : [];
|
|
2324
|
-
const mtu = asString(get(single, "mtu"));
|
|
2325
|
-
const psk = asString(get(single, "preshared-key"));
|
|
2326
|
-
const ip = asString(get(single, "ip"));
|
|
2327
|
-
const ipv6 = asString(get(single, "ipv6"));
|
|
2328
|
-
wireGuardConstruct(node, {
|
|
2329
|
-
dnsServers,
|
|
2330
|
-
group: group2,
|
|
2331
|
-
keepAlive: "0",
|
|
2332
|
-
mtu,
|
|
2333
|
-
port,
|
|
2334
|
-
preSharedKey: psk,
|
|
2335
|
-
privateKey,
|
|
2336
|
-
publicKey,
|
|
2337
|
-
remark: ps,
|
|
2338
|
-
selfIp: ip,
|
|
2339
|
-
selfIpv6: ipv6,
|
|
2340
|
-
server,
|
|
2341
|
-
testUrl: "",
|
|
2342
|
-
udp,
|
|
2343
|
-
underlyingProxy
|
|
2344
|
-
});
|
|
2345
|
-
break;
|
|
2346
|
-
}
|
|
2347
|
-
case "hysteria": {
|
|
2348
|
-
group2 = DEFAULT_GROUPS.hysteria;
|
|
2349
|
-
const ports = asString(get(single, "ports"));
|
|
2350
|
-
const protocol = asString(get(single, "protocol"));
|
|
2351
|
-
const obfsProtocol = asString(get(single, "obfs-protocol"));
|
|
2352
|
-
const up = asString(get(single, "up"));
|
|
2353
|
-
const upSpeed = asString(get(single, "up-speed"));
|
|
2354
|
-
const down = asString(get(single, "down"));
|
|
2355
|
-
const downSpeed = asString(get(single, "down-speed"));
|
|
2356
|
-
const auth = asString(get(single, "auth"));
|
|
2357
|
-
let authStr = asString(get(single, "auth-str"));
|
|
2358
|
-
if (authStr === "") {
|
|
2359
|
-
authStr = asString(get(single, "auth_str"));
|
|
2242
|
+
} else if (get(single, "obfs") !== void 0) {
|
|
2243
|
+
plugin = "obfs-local";
|
|
2244
|
+
pluginMode = asString(get(single, "obfs"));
|
|
2245
|
+
pluginHost = asString(get(single, "obfs-host"));
|
|
2246
|
+
}
|
|
2247
|
+
if (plugin === "simple-obfs" || plugin === "obfs-local") {
|
|
2248
|
+
pluginOption = `obfs=${pluginMode}`;
|
|
2249
|
+
pluginOption += pluginHost === "" ? "" : `;obfs-host=${pluginHost}`;
|
|
2250
|
+
} else if (plugin === "v2ray-plugin") {
|
|
2251
|
+
pluginOption = `mode=${pluginMode};${pluginTls}${pluginMux}`;
|
|
2252
|
+
if (pluginHost !== "") {
|
|
2253
|
+
pluginOption += `host=${pluginHost};`;
|
|
2360
2254
|
}
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
const fingerprint = asString(get(single, "fingerprint"));
|
|
2364
|
-
const alpnValue = get(single, "alpn");
|
|
2365
|
-
const alpn = Array.isArray(alpnValue) ? asString(alpnValue[0]) : asString(alpnValue);
|
|
2366
|
-
const ca = asString(get(single, "ca"));
|
|
2367
|
-
const caStr = asString(get(single, "ca-str"));
|
|
2368
|
-
const recvWindowConn = asString(get(single, "recv-window-conn"));
|
|
2369
|
-
const recvWindow = asString(get(single, "recv-window"));
|
|
2370
|
-
let disableMtuDiscovery = asString(get(single, "disable-mtu-discovery"));
|
|
2371
|
-
if (disableMtuDiscovery === "") {
|
|
2372
|
-
disableMtuDiscovery = asString(get(single, "disable_mtu_discovery"));
|
|
2255
|
+
if (path !== "") {
|
|
2256
|
+
pluginOption += `path=${path};`;
|
|
2373
2257
|
}
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
alpn,
|
|
2377
|
-
auth,
|
|
2378
|
-
authStr,
|
|
2379
|
-
ca,
|
|
2380
|
-
caStr,
|
|
2381
|
-
disableMtuDiscovery,
|
|
2382
|
-
down,
|
|
2383
|
-
downSpeed,
|
|
2384
|
-
fingerprint,
|
|
2385
|
-
group: group2,
|
|
2386
|
-
hopInterval,
|
|
2387
|
-
obfs,
|
|
2388
|
-
obfsProtocol,
|
|
2389
|
-
port,
|
|
2390
|
-
ports,
|
|
2391
|
-
protocol,
|
|
2392
|
-
recvWindow,
|
|
2393
|
-
recvWindowConn,
|
|
2394
|
-
remark: ps,
|
|
2395
|
-
scv,
|
|
2396
|
-
server,
|
|
2397
|
-
sni,
|
|
2398
|
-
tfo,
|
|
2399
|
-
underlyingProxy,
|
|
2400
|
-
up,
|
|
2401
|
-
upSpeed
|
|
2402
|
-
});
|
|
2403
|
-
break;
|
|
2404
|
-
}
|
|
2405
|
-
case "hysteria2": {
|
|
2406
|
-
group2 = DEFAULT_GROUPS.hysteria2;
|
|
2407
|
-
const ports = asString(get(single, "ports"));
|
|
2408
|
-
const up = asString(get(single, "up"));
|
|
2409
|
-
const down = asString(get(single, "down"));
|
|
2410
|
-
let password = asString(get(single, "password"));
|
|
2411
|
-
if (password === "") {
|
|
2412
|
-
password = asString(get(single, "auth"));
|
|
2258
|
+
if (pluginMux !== "") {
|
|
2259
|
+
pluginOption += `mux=${pluginMux};`;
|
|
2413
2260
|
}
|
|
2414
|
-
const obfs = asString(get(single, "obfs"));
|
|
2415
|
-
const obfsPassword = asString(get(single, "obfs-password"));
|
|
2416
|
-
const sni = asString(get(single, "sni"));
|
|
2417
|
-
const fingerprint = asString(get(single, "fingerprint"));
|
|
2418
|
-
const alpnValue = get(single, "alpn");
|
|
2419
|
-
const alpn = Array.isArray(alpnValue) ? asString(alpnValue[0]) : asString(alpnValue);
|
|
2420
|
-
const ca = asString(get(single, "ca"));
|
|
2421
|
-
const caStr = asString(get(single, "ca-str"));
|
|
2422
|
-
const cwnd = asString(get(single, "cwnd"));
|
|
2423
|
-
const hopInterval = asString(get(single, "hop-interval"));
|
|
2424
|
-
hysteria2Construct(node, {
|
|
2425
|
-
alpn,
|
|
2426
|
-
ca,
|
|
2427
|
-
caStr,
|
|
2428
|
-
cwnd,
|
|
2429
|
-
down,
|
|
2430
|
-
fingerprint,
|
|
2431
|
-
group: group2,
|
|
2432
|
-
hopInterval,
|
|
2433
|
-
obfs,
|
|
2434
|
-
obfsPassword,
|
|
2435
|
-
password,
|
|
2436
|
-
port,
|
|
2437
|
-
ports,
|
|
2438
|
-
remark: ps,
|
|
2439
|
-
scv,
|
|
2440
|
-
server,
|
|
2441
|
-
sni,
|
|
2442
|
-
tfo,
|
|
2443
|
-
underlyingProxy,
|
|
2444
|
-
up
|
|
2445
|
-
});
|
|
2446
|
-
break;
|
|
2447
|
-
}
|
|
2448
|
-
case "anytls": {
|
|
2449
|
-
group2 = DEFAULT_GROUPS.anytls;
|
|
2450
|
-
const password = asString(get(single, "password"));
|
|
2451
|
-
const sni = asString(get(single, "sni"));
|
|
2452
|
-
anyTlsConstruct(node, {
|
|
2453
|
-
group: group2,
|
|
2454
|
-
password,
|
|
2455
|
-
port,
|
|
2456
|
-
remark: ps,
|
|
2457
|
-
scv,
|
|
2458
|
-
server,
|
|
2459
|
-
sni,
|
|
2460
|
-
tfo,
|
|
2461
|
-
udp,
|
|
2462
|
-
underlyingProxy
|
|
2463
|
-
});
|
|
2464
|
-
break;
|
|
2465
2261
|
}
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
const tls = asString(get(single, "tls"));
|
|
2471
|
-
let path = "";
|
|
2472
|
-
let host = "";
|
|
2473
|
-
if (net === "ws") {
|
|
2474
|
-
path = asString(get(get(single, "ws-opts"), "path"));
|
|
2475
|
-
host = asString(get(get(get(single, "ws-opts"), "headers"), "Host"));
|
|
2476
|
-
} else if (net === "grpc") {
|
|
2477
|
-
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
2478
|
-
}
|
|
2479
|
-
const alpnValue = get(single, "alpn");
|
|
2480
|
-
vlessConstruct(node, {
|
|
2481
|
-
alpn: Array.isArray(alpnValue) ? alpnValue.map((a) => String(a)) : void 0,
|
|
2482
|
-
encryption: asString(get(single, "encryption")),
|
|
2483
|
-
fingerprint: asString(get(single, "client-fingerprint")),
|
|
2484
|
-
flow: asString(get(single, "flow")),
|
|
2485
|
-
group: group2,
|
|
2486
|
-
host,
|
|
2487
|
-
network: net,
|
|
2488
|
-
path,
|
|
2489
|
-
port,
|
|
2490
|
-
remark: ps,
|
|
2491
|
-
scv,
|
|
2492
|
-
server,
|
|
2493
|
-
sni: asString(get(single, "servername")),
|
|
2494
|
-
tfo,
|
|
2495
|
-
tls: tls === "true" ? "tls" : "",
|
|
2496
|
-
udp,
|
|
2497
|
-
underlyingProxy,
|
|
2498
|
-
userId
|
|
2499
|
-
});
|
|
2500
|
-
break;
|
|
2262
|
+
if (cipher === "AEAD_CHACHA20_POLY1305") {
|
|
2263
|
+
cipher = "chacha20-ietf-poly1305";
|
|
2264
|
+
} else if (cipher.includes("AEAD")) {
|
|
2265
|
+
cipher = cipher.replace(/AEAD_/g, "").replace(/_/g, "-").toLowerCase();
|
|
2501
2266
|
}
|
|
2502
|
-
|
|
2503
|
-
group2
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2267
|
+
ssConstruct(node, {
|
|
2268
|
+
group: group2,
|
|
2269
|
+
method: cipher,
|
|
2270
|
+
password,
|
|
2271
|
+
plugin,
|
|
2272
|
+
pluginOption,
|
|
2273
|
+
port,
|
|
2274
|
+
remark: ps,
|
|
2275
|
+
scv,
|
|
2276
|
+
server,
|
|
2277
|
+
tfo,
|
|
2278
|
+
udp,
|
|
2279
|
+
underlyingProxy
|
|
2280
|
+
});
|
|
2281
|
+
break;
|
|
2282
|
+
}
|
|
2283
|
+
case "socks5": {
|
|
2284
|
+
group2 = DEFAULT_GROUPS.socks;
|
|
2285
|
+
const user = asString(get(single, "username"));
|
|
2286
|
+
const password = asString(get(single, "password"));
|
|
2287
|
+
socksConstruct(node, {
|
|
2288
|
+
group: group2,
|
|
2289
|
+
password,
|
|
2290
|
+
port,
|
|
2291
|
+
remark: ps,
|
|
2292
|
+
server,
|
|
2293
|
+
underlyingProxy,
|
|
2294
|
+
username: user
|
|
2295
|
+
});
|
|
2296
|
+
break;
|
|
2297
|
+
}
|
|
2298
|
+
case "ssr": {
|
|
2299
|
+
group2 = DEFAULT_GROUPS.ssr;
|
|
2300
|
+
let cipher = asString(get(single, "cipher"));
|
|
2301
|
+
if (cipher === "dummy") {
|
|
2302
|
+
cipher = "none";
|
|
2303
|
+
}
|
|
2304
|
+
const password = asString(get(single, "password"));
|
|
2305
|
+
const protocol = asString(get(single, "protocol"));
|
|
2306
|
+
const obfs = asString(get(single, "obfs"));
|
|
2307
|
+
const protocolParam = get(single, "protocol-param") !== void 0 ? asString(get(single, "protocol-param")) : asString(get(single, "protocolparam"));
|
|
2308
|
+
const obfsParam = get(single, "obfs-param") !== void 0 ? asString(get(single, "obfs-param")) : asString(get(single, "obfsparam"));
|
|
2309
|
+
ssrConstruct(node, {
|
|
2310
|
+
group: group2,
|
|
2311
|
+
method: cipher,
|
|
2312
|
+
obfs,
|
|
2313
|
+
obfsParam,
|
|
2314
|
+
password,
|
|
2315
|
+
port,
|
|
2316
|
+
protocol,
|
|
2317
|
+
protocolParam,
|
|
2318
|
+
remark: ps,
|
|
2319
|
+
scv,
|
|
2320
|
+
server,
|
|
2321
|
+
tfo,
|
|
2322
|
+
udp,
|
|
2323
|
+
underlyingProxy
|
|
2324
|
+
});
|
|
2325
|
+
break;
|
|
2326
|
+
}
|
|
2327
|
+
case "http": {
|
|
2328
|
+
group2 = DEFAULT_GROUPS.http;
|
|
2329
|
+
const user = asString(get(single, "username"));
|
|
2330
|
+
const password = asString(get(single, "password"));
|
|
2331
|
+
const tls = asString(get(single, "tls"));
|
|
2332
|
+
httpConstruct(node, {
|
|
2333
|
+
group: group2,
|
|
2334
|
+
password,
|
|
2335
|
+
port,
|
|
2336
|
+
remark: ps,
|
|
2337
|
+
scv,
|
|
2338
|
+
server,
|
|
2339
|
+
tfo,
|
|
2340
|
+
tls: tls === "true",
|
|
2341
|
+
underlyingProxy,
|
|
2342
|
+
username: user
|
|
2343
|
+
});
|
|
2344
|
+
break;
|
|
2345
|
+
}
|
|
2346
|
+
case "trojan": {
|
|
2347
|
+
group2 = DEFAULT_GROUPS.trojan;
|
|
2348
|
+
const password = asString(get(single, "password"));
|
|
2349
|
+
const host = asString(get(single, "sni"));
|
|
2350
|
+
let net = asString(get(single, "network"));
|
|
2351
|
+
let path = "";
|
|
2352
|
+
switch (net) {
|
|
2353
|
+
case "grpc":
|
|
2354
|
+
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
2355
|
+
break;
|
|
2356
|
+
case "ws":
|
|
2357
|
+
path = asString(get(get(single, "ws-opts"), "path"));
|
|
2358
|
+
break;
|
|
2359
|
+
default:
|
|
2360
|
+
net = "tcp";
|
|
2361
|
+
path = "";
|
|
2362
|
+
break;
|
|
2521
2363
|
}
|
|
2522
|
-
|
|
2523
|
-
|
|
2364
|
+
trojanConstruct(node, {
|
|
2365
|
+
group: group2,
|
|
2366
|
+
host,
|
|
2367
|
+
network: net,
|
|
2368
|
+
password,
|
|
2369
|
+
path,
|
|
2370
|
+
port,
|
|
2371
|
+
remark: ps,
|
|
2372
|
+
scv,
|
|
2373
|
+
server,
|
|
2374
|
+
tfo,
|
|
2375
|
+
tlsSecure: true,
|
|
2376
|
+
udp,
|
|
2377
|
+
underlyingProxy
|
|
2378
|
+
});
|
|
2379
|
+
break;
|
|
2524
2380
|
}
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2381
|
+
case "snell": {
|
|
2382
|
+
group2 = DEFAULT_GROUPS.snell;
|
|
2383
|
+
const password = asString(get(single, "psk"));
|
|
2384
|
+
const obfs = asString(get(get(single, "obfs-opts"), "mode"));
|
|
2385
|
+
const host = asString(get(get(single, "obfs-opts"), "host"));
|
|
2386
|
+
const version = asString(get(single, "version"));
|
|
2387
|
+
snellConstruct(node, {
|
|
2388
|
+
group: group2,
|
|
2389
|
+
host,
|
|
2390
|
+
obfs,
|
|
2391
|
+
password,
|
|
2392
|
+
port,
|
|
2393
|
+
remark: ps,
|
|
2394
|
+
scv,
|
|
2395
|
+
server,
|
|
2396
|
+
tfo,
|
|
2397
|
+
udp,
|
|
2398
|
+
underlyingProxy,
|
|
2399
|
+
version: toInt(version)
|
|
2400
|
+
});
|
|
2401
|
+
break;
|
|
2402
|
+
}
|
|
2403
|
+
case "wireguard": {
|
|
2404
|
+
group2 = DEFAULT_GROUPS.wireguard;
|
|
2405
|
+
const publicKey = asString(get(single, "public-key"));
|
|
2406
|
+
const privateKey = asString(get(single, "private-key"));
|
|
2407
|
+
const dns = get(single, "dns");
|
|
2408
|
+
const dnsServers = Array.isArray(dns) ? dns.map((d) => String(d)) : dns ? [String(dns)] : [];
|
|
2409
|
+
const mtu = asString(get(single, "mtu"));
|
|
2410
|
+
const psk = asString(get(single, "preshared-key"));
|
|
2411
|
+
const ip = asString(get(single, "ip"));
|
|
2412
|
+
const ipv6 = asString(get(single, "ipv6"));
|
|
2413
|
+
wireGuardConstruct(node, {
|
|
2414
|
+
dnsServers,
|
|
2415
|
+
group: group2,
|
|
2416
|
+
keepAlive: "0",
|
|
2417
|
+
mtu,
|
|
2418
|
+
port,
|
|
2419
|
+
preSharedKey: psk,
|
|
2420
|
+
privateKey,
|
|
2421
|
+
publicKey,
|
|
2422
|
+
remark: ps,
|
|
2423
|
+
selfIp: ip,
|
|
2424
|
+
selfIpv6: ipv6,
|
|
2425
|
+
server,
|
|
2426
|
+
testUrl: "",
|
|
2427
|
+
udp,
|
|
2428
|
+
underlyingProxy
|
|
2429
|
+
});
|
|
2430
|
+
break;
|
|
2431
|
+
}
|
|
2432
|
+
case "hysteria": {
|
|
2433
|
+
group2 = DEFAULT_GROUPS.hysteria;
|
|
2434
|
+
const ports = asString(get(single, "ports"));
|
|
2435
|
+
const protocol = asString(get(single, "protocol"));
|
|
2436
|
+
const obfsProtocol = asString(get(single, "obfs-protocol"));
|
|
2437
|
+
const up = asString(get(single, "up"));
|
|
2438
|
+
const upSpeed = asString(get(single, "up-speed"));
|
|
2439
|
+
const down = asString(get(single, "down"));
|
|
2440
|
+
const downSpeed = asString(get(single, "down-speed"));
|
|
2441
|
+
const auth = asString(get(single, "auth"));
|
|
2442
|
+
let authStr = asString(get(single, "auth-str"));
|
|
2443
|
+
if (authStr === "") {
|
|
2444
|
+
authStr = asString(get(single, "auth_str"));
|
|
2445
|
+
}
|
|
2446
|
+
const obfs = asString(get(single, "obfs"));
|
|
2447
|
+
const sni = asString(get(single, "sni"));
|
|
2448
|
+
const fingerprint = asString(get(single, "fingerprint"));
|
|
2449
|
+
const alpnValue = get(single, "alpn");
|
|
2450
|
+
const alpn = Array.isArray(alpnValue) ? asString(alpnValue[0]) : asString(alpnValue);
|
|
2451
|
+
const ca = asString(get(single, "ca"));
|
|
2452
|
+
const caStr = asString(get(single, "ca-str"));
|
|
2453
|
+
const recvWindowConn = asString(get(single, "recv-window-conn"));
|
|
2454
|
+
const recvWindow = asString(get(single, "recv-window"));
|
|
2455
|
+
let disableMtuDiscovery = asString(get(single, "disable-mtu-discovery"));
|
|
2456
|
+
if (disableMtuDiscovery === "") {
|
|
2457
|
+
disableMtuDiscovery = asString(get(single, "disable_mtu_discovery"));
|
|
2458
|
+
}
|
|
2459
|
+
const hopInterval = asString(get(single, "hop-interval"));
|
|
2460
|
+
hysteriaConstruct(node, {
|
|
2461
|
+
alpn,
|
|
2462
|
+
auth,
|
|
2463
|
+
authStr,
|
|
2464
|
+
ca,
|
|
2465
|
+
caStr,
|
|
2466
|
+
disableMtuDiscovery,
|
|
2467
|
+
down,
|
|
2468
|
+
downSpeed,
|
|
2469
|
+
fingerprint,
|
|
2470
|
+
group: group2,
|
|
2471
|
+
hopInterval,
|
|
2472
|
+
obfs,
|
|
2473
|
+
obfsProtocol,
|
|
2474
|
+
port,
|
|
2475
|
+
ports,
|
|
2476
|
+
protocol,
|
|
2477
|
+
recvWindow,
|
|
2478
|
+
recvWindowConn,
|
|
2479
|
+
remark: ps,
|
|
2480
|
+
scv,
|
|
2481
|
+
server,
|
|
2482
|
+
sni,
|
|
2483
|
+
tfo,
|
|
2484
|
+
underlyingProxy,
|
|
2485
|
+
up,
|
|
2486
|
+
upSpeed
|
|
2487
|
+
});
|
|
2488
|
+
break;
|
|
2489
|
+
}
|
|
2490
|
+
case "hysteria2": {
|
|
2491
|
+
group2 = DEFAULT_GROUPS.hysteria2;
|
|
2492
|
+
const ports = asString(get(single, "ports"));
|
|
2493
|
+
const up = asString(get(single, "up"));
|
|
2494
|
+
const down = asString(get(single, "down"));
|
|
2495
|
+
let password = asString(get(single, "password"));
|
|
2496
|
+
if (password === "") {
|
|
2497
|
+
password = asString(get(single, "auth"));
|
|
2498
|
+
}
|
|
2499
|
+
const obfs = asString(get(single, "obfs"));
|
|
2500
|
+
const obfsPassword = asString(get(single, "obfs-password"));
|
|
2501
|
+
const sni = asString(get(single, "sni"));
|
|
2502
|
+
const fingerprint = asString(get(single, "fingerprint"));
|
|
2503
|
+
const alpnValue = get(single, "alpn");
|
|
2504
|
+
const alpn = Array.isArray(alpnValue) ? asString(alpnValue[0]) : asString(alpnValue);
|
|
2505
|
+
const ca = asString(get(single, "ca"));
|
|
2506
|
+
const caStr = asString(get(single, "ca-str"));
|
|
2507
|
+
const cwnd = asString(get(single, "cwnd"));
|
|
2508
|
+
const hopInterval = asString(get(single, "hop-interval"));
|
|
2509
|
+
hysteria2Construct(node, {
|
|
2510
|
+
alpn,
|
|
2511
|
+
ca,
|
|
2512
|
+
caStr,
|
|
2513
|
+
cwnd,
|
|
2514
|
+
down,
|
|
2515
|
+
fingerprint,
|
|
2516
|
+
group: group2,
|
|
2517
|
+
hopInterval,
|
|
2518
|
+
obfs,
|
|
2519
|
+
obfsPassword,
|
|
2520
|
+
password,
|
|
2521
|
+
port,
|
|
2522
|
+
ports,
|
|
2523
|
+
remark: ps,
|
|
2524
|
+
scv,
|
|
2525
|
+
server,
|
|
2526
|
+
sni,
|
|
2527
|
+
tfo,
|
|
2528
|
+
underlyingProxy,
|
|
2529
|
+
up
|
|
2530
|
+
});
|
|
2531
|
+
break;
|
|
2532
|
+
}
|
|
2533
|
+
case "anytls": {
|
|
2534
|
+
group2 = DEFAULT_GROUPS.anytls;
|
|
2535
|
+
const password = asString(get(single, "password"));
|
|
2536
|
+
const sni = asString(get(single, "sni"));
|
|
2537
|
+
anyTlsConstruct(node, {
|
|
2538
|
+
group: group2,
|
|
2539
|
+
password,
|
|
2540
|
+
port,
|
|
2541
|
+
remark: ps,
|
|
2542
|
+
scv,
|
|
2543
|
+
server,
|
|
2544
|
+
sni,
|
|
2545
|
+
tfo,
|
|
2546
|
+
udp,
|
|
2547
|
+
underlyingProxy
|
|
2548
|
+
});
|
|
2549
|
+
break;
|
|
2550
|
+
}
|
|
2551
|
+
case "vless": {
|
|
2552
|
+
group2 = DEFAULT_GROUPS.v2ray;
|
|
2553
|
+
const userId = asString(get(single, "uuid"));
|
|
2554
|
+
const net = asString(get(single, "network"));
|
|
2555
|
+
const tls = asString(get(single, "tls"));
|
|
2556
|
+
let path = "";
|
|
2557
|
+
let host = "";
|
|
2558
|
+
if (net === "ws") {
|
|
2559
|
+
path = asString(get(get(single, "ws-opts"), "path"));
|
|
2560
|
+
host = asString(get(get(get(single, "ws-opts"), "headers"), "Host"));
|
|
2561
|
+
} else if (net === "grpc") {
|
|
2562
|
+
path = asString(get(get(single, "grpc-opts"), "grpc-service-name"));
|
|
2563
|
+
}
|
|
2564
|
+
const alpnValue = get(single, "alpn");
|
|
2565
|
+
vlessConstruct(node, {
|
|
2566
|
+
alpn: Array.isArray(alpnValue) ? alpnValue.map((a) => String(a)) : void 0,
|
|
2567
|
+
encryption: asString(get(single, "encryption")),
|
|
2568
|
+
fingerprint: asString(get(single, "client-fingerprint")),
|
|
2569
|
+
flow: asString(get(single, "flow")),
|
|
2570
|
+
group: group2,
|
|
2571
|
+
host,
|
|
2572
|
+
network: net,
|
|
2573
|
+
path,
|
|
2574
|
+
port,
|
|
2575
|
+
remark: ps,
|
|
2576
|
+
scv,
|
|
2577
|
+
server,
|
|
2578
|
+
sni: asString(get(single, "servername")),
|
|
2579
|
+
tfo,
|
|
2580
|
+
tls: tls === "true" ? "tls" : "",
|
|
2581
|
+
udp,
|
|
2582
|
+
underlyingProxy,
|
|
2583
|
+
userId
|
|
2584
|
+
});
|
|
2585
|
+
break;
|
|
2586
|
+
}
|
|
2587
|
+
case "tuic": {
|
|
2588
|
+
group2 = DEFAULT_GROUPS.v2ray;
|
|
2589
|
+
const alpnValue = get(single, "alpn");
|
|
2590
|
+
tuicConstruct(node, {
|
|
2591
|
+
alpn: Array.isArray(alpnValue) ? alpnValue.map((a) => String(a)) : void 0,
|
|
2592
|
+
congestionControl: asString(get(single, "congestion-controller")),
|
|
2593
|
+
group: group2,
|
|
2594
|
+
password: asString(get(single, "password")),
|
|
2595
|
+
port,
|
|
2596
|
+
remark: ps,
|
|
2597
|
+
scv,
|
|
2598
|
+
server,
|
|
2599
|
+
sni: asString(get(single, "sni")),
|
|
2600
|
+
tfo,
|
|
2601
|
+
udp,
|
|
2602
|
+
underlyingProxy,
|
|
2603
|
+
userId: asString(get(single, "uuid"))
|
|
2604
|
+
});
|
|
2605
|
+
break;
|
|
2606
|
+
}
|
|
2607
|
+
default:
|
|
2608
|
+
return false;
|
|
2528
2609
|
}
|
|
2610
|
+
node.id = index;
|
|
2611
|
+
nodes.push(node);
|
|
2612
|
+
return true;
|
|
2529
2613
|
}
|
|
2530
2614
|
function parseRawSections(text) {
|
|
2531
2615
|
const sections = [];
|
|
@@ -4133,7 +4217,10 @@ function explodeSs(ss, node) {
|
|
|
4133
4217
|
const secret = match[1];
|
|
4134
4218
|
server = match[2];
|
|
4135
4219
|
port = match[3];
|
|
4136
|
-
const
|
|
4220
|
+
const raw = urlDecode(secret);
|
|
4221
|
+
const decoded = firstMatch(urlSafeBase64Decode(raw), "(\\S+?):(\\S+)");
|
|
4222
|
+
const plaintext = firstMatch(raw, "(\\S+?):(\\S+)");
|
|
4223
|
+
const secretMatch = decoded && isSsCipher(decoded[1]) ? decoded : plaintext ?? decoded;
|
|
4137
4224
|
if (!secretMatch) {
|
|
4138
4225
|
return;
|
|
4139
4226
|
}
|
|
@@ -4598,6 +4685,157 @@ function explodeAnyTls(link, node) {
|
|
|
4598
4685
|
udp: udp === "" ? void 0 : parseTri(udp)
|
|
4599
4686
|
});
|
|
4600
4687
|
}
|
|
4688
|
+
function explodeSnell(link, node) {
|
|
4689
|
+
let body = link.slice(8);
|
|
4690
|
+
let remark = "";
|
|
4691
|
+
let addition = "";
|
|
4692
|
+
const hashPos = body.lastIndexOf("#");
|
|
4693
|
+
if (hashPos !== -1) {
|
|
4694
|
+
remark = urlDecode(body.slice(hashPos + 1));
|
|
4695
|
+
body = body.slice(0, hashPos);
|
|
4696
|
+
}
|
|
4697
|
+
const qpos = body.lastIndexOf("?");
|
|
4698
|
+
if (qpos !== -1) {
|
|
4699
|
+
addition = body.slice(qpos + 1);
|
|
4700
|
+
body = body.slice(0, qpos);
|
|
4701
|
+
}
|
|
4702
|
+
const match = /^(.*?)@(.*)[:](\d+)$/.exec(body);
|
|
4703
|
+
if (!match) {
|
|
4704
|
+
return;
|
|
4705
|
+
}
|
|
4706
|
+
const password = match[1];
|
|
4707
|
+
const server = match[2];
|
|
4708
|
+
const port = match[3];
|
|
4709
|
+
if (password === "" || port === "" || port === "0") {
|
|
4710
|
+
return;
|
|
4711
|
+
}
|
|
4712
|
+
const obfs = getUrlArg(addition, "obfs");
|
|
4713
|
+
const host = getUrlArg(addition, "host");
|
|
4714
|
+
const version = getUrlArg(addition, "version");
|
|
4715
|
+
const udp = getUrlArg(addition, "udp");
|
|
4716
|
+
const tfo = getUrlArg(addition, "tfo");
|
|
4717
|
+
const scv = getUrlArg(addition, "skip-cert-verify");
|
|
4718
|
+
if (remark === "") {
|
|
4719
|
+
remark = `${server}:${port}`;
|
|
4720
|
+
}
|
|
4721
|
+
snellConstruct(node, {
|
|
4722
|
+
group: DEFAULT_GROUPS.snell,
|
|
4723
|
+
host,
|
|
4724
|
+
obfs: obfs === "" ? "none" : obfs,
|
|
4725
|
+
password,
|
|
4726
|
+
port,
|
|
4727
|
+
remark,
|
|
4728
|
+
scv: scv === "" ? void 0 : parseTri(scv),
|
|
4729
|
+
server,
|
|
4730
|
+
tfo: tfo === "" ? void 0 : parseTri(tfo),
|
|
4731
|
+
udp: udp === "" ? void 0 : parseTri(udp),
|
|
4732
|
+
version: version === "" ? 1 : toInt(version)
|
|
4733
|
+
});
|
|
4734
|
+
}
|
|
4735
|
+
function explodeHysteria(link, node) {
|
|
4736
|
+
let body = link.slice(11);
|
|
4737
|
+
let remark = "";
|
|
4738
|
+
let addition = "";
|
|
4739
|
+
const hashPos = body.lastIndexOf("#");
|
|
4740
|
+
if (hashPos !== -1) {
|
|
4741
|
+
remark = urlDecode(body.slice(hashPos + 1));
|
|
4742
|
+
body = body.slice(0, hashPos);
|
|
4743
|
+
}
|
|
4744
|
+
const qpos = body.lastIndexOf("?");
|
|
4745
|
+
if (qpos !== -1) {
|
|
4746
|
+
addition = body.slice(qpos + 1);
|
|
4747
|
+
body = body.slice(0, qpos);
|
|
4748
|
+
}
|
|
4749
|
+
const match = /^(.*)[:](\d+)$/.exec(body);
|
|
4750
|
+
if (!match) {
|
|
4751
|
+
return;
|
|
4752
|
+
}
|
|
4753
|
+
const server = match[1];
|
|
4754
|
+
const port = match[2];
|
|
4755
|
+
if (server === "" || port === "0") {
|
|
4756
|
+
return;
|
|
4757
|
+
}
|
|
4758
|
+
const auth = getUrlArg(addition, "auth");
|
|
4759
|
+
const protocol = getUrlArg(addition, "protocol");
|
|
4760
|
+
const upSpeed = getUrlArg(addition, "upmbps");
|
|
4761
|
+
const downSpeed = getUrlArg(addition, "downmbps");
|
|
4762
|
+
const alpn = getUrlArg(addition, "alpn");
|
|
4763
|
+
const obfs = getUrlArg(addition, "obfs");
|
|
4764
|
+
const obfsProtocol = getUrlArg(addition, "obfsParam");
|
|
4765
|
+
const sni = getUrlArg(addition, "peer");
|
|
4766
|
+
const insecure = getUrlArg(addition, "insecure");
|
|
4767
|
+
if (remark === "") {
|
|
4768
|
+
remark = `${server}:${port}`;
|
|
4769
|
+
}
|
|
4770
|
+
hysteriaConstruct(node, {
|
|
4771
|
+
alpn,
|
|
4772
|
+
authStr: auth,
|
|
4773
|
+
downSpeed,
|
|
4774
|
+
group: DEFAULT_GROUPS.hysteria,
|
|
4775
|
+
obfs,
|
|
4776
|
+
obfsProtocol,
|
|
4777
|
+
port,
|
|
4778
|
+
protocol: protocol === "" ? "udp" : protocol,
|
|
4779
|
+
remark,
|
|
4780
|
+
scv: insecure === "" ? void 0 : parseTri(insecure),
|
|
4781
|
+
server,
|
|
4782
|
+
sni: sni === "" ? server : sni,
|
|
4783
|
+
upSpeed
|
|
4784
|
+
});
|
|
4785
|
+
}
|
|
4786
|
+
function explodeWireguard(link, node) {
|
|
4787
|
+
const normalized = link.replace(/^(wg|wireguard):\/\//, "wireguard://");
|
|
4788
|
+
let body = normalized.slice(13);
|
|
4789
|
+
let remark = "";
|
|
4790
|
+
let addition = "";
|
|
4791
|
+
const hashPos = body.lastIndexOf("#");
|
|
4792
|
+
if (hashPos !== -1) {
|
|
4793
|
+
remark = urlDecode(body.slice(hashPos + 1));
|
|
4794
|
+
body = body.slice(0, hashPos);
|
|
4795
|
+
}
|
|
4796
|
+
const qpos = body.lastIndexOf("?");
|
|
4797
|
+
if (qpos !== -1) {
|
|
4798
|
+
addition = body.slice(qpos + 1);
|
|
4799
|
+
body = body.slice(0, qpos);
|
|
4800
|
+
}
|
|
4801
|
+
const match = /^(?:(.*)@)?\[?(.*?)]?:(\d+)$/.exec(body);
|
|
4802
|
+
if (!match) {
|
|
4803
|
+
return;
|
|
4804
|
+
}
|
|
4805
|
+
const server = match[2];
|
|
4806
|
+
const port = match[3];
|
|
4807
|
+
if (server === "" || port === "0") {
|
|
4808
|
+
return;
|
|
4809
|
+
}
|
|
4810
|
+
const privateKey = getUrlArg(addition, "privateKey") || getUrlArg(addition, "privatekey");
|
|
4811
|
+
const publicKey = getUrlArg(addition, "publicKey") || getUrlArg(addition, "publickey");
|
|
4812
|
+
if (privateKey === "" || publicKey === "") {
|
|
4813
|
+
return;
|
|
4814
|
+
}
|
|
4815
|
+
const presharedKey = getUrlArg(addition, "presharedKey");
|
|
4816
|
+
const selfIp = getUrlArg(addition, "selfIP");
|
|
4817
|
+
const selfIpv6 = getUrlArg(addition, "selfIPv6");
|
|
4818
|
+
const mtu = getUrlArg(addition, "mtu");
|
|
4819
|
+
const keepAlive = getUrlArg(addition, "keepAlive");
|
|
4820
|
+
const dns = getUrlArg(addition, "dns");
|
|
4821
|
+
if (remark === "") {
|
|
4822
|
+
remark = `${server}:${port}`;
|
|
4823
|
+
}
|
|
4824
|
+
wireGuardConstruct(node, {
|
|
4825
|
+
dnsServers: dns === "" ? ["1.1.1.1"] : dns.split(",").map((s) => s.trim()),
|
|
4826
|
+
group: DEFAULT_GROUPS.wireguard,
|
|
4827
|
+
keepAlive: keepAlive === "" ? 25 : toInt(keepAlive),
|
|
4828
|
+
mtu: mtu === "" ? 1420 : toInt(mtu),
|
|
4829
|
+
port,
|
|
4830
|
+
preSharedKey: presharedKey,
|
|
4831
|
+
privateKey,
|
|
4832
|
+
publicKey,
|
|
4833
|
+
remark,
|
|
4834
|
+
selfIp: selfIp === "" ? "10.0.0.2" : selfIp,
|
|
4835
|
+
selfIpv6,
|
|
4836
|
+
server
|
|
4837
|
+
});
|
|
4838
|
+
}
|
|
4601
4839
|
function explodeVless(link, node) {
|
|
4602
4840
|
let body = link.slice(8);
|
|
4603
4841
|
let remark = "";
|
|
@@ -4721,6 +4959,12 @@ function explode(link, node) {
|
|
|
4721
4959
|
explodeVless(link, node);
|
|
4722
4960
|
} else if (startsWith(link, "tuic://")) {
|
|
4723
4961
|
explodeTuic(link, node);
|
|
4962
|
+
} else if (startsWith(link, "snell://")) {
|
|
4963
|
+
explodeSnell(link, node);
|
|
4964
|
+
} else if (startsWith(link, "hysteria://")) {
|
|
4965
|
+
explodeHysteria(link, node);
|
|
4966
|
+
} else if (startsWith(link, "wg://") || startsWith(link, "wireguard://")) {
|
|
4967
|
+
explodeWireguard(link, node);
|
|
4724
4968
|
} else if (link.includes("hysteria2://") || link.includes("hy2://")) {
|
|
4725
4969
|
explodeHysteria2(link, node);
|
|
4726
4970
|
} else if (startsWith(link, "anytls://")) {
|
|
@@ -5117,7 +5361,11 @@ function normalizeRegionCode(code) {
|
|
|
5117
5361
|
const upper = code.trim().toUpperCase();
|
|
5118
5362
|
return /^[A-Z]{2}$/.test(upper) ? upper : "";
|
|
5119
5363
|
}
|
|
5120
|
-
function
|
|
5364
|
+
function normalizeCountryCode(code) {
|
|
5365
|
+
const upper = normalizeRegionCode(code);
|
|
5366
|
+
return upper !== "" && isRegionCode(upper) ? upper : void 0;
|
|
5367
|
+
}
|
|
5368
|
+
function displayName(code, locale) {
|
|
5121
5369
|
const upper = normalizeRegionCode(code);
|
|
5122
5370
|
if (upper === "") {
|
|
5123
5371
|
return code.trim();
|
|
@@ -5160,8 +5408,8 @@ function buildAliasRegex() {
|
|
|
5160
5408
|
}
|
|
5161
5409
|
};
|
|
5162
5410
|
for (const code of REGION_CODES) {
|
|
5163
|
-
add(
|
|
5164
|
-
add(
|
|
5411
|
+
add(displayName(code, "zh-CN"));
|
|
5412
|
+
add(displayName(code, "en"));
|
|
5165
5413
|
add(regionFlag(code));
|
|
5166
5414
|
}
|
|
5167
5415
|
for (const alias of EXTRA_ALIASES) {
|
|
@@ -5201,13 +5449,13 @@ function hasRegionName(remark) {
|
|
|
5201
5449
|
}
|
|
5202
5450
|
return false;
|
|
5203
5451
|
}
|
|
5204
|
-
function formatCountryRemark(remark, code
|
|
5205
|
-
const
|
|
5452
|
+
function formatCountryRemark(remark, code) {
|
|
5453
|
+
const normalized = normalizeCountryCode(code);
|
|
5206
5454
|
const trimmed = remark.trim();
|
|
5207
|
-
if (
|
|
5455
|
+
if (normalized === void 0) {
|
|
5208
5456
|
return trimmed;
|
|
5209
5457
|
}
|
|
5210
|
-
return trimmed === "" ?
|
|
5458
|
+
return trimmed === "" ? normalized : `${normalized}-${trimmed}`;
|
|
5211
5459
|
}
|
|
5212
5460
|
|
|
5213
5461
|
// src/generator/nodes.ts
|
|
@@ -5221,6 +5469,10 @@ function toRegex(pattern) {
|
|
|
5221
5469
|
function regFind(value, pattern) {
|
|
5222
5470
|
return toRegex(pattern).test(value);
|
|
5223
5471
|
}
|
|
5472
|
+
var REGEX_BLACKLIST = ["(.*)*"];
|
|
5473
|
+
function isBlacklistedPattern(pattern) {
|
|
5474
|
+
return REGEX_BLACKLIST.includes(pattern);
|
|
5475
|
+
}
|
|
5224
5476
|
function regMatch2(value, pattern) {
|
|
5225
5477
|
const match = toRegex(pattern).exec(value);
|
|
5226
5478
|
return match !== null && match[0] === value;
|
|
@@ -5466,7 +5718,7 @@ function nodeRename(node, renameArray) {
|
|
|
5466
5718
|
node.remark = original;
|
|
5467
5719
|
}
|
|
5468
5720
|
}
|
|
5469
|
-
function addCountryPrefix(node, resolve
|
|
5721
|
+
function addCountryPrefix(node, resolve) {
|
|
5470
5722
|
const remark = node.remark.trim();
|
|
5471
5723
|
if (hasRegionName(remark)) {
|
|
5472
5724
|
return node.remark;
|
|
@@ -5475,7 +5727,31 @@ function addCountryPrefix(node, resolve, locale = "zh-CN") {
|
|
|
5475
5727
|
if (code === void 0 || code === "") {
|
|
5476
5728
|
return node.remark;
|
|
5477
5729
|
}
|
|
5478
|
-
return formatCountryRemark(remark, code
|
|
5730
|
+
return formatCountryRemark(remark, code);
|
|
5731
|
+
}
|
|
5732
|
+
function filterNodesByCountry(nodes, resolve, include, exclude) {
|
|
5733
|
+
const includeSet = new Set(
|
|
5734
|
+
include.map((code) => normalizeCountryCode(code)).filter((code) => code !== void 0)
|
|
5735
|
+
);
|
|
5736
|
+
const excludeSet = new Set(
|
|
5737
|
+
exclude.map((code) => normalizeCountryCode(code)).filter((code) => code !== void 0)
|
|
5738
|
+
);
|
|
5739
|
+
if (includeSet.size === 0 && excludeSet.size === 0) {
|
|
5740
|
+
return;
|
|
5741
|
+
}
|
|
5742
|
+
const kept = [];
|
|
5743
|
+
for (const node of nodes) {
|
|
5744
|
+
const code = resolve ? normalizeCountryCode(resolve(node) ?? "") : void 0;
|
|
5745
|
+
if (includeSet.size > 0 && (code === void 0 || !includeSet.has(code))) {
|
|
5746
|
+
continue;
|
|
5747
|
+
}
|
|
5748
|
+
if (code !== void 0 && excludeSet.has(code)) {
|
|
5749
|
+
continue;
|
|
5750
|
+
}
|
|
5751
|
+
kept.push(node);
|
|
5752
|
+
}
|
|
5753
|
+
nodes.length = 0;
|
|
5754
|
+
nodes.push(...kept);
|
|
5479
5755
|
}
|
|
5480
5756
|
function preprocessNodes(nodes, options) {
|
|
5481
5757
|
for (const node of nodes) {
|
|
@@ -5493,13 +5769,25 @@ function preprocessNodes(nodes, options) {
|
|
|
5493
5769
|
node.remark = addEmoji(node, options.emojiArray);
|
|
5494
5770
|
}
|
|
5495
5771
|
if (options.autoCountry && options.countryResolver) {
|
|
5496
|
-
node.remark = addCountryPrefix(
|
|
5497
|
-
node,
|
|
5498
|
-
options.countryResolver,
|
|
5499
|
-
options.countryLocale ?? "zh-CN"
|
|
5500
|
-
);
|
|
5772
|
+
node.remark = addCountryPrefix(node, options.countryResolver);
|
|
5501
5773
|
}
|
|
5502
5774
|
}
|
|
5775
|
+
filterNodesByCountry(
|
|
5776
|
+
nodes,
|
|
5777
|
+
options.countryResolver,
|
|
5778
|
+
options.includeCountries ?? [],
|
|
5779
|
+
options.excludeCountries ?? []
|
|
5780
|
+
);
|
|
5781
|
+
const includeRemarks = options.includeRemarks ?? [];
|
|
5782
|
+
const excludeRemarks = options.excludeRemarks ?? [];
|
|
5783
|
+
if (includeRemarks.length > 0 || excludeRemarks.length > 0) {
|
|
5784
|
+
const kept = nodes.filter((node) => !checkIgnore(node, excludeRemarks, includeRemarks));
|
|
5785
|
+
kept.forEach((node, index) => {
|
|
5786
|
+
node.id = index;
|
|
5787
|
+
});
|
|
5788
|
+
nodes.length = 0;
|
|
5789
|
+
nodes.push(...kept);
|
|
5790
|
+
}
|
|
5503
5791
|
if (options.sortFlag) {
|
|
5504
5792
|
nodes.sort((a, b) => a.remark < b.remark ? -1 : a.remark > b.remark ? 1 : 0);
|
|
5505
5793
|
}
|
|
@@ -5556,12 +5844,59 @@ function stripBrackets(value) {
|
|
|
5556
5844
|
function toTri(value) {
|
|
5557
5845
|
return value;
|
|
5558
5846
|
}
|
|
5847
|
+
var MIHOMO_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
5848
|
+
"ss" /* Shadowsocks */,
|
|
5849
|
+
"ssr" /* ShadowsocksR */,
|
|
5850
|
+
"vmess" /* VMess */,
|
|
5851
|
+
"trojan" /* Trojan */,
|
|
5852
|
+
"snell" /* Snell */,
|
|
5853
|
+
"http" /* HTTP */,
|
|
5854
|
+
"https" /* HTTPS */,
|
|
5855
|
+
"socks5" /* SOCKS5 */,
|
|
5856
|
+
"wireguard" /* WireGuard */,
|
|
5857
|
+
"hysteria" /* Hysteria */,
|
|
5858
|
+
"hysteria2" /* Hysteria2 */,
|
|
5859
|
+
"vless" /* VLESS */,
|
|
5860
|
+
"anytls" /* AnyTLS */,
|
|
5861
|
+
"tuic" /* TUIC */
|
|
5862
|
+
]);
|
|
5863
|
+
var PREMIUM_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
5864
|
+
"ss" /* Shadowsocks */,
|
|
5865
|
+
"ssr" /* ShadowsocksR */,
|
|
5866
|
+
"vmess" /* VMess */,
|
|
5867
|
+
"trojan" /* Trojan */,
|
|
5868
|
+
"snell" /* Snell */,
|
|
5869
|
+
"http" /* HTTP */,
|
|
5870
|
+
"https" /* HTTPS */,
|
|
5871
|
+
"socks5" /* SOCKS5 */,
|
|
5872
|
+
"wireguard" /* WireGuard */
|
|
5873
|
+
]);
|
|
5874
|
+
var STASH_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
5875
|
+
...PREMIUM_PROTOCOLS,
|
|
5876
|
+
"hysteria" /* Hysteria */,
|
|
5877
|
+
"hysteria2" /* Hysteria2 */,
|
|
5878
|
+
"vless" /* VLESS */,
|
|
5879
|
+
"tuic" /* TUIC */
|
|
5880
|
+
]);
|
|
5881
|
+
function clashCapabilities(flavor) {
|
|
5882
|
+
if (flavor === "premium") {
|
|
5883
|
+
return { clientFingerprint: false, protocols: PREMIUM_PROTOCOLS, reality: false };
|
|
5884
|
+
}
|
|
5885
|
+
if (flavor === "stash") {
|
|
5886
|
+
return { clientFingerprint: false, protocols: STASH_PROTOCOLS, reality: true };
|
|
5887
|
+
}
|
|
5888
|
+
return { clientFingerprint: true, protocols: MIHOMO_PROTOCOLS, reality: true };
|
|
5889
|
+
}
|
|
5559
5890
|
function buildClashProxy(x, settings, clashR, remark, skipCertVerify, tfo) {
|
|
5560
5891
|
const proxy = {
|
|
5561
5892
|
name: remark,
|
|
5562
5893
|
port: x.port,
|
|
5563
5894
|
server: stripBrackets(x.hostname)
|
|
5564
5895
|
};
|
|
5896
|
+
const caps = clashCapabilities(settings.clashFlavor);
|
|
5897
|
+
if (!caps.protocols.has(x.type)) {
|
|
5898
|
+
return void 0;
|
|
5899
|
+
}
|
|
5565
5900
|
switch (x.type) {
|
|
5566
5901
|
case "ss" /* Shadowsocks */: {
|
|
5567
5902
|
if (settings.filterDeprecated && x.encryptMethod === "chacha20") {
|
|
@@ -5811,7 +6146,7 @@ function buildClashProxy(x, settings, clashR, remark, skipCertVerify, tfo) {
|
|
|
5811
6146
|
if (skipCertVerify !== void 0) {
|
|
5812
6147
|
proxy["skip-cert-verify"] = skipCertVerify;
|
|
5813
6148
|
}
|
|
5814
|
-
if (x.fingerprint !== "") {
|
|
6149
|
+
if (x.fingerprint !== "" && caps.clientFingerprint) {
|
|
5815
6150
|
proxy.fingerprint = x.fingerprint;
|
|
5816
6151
|
}
|
|
5817
6152
|
if (x.alpn.length > 0) {
|
|
@@ -5866,7 +6201,7 @@ function buildClashProxy(x, settings, clashR, remark, skipCertVerify, tfo) {
|
|
|
5866
6201
|
if (skipCertVerify !== void 0) {
|
|
5867
6202
|
proxy["skip-cert-verify"] = skipCertVerify;
|
|
5868
6203
|
}
|
|
5869
|
-
if (x.fingerprint !== "") {
|
|
6204
|
+
if (x.fingerprint !== "" && caps.clientFingerprint) {
|
|
5870
6205
|
proxy.fingerprint = x.fingerprint;
|
|
5871
6206
|
}
|
|
5872
6207
|
if (x.alpn.length > 0) {
|
|
@@ -5905,10 +6240,13 @@ function buildClashProxy(x, settings, clashR, remark, skipCertVerify, tfo) {
|
|
|
5905
6240
|
if (x.serverName !== "") {
|
|
5906
6241
|
proxy.servername = x.serverName;
|
|
5907
6242
|
}
|
|
5908
|
-
if (x.fingerprint !== "") {
|
|
6243
|
+
if (x.fingerprint !== "" && caps.clientFingerprint) {
|
|
5909
6244
|
proxy["client-fingerprint"] = x.fingerprint;
|
|
5910
6245
|
}
|
|
5911
6246
|
if (x.publicKey !== "" || x.shortId !== "") {
|
|
6247
|
+
if (!caps.reality) {
|
|
6248
|
+
return void 0;
|
|
6249
|
+
}
|
|
5912
6250
|
const realityOpts = {};
|
|
5913
6251
|
if (x.publicKey !== "") {
|
|
5914
6252
|
realityOpts["public-key"] = x.publicKey;
|
|
@@ -7265,7 +7603,7 @@ function collectRuleLines(content, group2, noResolveOnly) {
|
|
|
7265
7603
|
}
|
|
7266
7604
|
return out;
|
|
7267
7605
|
}
|
|
7268
|
-
function rulesetToClashRules(rulesets) {
|
|
7606
|
+
function rulesetToClashRules(rulesets, classical = false) {
|
|
7269
7607
|
const rules = [];
|
|
7270
7608
|
for (const ruleset of rulesets) {
|
|
7271
7609
|
const content = ruleset.content;
|
|
@@ -7281,7 +7619,10 @@ function rulesetToClashRules(rulesets) {
|
|
|
7281
7619
|
rules.push(transformRuleToCommon(line, group2));
|
|
7282
7620
|
continue;
|
|
7283
7621
|
}
|
|
7284
|
-
const converted = convertRuleset(
|
|
7622
|
+
const converted = convertRuleset(
|
|
7623
|
+
content,
|
|
7624
|
+
classical && /^payload:\r?\n/.test(content) ? "clash-classical" /* ClashClassical */ : ruleset.ruleType
|
|
7625
|
+
);
|
|
7285
7626
|
for (const rawLine of converted.split(/\r?\n/)) {
|
|
7286
7627
|
let line = rawLine.trim();
|
|
7287
7628
|
if (!isRuleLine(line)) {
|
|
@@ -7298,7 +7639,7 @@ function rulesetToClashRules(rulesets) {
|
|
|
7298
7639
|
}
|
|
7299
7640
|
return rules;
|
|
7300
7641
|
}
|
|
7301
|
-
function rulesetToSurgeRules(rulesets, surgeVersion) {
|
|
7642
|
+
function rulesetToSurgeRules(rulesets, surgeVersion, expand = true) {
|
|
7302
7643
|
let section;
|
|
7303
7644
|
let allowed;
|
|
7304
7645
|
let noResolveOnly = false;
|
|
@@ -7336,6 +7677,17 @@ function rulesetToSurgeRules(rulesets, surgeVersion) {
|
|
|
7336
7677
|
continue;
|
|
7337
7678
|
}
|
|
7338
7679
|
const group2 = ruleset.ruleGroup;
|
|
7680
|
+
if (!expand && (surgeVersion > 2 || surgeVersion === -3)) {
|
|
7681
|
+
const { url } = parseRulesetSource(ruleset.rulePath);
|
|
7682
|
+
if (/^https?:\/\//i.test(url.trim()) && !ruleset.content.startsWith("[]")) {
|
|
7683
|
+
let line = `RULE-SET,${url.trim()},${group2}`;
|
|
7684
|
+
if (ruleset.updateInterval > 0) {
|
|
7685
|
+
line += `,update-interval=${ruleset.updateInterval}`;
|
|
7686
|
+
}
|
|
7687
|
+
lines.push(line);
|
|
7688
|
+
continue;
|
|
7689
|
+
}
|
|
7690
|
+
}
|
|
7339
7691
|
if (ruleset.content.startsWith("[]")) {
|
|
7340
7692
|
let line = ruleset.content.slice(2);
|
|
7341
7693
|
if (line === "MATCH") {
|
|
@@ -8100,9 +8452,24 @@ function buildOutbound(x, settings, remark) {
|
|
|
8100
8452
|
proxy = out;
|
|
8101
8453
|
break;
|
|
8102
8454
|
}
|
|
8103
|
-
// sing-box has no
|
|
8455
|
+
// sing-box has no ShadowsocksR implementation (configs using it fail
|
|
8456
|
+
// at startup), so such nodes are dropped.
|
|
8104
8457
|
case "ssr" /* ShadowsocksR */:
|
|
8105
8458
|
return void 0;
|
|
8459
|
+
case "snell" /* Snell */: {
|
|
8460
|
+
const out = { ...common, psk: x.password, type: "snell" };
|
|
8461
|
+
if (x.snellVersion) {
|
|
8462
|
+
out.version = x.snellVersion;
|
|
8463
|
+
}
|
|
8464
|
+
if (x.obfs !== "" && x.obfs !== "none") {
|
|
8465
|
+
out.obfs_mode = x.obfs;
|
|
8466
|
+
}
|
|
8467
|
+
if (x.host !== "") {
|
|
8468
|
+
out.obfs_host = x.host;
|
|
8469
|
+
}
|
|
8470
|
+
proxy = out;
|
|
8471
|
+
break;
|
|
8472
|
+
}
|
|
8106
8473
|
case "vmess" /* VMess */: {
|
|
8107
8474
|
const out = {
|
|
8108
8475
|
...common,
|
|
@@ -8385,9 +8752,12 @@ function runPreprocess(nodes, settings) {
|
|
|
8385
8752
|
preprocessNodes(nodes, {
|
|
8386
8753
|
addEmoji: settings.addEmoji,
|
|
8387
8754
|
autoCountry: settings.autoCountry,
|
|
8388
|
-
countryLocale: settings.countryLocale,
|
|
8389
8755
|
countryResolver: settings.countryResolver,
|
|
8390
8756
|
emojiArray: settings.emojiArray,
|
|
8757
|
+
excludeCountries: settings.excludeCountries,
|
|
8758
|
+
excludeRemarks: settings.excludeRemarks,
|
|
8759
|
+
includeCountries: settings.includeCountries,
|
|
8760
|
+
includeRemarks: settings.includeRemarks,
|
|
8391
8761
|
nameRegexArray: settings.nameRegexArray,
|
|
8392
8762
|
nameRemove: settings.nameRemove,
|
|
8393
8763
|
removeEmoji: settings.removeEmoji,
|
|
@@ -8403,6 +8773,7 @@ function generate(nodes, options) {
|
|
|
8403
8773
|
runPreprocess(nodes, settings);
|
|
8404
8774
|
const groups = resolveGroups(options);
|
|
8405
8775
|
const rulesets = resolveRulesets(options, settings);
|
|
8776
|
+
const baseConf = applyBaseTemplate(options.baseConf ?? "", settings);
|
|
8406
8777
|
switch (options.target) {
|
|
8407
8778
|
case "clash" /* Clash */:
|
|
8408
8779
|
case "clashr" /* ClashR */: {
|
|
@@ -8412,9 +8783,9 @@ function generate(nodes, options) {
|
|
|
8412
8783
|
}
|
|
8413
8784
|
case "surge" /* Surge */: {
|
|
8414
8785
|
const surgeVersion = options.surgeVersion ?? 5;
|
|
8415
|
-
const rules = rulesets ? rulesetToSurgeRules(rulesets, surgeVersion) : void 0;
|
|
8786
|
+
const rules = rulesets ? rulesetToSurgeRules(rulesets, surgeVersion, settings.expandRulesets) : void 0;
|
|
8416
8787
|
return toSurge(nodes, groups, settings, {
|
|
8417
|
-
baseConf
|
|
8788
|
+
baseConf,
|
|
8418
8789
|
nodeList: settings.nodeList,
|
|
8419
8790
|
rules,
|
|
8420
8791
|
version: surgeVersion
|
|
@@ -8423,7 +8794,7 @@ function generate(nodes, options) {
|
|
|
8423
8794
|
case "quanx" /* QuantumultX */: {
|
|
8424
8795
|
const rules = rulesets ? rulesetToSurgeRules(rulesets, -1) : void 0;
|
|
8425
8796
|
return toQuanX(nodes, groups, settings, {
|
|
8426
|
-
baseConf
|
|
8797
|
+
baseConf,
|
|
8427
8798
|
nodeList: settings.nodeList,
|
|
8428
8799
|
rules
|
|
8429
8800
|
});
|
|
@@ -8431,7 +8802,7 @@ function generate(nodes, options) {
|
|
|
8431
8802
|
case "quan" /* Quantumult */: {
|
|
8432
8803
|
const rules = rulesets ? rulesetToSurgeRules(rulesets, -2) : void 0;
|
|
8433
8804
|
return toQuan(nodes, groups, settings, {
|
|
8434
|
-
baseConf
|
|
8805
|
+
baseConf,
|
|
8435
8806
|
nodeList: settings.nodeList,
|
|
8436
8807
|
rules
|
|
8437
8808
|
});
|
|
@@ -8439,21 +8810,21 @@ function generate(nodes, options) {
|
|
|
8439
8810
|
case "loon" /* Loon */: {
|
|
8440
8811
|
const rules = rulesets ? rulesetToSurgeRules(rulesets, -4) : void 0;
|
|
8441
8812
|
return toLoon(nodes, groups, settings, {
|
|
8442
|
-
baseConf
|
|
8813
|
+
baseConf,
|
|
8443
8814
|
nodeList: settings.nodeList,
|
|
8444
8815
|
rules
|
|
8445
8816
|
});
|
|
8446
8817
|
}
|
|
8447
8818
|
case "singbox" /* SingBox */:
|
|
8448
8819
|
return toSingBox(nodes, groups, settings, {
|
|
8449
|
-
baseConf
|
|
8820
|
+
baseConf,
|
|
8450
8821
|
nodeList: settings.nodeList,
|
|
8451
8822
|
overwriteOriginalRules: settings.overwriteOriginalRules,
|
|
8452
8823
|
rulesets
|
|
8453
8824
|
});
|
|
8454
8825
|
case "mellow" /* Mellow */:
|
|
8455
8826
|
return toMellow(nodes, groups, settings, {
|
|
8456
|
-
baseConf
|
|
8827
|
+
baseConf,
|
|
8457
8828
|
nodeList: settings.nodeList,
|
|
8458
8829
|
overwriteOriginalRules: settings.overwriteOriginalRules,
|
|
8459
8830
|
rulesets
|
|
@@ -8471,11 +8842,11 @@ function generate(nodes, options) {
|
|
|
8471
8842
|
case "ssd" /* SSD */:
|
|
8472
8843
|
return proxyToSsd(nodes, "", "");
|
|
8473
8844
|
case "sssub" /* SSSub */:
|
|
8474
|
-
return proxyToSsSub(nodes,
|
|
8845
|
+
return proxyToSsSub(nodes, baseConf);
|
|
8475
8846
|
case "surfboard" /* Surfboard */: {
|
|
8476
|
-
const rules = rulesets ? rulesetToSurgeRules(rulesets, options.surgeVersion ?? 5) : void 0;
|
|
8847
|
+
const rules = rulesets ? rulesetToSurgeRules(rulesets, options.surgeVersion ?? 5, settings.expandRulesets) : void 0;
|
|
8477
8848
|
return toSurfboard(nodes, groups, settings, {
|
|
8478
|
-
baseConf
|
|
8849
|
+
baseConf,
|
|
8479
8850
|
nodeList: settings.nodeList,
|
|
8480
8851
|
rules
|
|
8481
8852
|
});
|
|
@@ -8488,6 +8859,12 @@ function generate(nodes, options) {
|
|
|
8488
8859
|
throw new Error(`Unsupported target format: ${options.target}`);
|
|
8489
8860
|
}
|
|
8490
8861
|
}
|
|
8862
|
+
function applyBaseTemplate(baseConf, settings) {
|
|
8863
|
+
if (baseConf === "" || !hasTemplatePlaceholders(baseConf)) {
|
|
8864
|
+
return baseConf;
|
|
8865
|
+
}
|
|
8866
|
+
return renderTemplate(baseConf, settings.templateVars);
|
|
8867
|
+
}
|
|
8491
8868
|
function toSip008(nodes, baseConf = "") {
|
|
8492
8869
|
return proxyToSsSub(nodes, baseConf);
|
|
8493
8870
|
}
|
|
@@ -8517,7 +8894,7 @@ function attachClashRules(doc, settings, rulesets) {
|
|
|
8517
8894
|
return;
|
|
8518
8895
|
}
|
|
8519
8896
|
const field = settings.clashNewFieldName ? "rules" : "Rule";
|
|
8520
|
-
const generated = rulesetToClashRules(rulesets);
|
|
8897
|
+
const generated = rulesetToClashRules(rulesets, settings.clashClassicalRuleset);
|
|
8521
8898
|
if (generated.length === 0) {
|
|
8522
8899
|
return;
|
|
8523
8900
|
}
|