Compare commits

..

1 Commits

12 changed files with 32 additions and 101 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "sub-store", "name": "sub-store",
"version": "2.14.260", "version": "2.14.253",
"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": {

View File

@@ -10,8 +10,6 @@ const RULE_TYPES_MAPPING = [
[/^PROTOCOL$/, 'PROTOCOL'], [/^PROTOCOL$/, 'PROTOCOL'],
[/^IP-CIDR$/i, 'IP-CIDR'], [/^IP-CIDR$/i, 'IP-CIDR'],
[/^(IP-CIDR6|ip6-cidr|IP6-CIDR)$/, 'IP-CIDR6'], [/^(IP-CIDR6|ip6-cidr|IP6-CIDR)$/, 'IP-CIDR6'],
[/^GEOIP$/i, 'GEOIP'],
[/^GEOSITE$/i, 'GEOSITE'],
]; ];
function AllRuleParser() { function AllRuleParser() {
@@ -39,7 +37,8 @@ function AllRuleParser() {
content: params[1], content: params[1],
}; };
if ( if (
['IP-CIDR', 'IP-CIDR6', 'GEOIP'].includes(rule.type) rule.type === 'IP-CIDR' ||
rule.type === 'IP-CIDR6'
) { ) {
rule.options = params.slice(2); rule.options = params.slice(2);
} }

View File

@@ -10,8 +10,6 @@ function QXFilter() {
'SRC-IP', 'SRC-IP',
'IN-PORT', 'IN-PORT',
'PROTOCOL', 'PROTOCOL',
'GEOSITE',
'GEOIP',
]; ];
if (UNSUPPORTED.indexOf(rule.type) !== -1) return null; if (UNSUPPORTED.indexOf(rule.type) !== -1) return null;
@@ -31,8 +29,6 @@ function QXFilter() {
function SurgeRuleSet() { function SurgeRuleSet() {
const type = 'SINGLE'; const type = 'SINGLE';
const func = (rule) => { const func = (rule) => {
const UNSUPPORTED = ['GEOSITE', 'GEOIP'];
if (UNSUPPORTED.indexOf(rule.type) !== -1) return null;
let output = `${rule.type},${rule.content}`; let output = `${rule.type},${rule.content}`;
if (['IP-CIDR', 'IP-CIDR6'].includes(rule.type)) { if (['IP-CIDR', 'IP-CIDR6'].includes(rule.type)) {
output += output +=
@@ -47,7 +43,7 @@ function LoonRules() {
const type = 'SINGLE'; const type = 'SINGLE';
const func = (rule) => { const func = (rule) => {
// skip unsupported rules // skip unsupported rules
const UNSUPPORTED = ['SRC-IP', 'GEOSITE', 'GEOIP']; const UNSUPPORTED = ['DEST-PORT', 'SRC-IP', 'IN-PORT', 'PROTOCOL'];
if (UNSUPPORTED.indexOf(rule.type) !== -1) return null; if (UNSUPPORTED.indexOf(rule.type) !== -1) return null;
if (['IP-CIDR', 'IP-CIDR6'].includes(rule.type) && rule.options) { if (['IP-CIDR', 'IP-CIDR6'].includes(rule.type) && rule.options) {
// Loon only supports the no-resolve option // Loon only supports the no-resolve option
@@ -73,7 +69,7 @@ function ClashRuleProvider() {
let output = `${TRANSFORM[rule.type] || rule.type},${ let output = `${TRANSFORM[rule.type] || rule.type},${
rule.content rule.content
}`; }`;
if (['IP-CIDR', 'IP-CIDR6', 'GEOIP'].includes(rule.type)) { if (['IP-CIDR', 'IP-CIDR6'].includes(rule.type)) {
if (rule.options) { if (rule.options) {
// Clash only supports the no-resolve option // Clash only supports the no-resolve option
rule.options = rule.options.filter((option) => rule.options = rule.options.filter((option) =>

View File

@@ -128,19 +128,10 @@ async function doSync() {
files.map((item) => [item.path, item]), files.map((item) => [item.path, item]),
); );
} }
const raw_url = const url = files[encodeURIComponent(artifact.name)]?.raw_url;
files[encodeURIComponent(artifact.name)]?.raw_url; artifact.url = isGitLab
const new_url = isGitLab ? url
? raw_url : url?.replace(/\/raw\/[^/]*\/(.*)/, '/raw/$1');
: raw_url?.replace(/\/raw\/[^/]*\/(.*)/, '/raw/$1');
$.info(
`上传配置完成\n文件列表: ${Object.keys(files).join(
', ',
)}\n当前文件: ${encodeURIComponent(
artifact.name,
)}\n响应返回的原始链接: ${raw_url}\n处理完的新链接: ${new_url}`,
);
artifact.url = new_url;
} }
} }

View File

@@ -79,7 +79,8 @@ async function downloadSubscription(req, res) {
if ( if (
sub.source !== 'local' || sub.source !== 'local' ||
['localFirst', 'remoteFirst'].includes(sub.mergeSources) ['localFirst', 'remoteFirst'].includes(sub.mergeSources) ||
url
) { ) {
try { try {
url = `${url || sub.url}` url = `${url || sub.url}`
@@ -112,7 +113,7 @@ async function downloadSubscription(req, res) {
// forward flow headers // forward flow headers
const flowInfo = await getFlowHeaders( const flowInfo = await getFlowHeaders(
url, url,
$arguments.flowUserAgent, undefined,
undefined, undefined,
sub.proxy, sub.proxy,
); );
@@ -249,7 +250,7 @@ async function downloadCollection(req, res) {
if (!$arguments.noFlow) { if (!$arguments.noFlow) {
const flowInfo = await getFlowHeaders( const flowInfo = await getFlowHeaders(
url, url,
$arguments.flowUserAgent, undefined,
undefined, undefined,
sub.proxy, sub.proxy,
); );

View File

@@ -153,14 +153,11 @@ async function gistBackup(req, res) {
} }
success(res); success(res);
} catch (err) { } catch (err) {
$.error(
`Failed to ${action} gist data.\nReason: ${err.message ?? err}`,
);
failed( failed(
res, res,
new InternalServerError( new InternalServerError(
'BACKUP_FAILED', 'BACKUP_FAILED',
`Failed to ${action} gist data!`, `Failed to ${action} data to gist!`,
`Reason: ${err.message ?? err}`, `Reason: ${err.message ?? err}`,
), ),
); );

View File

@@ -115,7 +115,7 @@ async function getFlowInfo(req, res) {
} else { } else {
const flowHeaders = await getFlowHeaders( const flowHeaders = await getFlowHeaders(
url, url,
$arguments.flowUserAgent, undefined,
undefined, undefined,
sub.proxy, sub.proxy,
); );

View File

@@ -563,19 +563,10 @@ async function syncArtifacts() {
files.map((item) => [item.path, item]), files.map((item) => [item.path, item]),
); );
} }
const raw_url = const url = files[encodeURIComponent(artifact.name)]?.raw_url;
files[encodeURIComponent(artifact.name)]?.raw_url; artifact.url = isGitLab
const new_url = isGitLab ? url
? raw_url : url?.replace(/\/raw\/[^/]*\/(.*)/, '/raw/$1');
: raw_url?.replace(/\/raw\/[^/]*\/(.*)/, '/raw/$1');
$.info(
`上传配置完成\n文件列表: ${Object.keys(files).join(
', ',
)}\n当前文件: ${encodeURIComponent(
artifact.name,
)}\n响应返回的原始链接: ${raw_url}\n处理完的新链接: ${new_url}`,
);
artifact.url = new_url;
} }
} }
@@ -669,18 +660,10 @@ async function syncArtifact(req, res) {
isGitLab = true; isGitLab = true;
files = Object.fromEntries(files.map((item) => [item.path, item])); files = Object.fromEntries(files.map((item) => [item.path, item]));
} }
const raw_url = files[encodeURIComponent(artifact.name)]?.raw_url; const url = files[encodeURIComponent(artifact.name)]?.raw_url;
const new_url = isGitLab artifact.url = isGitLab
? raw_url ? url
: raw_url?.replace(/\/raw\/[^/]*\/(.*)/, '/raw/$1'); : url?.replace(/\/raw\/[^/]*\/(.*)/, '/raw/$1');
$.info(
`上传配置完成\n文件列表: ${Object.keys(files).join(
', ',
)}\n当前文件: ${encodeURIComponent(
artifact.name,
)}\n响应返回的原始链接: ${raw_url}\n处理完的新链接: ${new_url}`,
);
artifact.url = new_url;
$.write(allArtifacts, ARTIFACTS_KEY); $.write(allArtifacts, ARTIFACTS_KEY);
success(res, artifact); success(res, artifact);
} catch (err) { } catch (err) {

View File

@@ -129,12 +129,7 @@ export default async function download(rawUrl, ua, timeout, proxy) {
if ($arguments?.validCheck) { if ($arguments?.validCheck) {
await validCheck( await validCheck(
parseFlowHeaders( parseFlowHeaders(
await getFlowHeaders( await getFlowHeaders(url, undefined, undefined, proxy),
url,
$arguments.flowUserAgent,
undefined,
proxy,
),
), ),
); );
} }

View File

@@ -49,11 +49,7 @@ export async function getFlowHeaders(rawUrl, ua, timeout, proxy) {
const requestTimeout = timeout || defaultTimeout; const requestTimeout = timeout || defaultTimeout;
const http = HTTP(); const http = HTTP();
try { try {
$.info( // $.info(`使用 HEAD 方法获取流量信息: ${url}`);
`使用 HEAD 方法获取流量信息: ${url}, User-Agent: ${
userAgent || ''
}`,
);
const { headers } = await http.head({ const { headers } = await http.head({
url: url url: url
.split(/[\r\n]+/) .split(/[\r\n]+/)
@@ -80,17 +76,11 @@ export async function getFlowHeaders(rawUrl, ua, timeout, proxy) {
flowInfo = getFlowField(headers); flowInfo = getFlowField(headers);
} catch (e) { } catch (e) {
$.error( $.error(
`使用 HEAD 方法获取流量信息失败: ${url}, User-Agent: ${ `使用 HEAD 方法获取流量信息失败: ${url}: ${e.message ?? e}`,
userAgent || ''
}: ${e.message ?? e}`,
); );
} }
if (!flowInfo) { if (!flowInfo) {
$.info( $.info(`使用 GET 方法获取流量信息: ${url}`);
`使用 GET 方法获取流量信息: ${url}, User-Agent: ${
userAgent || ''
}`,
);
const { headers } = await http.get({ const { headers } = await http.get({
url: url url: url
.split(/[\r\n]+/) .split(/[\r\n]+/)

View File

@@ -316,7 +316,6 @@ export function HTTP(defaultOptions = { baseURL: '' }) {
url: options.url, url: options.url,
headers: options.headers, headers: options.headers,
body: options.body, body: options.body,
opts: options.opts,
}); });
} else if (isLoon || isSurge || isNode) { } else if (isLoon || isSurge || isNode) {
worker = new Promise((resolve, reject) => { worker = new Promise((resolve, reject) => {

View File

@@ -49,10 +49,7 @@ function operator(proxies = [], targetPlatform, context) {
// 2. sing-box // 2. sing-box
// 但是一般不需要这样用, 可参考 // 但是一般不需要这样用, 可参考 1. https://t.me/zhetengsha/1111 和 2. https://t.me/zhetengsha/1070
// 1. https://t.me/zhetengsha/1111
// 2. https://t.me/zhetengsha/1070
// 3. https://t.me/zhetengsha/1241
// let singboxProxies = await produceArtifact({ // let singboxProxies = await produceArtifact({
// type: 'subscription', // type: 'subscription' 或 'collection' // type: 'subscription', // type: 'subscription' 或 'collection'
@@ -66,41 +63,24 @@ function operator(proxies = [], targetPlatform, context) {
// 3. clash.meta // 3. clash.meta
// 但是一般不需要这样用, 可参考 // 但是一般不需要这样用, 可参考 1. https://t.me/zhetengsha/1111 和 2. https://t.me/zhetengsha/1070
// 1. https://t.me/zhetengsha/1111
// 2. https://t.me/zhetengsha/1070
// 3. https://t.me/zhetengsha/1234
// let clashMetaProxies = await produceArtifact({ // let clashMetaProxies = await produceArtifact({
// type: 'subscription', // type: 'subscription',
// name: 'sub', // name: 'sub',
// platform: 'ClashMeta', // platform: 'ClashMeta',
// produceType: 'internal' // 'internal' produces an Array, otherwise produces a String( ProxyUtils.yaml.safeLoad('YAML String').proxies ) // produceType: 'internal' // 'internal' produces an Array, otherwise produces a String( ProxyUtils.yaml.safeLoad('YAML String').proxies )
// }) // }))
// // YAML // // YAML
// ProxyUtils.yaml.load('YAML String')
// ProxyUtils.yaml.safeLoad('YAML String')
// $content = ProxyUtils.yaml.safeDump({}) // $content = ProxyUtils.yaml.safeDump({})
// $content = ProxyUtils.yaml.dump({})
// 一个往文件里插入本地节点的例子:
// const yaml = ProxyUtils.yaml.safeLoad($content ?? $files[0])
// let clashMetaProxies = await produceArtifact({
// type: 'collection',
// name: '机场',
// platform: 'ClashMeta',
// produceType: 'internal'
// })
// yaml.proxies.unshift(...clashMetaProxies)
// $content = ProxyUtils.yaml.dump(yaml)
// { $content, $files } will be passed to the next operator // { $content, $files } will be passed to the next operator
// $content is the final content of the file // $content is the final content of the file
// flowUtils 为机场订阅流量信息处理工具 // flowUtils 为机场订阅流量信息处理工具
// 可参考: // 可参考 https://t.me/zhetengsha/948
// 1. https://t.me/zhetengsha/948 // https://github.com/sub-store-org/Sub-Store/blob/31b6dd0507a9286d6ab834ec94ad3050f6bdc86b/backend/src/utils/download.js#L104
// context 为传入的上下文 // context 为传入的上下文
// 有三种情况, 按需判断 // 有三种情况, 按需判断