mirror of
https://git.mirrors.martin98.com/https://github.com/sub-store-org/Sub-Store.git
synced 2026-04-29 10:48:05 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59a9290f9e |
@@ -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": {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) =>
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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}`,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]+/)
|
||||||
|
|||||||
1
backend/src/vendor/open-api.js
vendored
1
backend/src/vendor/open-api.js
vendored
@@ -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) => {
|
||||||
|
|||||||
@@ -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 为传入的上下文
|
||||||
// 有三种情况, 按需判断
|
// 有三种情况, 按需判断
|
||||||
|
|||||||
Reference in New Issue
Block a user