mirror of
https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-10 00:52:40 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cf8080cd3 | ||
|
|
839fcacf63 | ||
|
|
a2e45bcb10 | ||
|
|
ea0eb91691 | ||
|
|
1f0ddf2d28 | ||
|
|
a660c6ff90 | ||
|
|
71d9adbc07 | ||
|
|
97bec9183a | ||
|
|
ef85b6d0e9 | ||
|
|
8ffb060cb4 |
@@ -26,6 +26,8 @@ Core functionalities:
|
|||||||
|
|
||||||
### Supported Input Formats
|
### Supported Input Formats
|
||||||
|
|
||||||
|
> ⚠️ Do not use `Shadowrocket` to export URI and then import it as input. It is not a standard URI.
|
||||||
|
|
||||||
- [x] URI(SS, SSR, VMess, VLESS, Trojan, Hysteria, Hysteria 2, TUIC v5, WireGuard)
|
- [x] URI(SS, SSR, VMess, VLESS, Trojan, Hysteria, Hysteria 2, TUIC v5, WireGuard)
|
||||||
- [x] Clash Proxies YAML
|
- [x] Clash Proxies YAML
|
||||||
- [x] Clash Proxy JSON(single line)
|
- [x] Clash Proxy JSON(single line)
|
||||||
@@ -33,7 +35,6 @@ Core functionalities:
|
|||||||
- [x] Loon (SS, SSR, VMess, Trojan, HTTP, SOCKS5, SOCKS5-TLS, WireGuard, VLESS, Hysteria 2)
|
- [x] Loon (SS, SSR, VMess, Trojan, HTTP, SOCKS5, SOCKS5-TLS, WireGuard, VLESS, Hysteria 2)
|
||||||
- [x] Surge (SS, VMess, Trojan, HTTP, SOCKS5, SOCKS5-TLS, TUIC, Snell, Hysteria 2, SSH(Password authentication only), External Proxy Program(only for macOS), WireGuard(Surge to Surge))
|
- [x] Surge (SS, VMess, Trojan, HTTP, SOCKS5, SOCKS5-TLS, TUIC, Snell, Hysteria 2, SSH(Password authentication only), External Proxy Program(only for macOS), WireGuard(Surge to Surge))
|
||||||
- [x] Surfboard (SS, VMess, Trojan, HTTP, SOCKS5, SOCKS5-TLS, WireGuard(Surfboard to Surfboard))
|
- [x] Surfboard (SS, VMess, Trojan, HTTP, SOCKS5, SOCKS5-TLS, WireGuard(Surfboard to Surfboard))
|
||||||
- [x] Shadowrocket (SS, SSR, VMess, Trojan, HTTP, SOCKS5, Snell, VLESS, WireGuard, Hysteria, Hysteria 2, TUIC)
|
|
||||||
- [x] Clash.Meta (SS, SSR, VMess, Trojan, HTTP, SOCKS5, Snell, VLESS, WireGuard, Hysteria, Hysteria 2, TUIC)
|
- [x] Clash.Meta (SS, SSR, VMess, Trojan, HTTP, SOCKS5, Snell, VLESS, WireGuard, Hysteria, Hysteria 2, TUIC)
|
||||||
- [x] Stash (SS, SSR, VMess, Trojan, HTTP, SOCKS5, Snell, VLESS, WireGuard, Hysteria, TUIC, Juicity, SSH)
|
- [x] Stash (SS, SSR, VMess, Trojan, HTTP, SOCKS5, Snell, VLESS, WireGuard, Hysteria, TUIC, Juicity, SSH)
|
||||||
- [x] Clash (SS, SSR, VMess, Trojan, HTTP, SOCKS5, Snell, VLESS, WireGuard)
|
- [x] Clash (SS, SSR, VMess, Trojan, HTTP, SOCKS5, Snell, VLESS, WireGuard)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sub-store",
|
"name": "sub-store",
|
||||||
"version": "2.14.389",
|
"version": "2.14.399",
|
||||||
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
|
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
|
||||||
"main": "src/main.js",
|
"main": "src/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -408,20 +408,7 @@ function lastParse(proxy) {
|
|||||||
proxy['h2-opts'].path = path[0];
|
proxy['h2-opts'].path = path[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (proxy.tls && !proxy.sni) {
|
|
||||||
if (proxy.network) {
|
|
||||||
let transportHost = proxy[`${proxy.network}-opts`]?.headers?.Host;
|
|
||||||
transportHost = Array.isArray(transportHost)
|
|
||||||
? transportHost[0]
|
|
||||||
: transportHost;
|
|
||||||
if (transportHost) {
|
|
||||||
proxy.sni = transportHost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!proxy.sni && !isIP(proxy.server)) {
|
|
||||||
proxy.sni = proxy.server;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 非 tls, 有 ws/http 传输层, 使用域名的节点, 将设置传输层 Host 防止之后域名解析后丢失域名(不覆盖现有的 Host)
|
// 非 tls, 有 ws/http 传输层, 使用域名的节点, 将设置传输层 Host 防止之后域名解析后丢失域名(不覆盖现有的 Host)
|
||||||
if (
|
if (
|
||||||
!proxy.tls &&
|
!proxy.tls &&
|
||||||
@@ -448,6 +435,20 @@ function lastParse(proxy) {
|
|||||||
proxy[`${proxy.network}-opts`].path = [transportPath];
|
proxy[`${proxy.network}-opts`].path = [transportPath];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (proxy.tls && !proxy.sni) {
|
||||||
|
if (!isIP(proxy.server)) {
|
||||||
|
proxy.sni = proxy.server;
|
||||||
|
}
|
||||||
|
if (!proxy.sni && proxy.network) {
|
||||||
|
let transportHost = proxy[`${proxy.network}-opts`]?.headers?.Host;
|
||||||
|
transportHost = Array.isArray(transportHost)
|
||||||
|
? transportHost[0]
|
||||||
|
: transportHost;
|
||||||
|
if (transportHost) {
|
||||||
|
proxy.sni = transportHost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// if (['hysteria', 'hysteria2', 'tuic'].includes(proxy.type)) {
|
// if (['hysteria', 'hysteria2', 'tuic'].includes(proxy.type)) {
|
||||||
if (proxy.ports) {
|
if (proxy.ports) {
|
||||||
proxy.ports = String(proxy.ports).replace(/\//g, ',');
|
proxy.ports = String(proxy.ports).replace(/\//g, ',');
|
||||||
|
|||||||
@@ -391,12 +391,6 @@ function URI_VMess() {
|
|||||||
} else {
|
} else {
|
||||||
delete proxy.network;
|
delete proxy.network;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/MetaCubeX/Clash.Meta/blob/Alpha/docs/config.yaml#L413
|
|
||||||
// sni 优先级应高于 host
|
|
||||||
if (proxy.tls && !proxy.sni && transportHost) {
|
|
||||||
proxy.sni = transportHost;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
@@ -539,15 +533,6 @@ function URI_VLESS() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy.tls && !proxy.sni) {
|
|
||||||
if (proxy.network === 'ws') {
|
|
||||||
proxy.sni = proxy['ws-opts']?.headers?.Host;
|
|
||||||
} else if (proxy.network === 'http') {
|
|
||||||
let httpHost = proxy['http-opts']?.headers?.Host;
|
|
||||||
proxy.sni = Array.isArray(httpHost) ? httpHost[0] : httpHost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return proxy;
|
return proxy;
|
||||||
};
|
};
|
||||||
return { name, test, parse };
|
return { name, test, parse };
|
||||||
@@ -898,18 +883,7 @@ function Clash_All() {
|
|||||||
if (['vmess', 'vless'].includes(proxy.type)) {
|
if (['vmess', 'vless'].includes(proxy.type)) {
|
||||||
proxy.sni = proxy.servername;
|
proxy.sni = proxy.servername;
|
||||||
delete proxy.servername;
|
delete proxy.servername;
|
||||||
if (proxy.tls && !proxy.sni) {
|
|
||||||
if (proxy.network === 'ws') {
|
|
||||||
proxy.sni = proxy['ws-opts']?.headers?.Host;
|
|
||||||
} else if (proxy.network === 'http') {
|
|
||||||
let httpHost = proxy['http-opts']?.headers?.Host;
|
|
||||||
proxy.sni = Array.isArray(httpHost)
|
|
||||||
? httpHost[0]
|
|
||||||
: httpHost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy['server-cert-fingerprint']) {
|
if (proxy['server-cert-fingerprint']) {
|
||||||
proxy['tls-fingerprint'] = proxy['server-cert-fingerprint'];
|
proxy['tls-fingerprint'] = proxy['server-cert-fingerprint'];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ vmess_aead = comma "vmess-aead" equals flag:bool { proxy.aead = flag; }
|
|||||||
method = comma "encrypt-method" equals cipher:cipher {
|
method = comma "encrypt-method" equals cipher:cipher {
|
||||||
proxy.cipher = cipher;
|
proxy.cipher = cipher;
|
||||||
}
|
}
|
||||||
cipher = ("aes-128-cfb"/"aes-128-ctr"/"aes-128-gcm"/"aes-192-cfb"/"aes-192-ctr"/"aes-192-gcm"/"aes-256-cfb"/"aes-256-ctr"/"aes-256-gcm"/"bf-cfb"/"camellia-128-cfb"/"camellia-192-cfb"/"camellia-256-cfb"/"cast5-cfb"/"chacha20-ietf-poly1305"/"chacha20-ietf"/"chacha20-poly1305"/"chacha20"/"des-cfb"/"idea-cfb"/"none"/"rc2-cfb"/"rc4-md5"/"rc4"/"salsa20"/"seed-cfb"/"xchacha20-ietf-poly1305");
|
cipher = ("aes-128-cfb"/"aes-128-ctr"/"aes-128-gcm"/"aes-192-cfb"/"aes-192-ctr"/"aes-192-gcm"/"aes-256-cfb"/"aes-256-ctr"/"aes-256-gcm"/"bf-cfb"/"camellia-128-cfb"/"camellia-192-cfb"/"camellia-256-cfb"/"cast5-cfb"/"chacha20-ietf-poly1305"/"chacha20-ietf"/"chacha20-poly1305"/"chacha20"/"des-cfb"/"idea-cfb"/"none"/"rc2-cfb"/"rc4-md5"/"rc4"/"salsa20"/"seed-cfb"/"xchacha20-ietf-poly1305"/"2022-blake3-aes-128-gcm"/"2022-blake3-aes-256-gcm");
|
||||||
|
|
||||||
ws = comma "ws" equals flag:bool { obfs.type = "ws"; }
|
ws = comma "ws" equals flag:bool { obfs.type = "ws"; }
|
||||||
ws_headers = comma "ws-headers" equals headers:$[^,]+ {
|
ws_headers = comma "ws-headers" equals headers:$[^,]+ {
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ vmess_aead = comma "vmess-aead" equals flag:bool { proxy.aead = flag; }
|
|||||||
method = comma "encrypt-method" equals cipher:cipher {
|
method = comma "encrypt-method" equals cipher:cipher {
|
||||||
proxy.cipher = cipher;
|
proxy.cipher = cipher;
|
||||||
}
|
}
|
||||||
cipher = ("aes-128-cfb"/"aes-128-ctr"/"aes-128-gcm"/"aes-192-cfb"/"aes-192-ctr"/"aes-192-gcm"/"aes-256-cfb"/"aes-256-ctr"/"aes-256-gcm"/"bf-cfb"/"camellia-128-cfb"/"camellia-192-cfb"/"camellia-256-cfb"/"cast5-cfb"/"chacha20-ietf-poly1305"/"chacha20-ietf"/"chacha20-poly1305"/"chacha20"/"des-cfb"/"idea-cfb"/"none"/"rc2-cfb"/"rc4-md5"/"rc4"/"salsa20"/"seed-cfb"/"xchacha20-ietf-poly1305");
|
cipher = ("aes-128-cfb"/"aes-128-ctr"/"aes-128-gcm"/"aes-192-cfb"/"aes-192-ctr"/"aes-192-gcm"/"aes-256-cfb"/"aes-256-ctr"/"aes-256-gcm"/"bf-cfb"/"camellia-128-cfb"/"camellia-192-cfb"/"camellia-256-cfb"/"cast5-cfb"/"chacha20-ietf-poly1305"/"chacha20-ietf"/"chacha20-poly1305"/"chacha20"/"des-cfb"/"idea-cfb"/"none"/"rc2-cfb"/"rc4-md5"/"rc4"/"salsa20"/"seed-cfb"/"xchacha20-ietf-poly1305"/"2022-blake3-aes-128-gcm"/"2022-blake3-aes-256-gcm");
|
||||||
|
|
||||||
ws = comma "ws" equals flag:bool { obfs.type = "ws"; }
|
ws = comma "ws" equals flag:bool { obfs.type = "ws"; }
|
||||||
ws_headers = comma "ws-headers" equals headers:$[^,]+ {
|
ws_headers = comma "ws-headers" equals headers:$[^,]+ {
|
||||||
|
|||||||
@@ -50,10 +50,32 @@ function Clash() {
|
|||||||
};
|
};
|
||||||
const parse = function (raw) {
|
const parse = function (raw) {
|
||||||
// Clash YAML format
|
// Clash YAML format
|
||||||
|
|
||||||
|
// 防止 VLESS节点 reality-opts 选项中的 short-id 被解析成 Infinity
|
||||||
|
// 匹配 short-id 冒号后面的值(包含空格和引号)
|
||||||
|
const afterReplace = raw.replace(
|
||||||
|
/short-id:([ ]*[^,\n}]*)/g,
|
||||||
|
(matched, value) => {
|
||||||
|
const afterTrim = value.trim();
|
||||||
|
|
||||||
|
// 为空
|
||||||
|
if (!afterTrim || afterTrim === '') {
|
||||||
|
return 'short-id: ""'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否被引号包裹
|
||||||
|
if (/^(['"]).*\1$/.test(afterTrim)) {
|
||||||
|
return `short-id: ${afterTrim}`;
|
||||||
|
} else {
|
||||||
|
return `short-id: "${afterTrim}"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
proxies,
|
proxies,
|
||||||
'global-client-fingerprint': globalClientFingerprint,
|
'global-client-fingerprint': globalClientFingerprint,
|
||||||
} = safeLoad(raw);
|
} = safeLoad(afterReplace);
|
||||||
return proxies
|
return proxies
|
||||||
.map((p) => {
|
.map((p) => {
|
||||||
// https://github.com/MetaCubeX/mihomo/blob/Alpha/docs/config.yaml#L73C1-L73C26
|
// https://github.com/MetaCubeX/mihomo/blob/Alpha/docs/config.yaml#L73C1-L73C26
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export default function Surge_Producer() {
|
|||||||
}
|
}
|
||||||
switch (proxy.type) {
|
switch (proxy.type) {
|
||||||
case 'ss':
|
case 'ss':
|
||||||
return shadowsocks(proxy);
|
return shadowsocks(proxy, opts['include-unsupported-proxy']);
|
||||||
case 'trojan':
|
case 'trojan':
|
||||||
return trojan(proxy);
|
return trojan(proxy);
|
||||||
case 'vmess':
|
case 'vmess':
|
||||||
@@ -51,7 +51,7 @@ export default function Surge_Producer() {
|
|||||||
return { produce };
|
return { produce };
|
||||||
}
|
}
|
||||||
|
|
||||||
function shadowsocks(proxy) {
|
function shadowsocks(proxy, includeUnsupportedProxy) {
|
||||||
const result = new Result(proxy);
|
const result = new Result(proxy);
|
||||||
result.append(`${proxy.name}=${proxy.type},${proxy.server},${proxy.port}`);
|
result.append(`${proxy.name}=${proxy.type},${proxy.server},${proxy.port}`);
|
||||||
if (!proxy.cipher) {
|
if (!proxy.cipher) {
|
||||||
@@ -85,6 +85,9 @@ function shadowsocks(proxy) {
|
|||||||
'chacha20',
|
'chacha20',
|
||||||
'chacha20-ietf',
|
'chacha20-ietf',
|
||||||
'none',
|
'none',
|
||||||
|
...(includeUnsupportedProxy
|
||||||
|
? ['2022-blake3-aes-128-gcm', '2022-blake3-aes-256-gcm']
|
||||||
|
: []),
|
||||||
].includes(proxy.cipher)
|
].includes(proxy.cipher)
|
||||||
) {
|
) {
|
||||||
throw new Error(`cipher ${proxy.cipher} is not supported`);
|
throw new Error(`cipher ${proxy.cipher} is not supported`);
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ async function downloadSubscription(req, res) {
|
|||||||
produceType,
|
produceType,
|
||||||
includeUnsupportedProxy,
|
includeUnsupportedProxy,
|
||||||
resultFormat,
|
resultFormat,
|
||||||
|
proxy,
|
||||||
} = req.query;
|
} = req.query;
|
||||||
let $options = {};
|
let $options = {};
|
||||||
if (req.query.$options) {
|
if (req.query.$options) {
|
||||||
@@ -92,6 +93,10 @@ async function downloadSubscription(req, res) {
|
|||||||
url = decodeURIComponent(url);
|
url = decodeURIComponent(url);
|
||||||
$.info(`指定远程订阅 URL: ${url}`);
|
$.info(`指定远程订阅 URL: ${url}`);
|
||||||
}
|
}
|
||||||
|
if (proxy) {
|
||||||
|
proxy = decodeURIComponent(proxy);
|
||||||
|
$.info(`指定远程订阅使用代理/策略 proxy: ${proxy}`);
|
||||||
|
}
|
||||||
if (ua) {
|
if (ua) {
|
||||||
ua = decodeURIComponent(ua);
|
ua = decodeURIComponent(ua);
|
||||||
$.info(`指定远程订阅 User-Agent: ${ua}`);
|
$.info(`指定远程订阅 User-Agent: ${ua}`);
|
||||||
@@ -135,6 +140,7 @@ async function downloadSubscription(req, res) {
|
|||||||
'include-unsupported-proxy': includeUnsupportedProxy,
|
'include-unsupported-proxy': includeUnsupportedProxy,
|
||||||
},
|
},
|
||||||
$options,
|
$options,
|
||||||
|
proxy,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -175,7 +181,7 @@ async function downloadSubscription(req, res) {
|
|||||||
url,
|
url,
|
||||||
$arguments.flowUserAgent,
|
$arguments.flowUserAgent,
|
||||||
undefined,
|
undefined,
|
||||||
sub.proxy,
|
proxy || sub.proxy,
|
||||||
$arguments.flowUrl,
|
$arguments.flowUrl,
|
||||||
);
|
);
|
||||||
if (flowInfo) {
|
if (flowInfo) {
|
||||||
@@ -264,6 +270,7 @@ async function downloadCollection(req, res) {
|
|||||||
produceType,
|
produceType,
|
||||||
includeUnsupportedProxy,
|
includeUnsupportedProxy,
|
||||||
resultFormat,
|
resultFormat,
|
||||||
|
proxy,
|
||||||
} = req.query;
|
} = req.query;
|
||||||
|
|
||||||
let $options = {};
|
let $options = {};
|
||||||
@@ -285,6 +292,11 @@ async function downloadCollection(req, res) {
|
|||||||
$.info(`传入 $options: ${JSON.stringify($options)}`);
|
$.info(`传入 $options: ${JSON.stringify($options)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (proxy) {
|
||||||
|
proxy = decodeURIComponent(proxy);
|
||||||
|
$.info(`指定远程订阅使用代理/策略 proxy: ${proxy}`);
|
||||||
|
}
|
||||||
|
|
||||||
if (ignoreFailedRemoteSub != null && ignoreFailedRemoteSub !== '') {
|
if (ignoreFailedRemoteSub != null && ignoreFailedRemoteSub !== '') {
|
||||||
ignoreFailedRemoteSub = decodeURIComponent(ignoreFailedRemoteSub);
|
ignoreFailedRemoteSub = decodeURIComponent(ignoreFailedRemoteSub);
|
||||||
$.info(`指定忽略失败的远程订阅: ${ignoreFailedRemoteSub}`);
|
$.info(`指定忽略失败的远程订阅: ${ignoreFailedRemoteSub}`);
|
||||||
@@ -311,6 +323,7 @@ async function downloadCollection(req, res) {
|
|||||||
'include-unsupported-proxy': includeUnsupportedProxy,
|
'include-unsupported-proxy': includeUnsupportedProxy,
|
||||||
},
|
},
|
||||||
$options,
|
$options,
|
||||||
|
proxy,
|
||||||
});
|
});
|
||||||
|
|
||||||
// forward flow header from the first subscription in this collection
|
// forward flow header from the first subscription in this collection
|
||||||
@@ -355,7 +368,7 @@ async function downloadCollection(req, res) {
|
|||||||
url,
|
url,
|
||||||
$arguments.flowUserAgent,
|
$arguments.flowUserAgent,
|
||||||
undefined,
|
undefined,
|
||||||
sub.proxy,
|
proxy || sub.proxy || collection.proxy,
|
||||||
$arguments.flowUrl,
|
$arguments.flowUrl,
|
||||||
);
|
);
|
||||||
if (flowInfo) {
|
if (flowInfo) {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ async function getFile(req, res) {
|
|||||||
content,
|
content,
|
||||||
mergeSources,
|
mergeSources,
|
||||||
ignoreFailedRemoteFile,
|
ignoreFailedRemoteFile,
|
||||||
|
proxy,
|
||||||
} = req.query;
|
} = req.query;
|
||||||
let $options = {};
|
let $options = {};
|
||||||
if (req.query.$options) {
|
if (req.query.$options) {
|
||||||
@@ -82,6 +83,10 @@ async function getFile(req, res) {
|
|||||||
url = decodeURIComponent(url);
|
url = decodeURIComponent(url);
|
||||||
$.info(`指定远程文件 URL: ${url}`);
|
$.info(`指定远程文件 URL: ${url}`);
|
||||||
}
|
}
|
||||||
|
if (proxy) {
|
||||||
|
proxy = decodeURIComponent(proxy);
|
||||||
|
$.info(`指定远程订阅使用代理/策略 proxy: ${proxy}`);
|
||||||
|
}
|
||||||
if (ua) {
|
if (ua) {
|
||||||
ua = decodeURIComponent(ua);
|
ua = decodeURIComponent(ua);
|
||||||
$.info(`指定远程文件 User-Agent: ${ua}`);
|
$.info(`指定远程文件 User-Agent: ${ua}`);
|
||||||
@@ -120,6 +125,7 @@ async function getFile(req, res) {
|
|||||||
mergeSources,
|
mergeSources,
|
||||||
ignoreFailedRemoteFile,
|
ignoreFailedRemoteFile,
|
||||||
$options,
|
$options,
|
||||||
|
proxy,
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -129,6 +135,8 @@ async function getFile(req, res) {
|
|||||||
const flowInfo = await getFlowHeaders(
|
const flowInfo = await getFlowHeaders(
|
||||||
subInfoUrl,
|
subInfoUrl,
|
||||||
subInfoUserAgent || file.subInfoUserAgent,
|
subInfoUserAgent || file.subInfoUserAgent,
|
||||||
|
undefined,
|
||||||
|
proxy || file.proxy,
|
||||||
);
|
);
|
||||||
if (flowInfo) {
|
if (flowInfo) {
|
||||||
res.set('subscription-userinfo', flowInfo);
|
res.set('subscription-userinfo', flowInfo);
|
||||||
|
|||||||
@@ -177,7 +177,20 @@ async function compareCollection(req, res) {
|
|||||||
try {
|
try {
|
||||||
const allSubs = $.read(SUBS_KEY);
|
const allSubs = $.read(SUBS_KEY);
|
||||||
const collection = req.body;
|
const collection = req.body;
|
||||||
const subnames = collection.subscriptions;
|
const subnames = [...collection.subscriptions];
|
||||||
|
let subscriptionTags = collection.subscriptionTags;
|
||||||
|
if (Array.isArray(subscriptionTags) && subscriptionTags.length > 0) {
|
||||||
|
allSubs.forEach((sub) => {
|
||||||
|
if (
|
||||||
|
Array.isArray(sub.tag) &&
|
||||||
|
sub.tag.length > 0 &&
|
||||||
|
!subnames.includes(sub.name) &&
|
||||||
|
sub.tag.some((tag) => subscriptionTags.includes(tag))
|
||||||
|
) {
|
||||||
|
subnames.push(sub.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
const results = {};
|
const results = {};
|
||||||
const errors = {};
|
const errors = {};
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ async function produceArtifact({
|
|||||||
subscription,
|
subscription,
|
||||||
awaitCustomCache,
|
awaitCustomCache,
|
||||||
$options,
|
$options,
|
||||||
|
proxy,
|
||||||
}) {
|
}) {
|
||||||
platform = platform || 'JSON';
|
platform = platform || 'JSON';
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ async function produceArtifact({
|
|||||||
url,
|
url,
|
||||||
ua || sub.ua,
|
ua || sub.ua,
|
||||||
undefined,
|
undefined,
|
||||||
sub.proxy,
|
proxy || sub.proxy,
|
||||||
undefined,
|
undefined,
|
||||||
awaitCustomCache,
|
awaitCustomCache,
|
||||||
);
|
);
|
||||||
@@ -115,7 +116,7 @@ async function produceArtifact({
|
|||||||
url,
|
url,
|
||||||
ua || sub.ua,
|
ua || sub.ua,
|
||||||
undefined,
|
undefined,
|
||||||
sub.proxy,
|
proxy || sub.proxy,
|
||||||
undefined,
|
undefined,
|
||||||
awaitCustomCache,
|
awaitCustomCache,
|
||||||
);
|
);
|
||||||
@@ -189,7 +190,20 @@ async function produceArtifact({
|
|||||||
const allCols = $.read(COLLECTIONS_KEY);
|
const allCols = $.read(COLLECTIONS_KEY);
|
||||||
const collection = findByName(allCols, name);
|
const collection = findByName(allCols, name);
|
||||||
if (!collection) throw new Error(`找不到组合订阅 ${name}`);
|
if (!collection) throw new Error(`找不到组合订阅 ${name}`);
|
||||||
const subnames = collection.subscriptions;
|
const subnames = [...collection.subscriptions];
|
||||||
|
let subscriptionTags = collection.subscriptionTags;
|
||||||
|
if (Array.isArray(subscriptionTags) && subscriptionTags.length > 0) {
|
||||||
|
allSubs.forEach((sub) => {
|
||||||
|
if (
|
||||||
|
Array.isArray(sub.tag) &&
|
||||||
|
sub.tag.length > 0 &&
|
||||||
|
!subnames.includes(sub.name) &&
|
||||||
|
sub.tag.some((tag) => subscriptionTags.includes(tag))
|
||||||
|
) {
|
||||||
|
subnames.push(sub.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
const results = {};
|
const results = {};
|
||||||
const errors = {};
|
const errors = {};
|
||||||
let processed = 0;
|
let processed = 0;
|
||||||
@@ -220,7 +234,9 @@ async function produceArtifact({
|
|||||||
url,
|
url,
|
||||||
sub.ua,
|
sub.ua,
|
||||||
undefined,
|
undefined,
|
||||||
sub.proxy,
|
proxy ||
|
||||||
|
sub.proxy ||
|
||||||
|
collection.proxy,
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errors[url] = err;
|
errors[url] = err;
|
||||||
@@ -344,7 +360,6 @@ async function produceArtifact({
|
|||||||
}
|
}
|
||||||
exist[proxy.name] = true;
|
exist[proxy.name] = true;
|
||||||
}
|
}
|
||||||
console.log(proxies);
|
|
||||||
return ProxyUtils.produce(proxies, platform, produceType, produceOpts);
|
return ProxyUtils.produce(proxies, platform, produceType, produceOpts);
|
||||||
} else if (type === 'rule') {
|
} else if (type === 'rule') {
|
||||||
const allRules = $.read(RULES_KEY);
|
const allRules = $.read(RULES_KEY);
|
||||||
@@ -390,7 +405,12 @@ async function produceArtifact({
|
|||||||
.filter((i) => i.length)
|
.filter((i) => i.length)
|
||||||
.map(async (url) => {
|
.map(async (url) => {
|
||||||
try {
|
try {
|
||||||
return await download(url, ua || file.ua);
|
return await download(
|
||||||
|
url,
|
||||||
|
ua || file.ua,
|
||||||
|
undefined,
|
||||||
|
file.proxy || proxy,
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errors[url] = err;
|
errors[url] = err;
|
||||||
$.error(
|
$.error(
|
||||||
@@ -433,7 +453,12 @@ async function produceArtifact({
|
|||||||
.filter((i) => i.length)
|
.filter((i) => i.length)
|
||||||
.map(async (url) => {
|
.map(async (url) => {
|
||||||
try {
|
try {
|
||||||
return await download(url, ua || file.ua);
|
return await download(
|
||||||
|
url,
|
||||||
|
ua || file.ua,
|
||||||
|
undefined,
|
||||||
|
file.proxy || proxy,
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errors[url] = err;
|
errors[url] = err;
|
||||||
$.error(
|
$.error(
|
||||||
|
|||||||
Reference in New Issue
Block a user