mirror of
https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-10 00:52:40 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b23f82953 | ||
|
|
e071a7f253 | ||
|
|
b9bba895e1 | ||
|
|
8090d678ee | ||
|
|
ff4be7ac38 | ||
|
|
7e2109dc68 | ||
|
|
278beae99a | ||
|
|
3aedd5943d |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sub-store",
|
||||
"version": "2.15.3",
|
||||
"version": "2.16.0",
|
||||
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
|
||||
"main": "src/main.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -75,6 +75,12 @@ export default function Egern_Producer() {
|
||||
if (proxy.tls && !proxy.sni) {
|
||||
proxy.sni = proxy.server;
|
||||
}
|
||||
const prev_hop =
|
||||
proxy.prev_hop ||
|
||||
proxy['underlying-proxy'] ||
|
||||
proxy['dialer-proxy'] ||
|
||||
proxy.detour;
|
||||
|
||||
if (proxy.type === 'http') {
|
||||
proxy = {
|
||||
type: 'http',
|
||||
@@ -133,6 +139,8 @@ export default function Egern_Producer() {
|
||||
next_hop: proxy.next_hop,
|
||||
sni: proxy.sni,
|
||||
skip_tls_verify: proxy['skip-cert-verify'],
|
||||
port_hopping: proxy.ports,
|
||||
port_hopping_interval: proxy['hop-interval'],
|
||||
};
|
||||
if (proxy['obfs-password'] && proxy.obfs == 'salamander') {
|
||||
proxy.obfs = 'salamander';
|
||||
@@ -287,6 +295,7 @@ export default function Egern_Producer() {
|
||||
[proxy.type]: {
|
||||
...proxy,
|
||||
type: undefined,
|
||||
prev_hop,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -568,7 +568,7 @@ const hysteriaParser = (proxy = {}) => {
|
||||
smuxParser(proxy.smux, parsedProxy);
|
||||
return parsedProxy;
|
||||
};
|
||||
const hysteria2Parser = (proxy = {}) => {
|
||||
const hysteria2Parser = (proxy = {}, includeUnsupportedProxy) => {
|
||||
const parsedProxy = {
|
||||
tag: proxy.name,
|
||||
type: 'hysteria2',
|
||||
@@ -580,6 +580,16 @@ const hysteria2Parser = (proxy = {}) => {
|
||||
};
|
||||
if (parsedProxy.server_port < 0 || parsedProxy.server_port > 65535)
|
||||
throw 'invalid port';
|
||||
if (includeUnsupportedProxy) {
|
||||
if (proxy['hop-interval'])
|
||||
parsedProxy.hop_interval = /^\d+$/.test(proxy['hop-interval'])
|
||||
? `${proxy['hop-interval']}s`
|
||||
: proxy['hop-interval'];
|
||||
if (proxy['ports'])
|
||||
parsedProxy.server_ports = proxy['ports']
|
||||
.split(/\s*,\s*/)
|
||||
.map((p) => p.replace(/\s*-\s*/g, ':'));
|
||||
}
|
||||
if (proxy.up) parsedProxy.up_mbps = parseInt(`${proxy.up}`, 10);
|
||||
if (proxy.down) parsedProxy.down_mbps = parseInt(`${proxy.down}`, 10);
|
||||
if (proxy.obfs === 'salamander') parsedProxy.obfs.type = 'salamander';
|
||||
@@ -790,7 +800,12 @@ export default function singbox_Producer() {
|
||||
list.push(hysteriaParser(proxy));
|
||||
break;
|
||||
case 'hysteria2':
|
||||
list.push(hysteria2Parser(proxy));
|
||||
list.push(
|
||||
hysteria2Parser(
|
||||
proxy,
|
||||
opts['include-unsupported-proxy'],
|
||||
),
|
||||
);
|
||||
break;
|
||||
case 'tuic':
|
||||
if (!proxy.token || proxy.token.length === 0) {
|
||||
|
||||
@@ -50,11 +50,21 @@ function createCollection(req, res) {
|
||||
|
||||
function getCollection(req, res) {
|
||||
let { name } = req.params;
|
||||
let { raw } = req.query;
|
||||
name = decodeURIComponent(name);
|
||||
const allCols = $.read(COLLECTIONS_KEY);
|
||||
const collection = findByName(allCols, name);
|
||||
if (collection) {
|
||||
success(res, collection);
|
||||
if (raw) {
|
||||
res.set('content-type', 'application/json')
|
||||
.set(
|
||||
'content-disposition',
|
||||
`attachment; filename="${encodeURIComponent(name)}.json"`,
|
||||
)
|
||||
.send(JSON.stringify(collection));
|
||||
} else {
|
||||
success(res, collection);
|
||||
}
|
||||
} else {
|
||||
failed(
|
||||
res,
|
||||
|
||||
@@ -13,11 +13,44 @@ import { getISO } from '@/utils/geo';
|
||||
import env from '@/utils/env';
|
||||
|
||||
export default function register($app) {
|
||||
$app.get('/share/col/:name/:target', async (req, res) => {
|
||||
const { target } = req.params;
|
||||
if (target) {
|
||||
req.query.target = target;
|
||||
$.info(`使用路由指定目标: ${target}`);
|
||||
}
|
||||
await downloadCollection(req, res);
|
||||
});
|
||||
$app.get('/share/col/:name', downloadCollection);
|
||||
$app.get('/share/sub/:name/:target', async (req, res) => {
|
||||
const { target } = req.params;
|
||||
if (target) {
|
||||
req.query.target = target;
|
||||
$.info(`使用路由指定目标: ${target}`);
|
||||
}
|
||||
await downloadSubscription(req, res);
|
||||
});
|
||||
$app.get('/share/sub/:name', downloadSubscription);
|
||||
|
||||
$app.get('/download/collection/:name/:target', async (req, res) => {
|
||||
const { target } = req.params;
|
||||
if (target) {
|
||||
req.query.target = target;
|
||||
$.info(`使用路由指定目标: ${target}`);
|
||||
}
|
||||
await downloadCollection(req, res);
|
||||
});
|
||||
$app.get('/download/collection/:name', downloadCollection);
|
||||
$app.get('/download/:name/:target', async (req, res) => {
|
||||
const { target } = req.params;
|
||||
if (target) {
|
||||
req.query.target = target;
|
||||
$.info(`使用路由指定目标: ${target}`);
|
||||
}
|
||||
await downloadSubscription(req, res);
|
||||
});
|
||||
$app.get('/download/:name', downloadSubscription);
|
||||
|
||||
$app.get(
|
||||
'/download/collection/:name/api/v1/server/details',
|
||||
async (req, res) => {
|
||||
@@ -59,11 +92,9 @@ async function downloadSubscription(req, res) {
|
||||
|
||||
const platform =
|
||||
req.query.target || getPlatformFromHeaders(req.headers) || 'JSON';
|
||||
|
||||
const reqUA = req.headers['user-agent'] || req.headers['User-Agent'];
|
||||
$.info(
|
||||
`正在下载订阅:${name}\n请求 User-Agent: ${
|
||||
req.headers['user-agent'] || req.headers['User-Agent']
|
||||
}\n请求 target: ${req.query.target}\n实际输出: ${platform}`,
|
||||
`正在下载订阅:${name}\n请求 User-Agent: ${reqUA}\n请求 target: ${req.query.target}\n实际输出: ${platform}`,
|
||||
);
|
||||
let {
|
||||
url,
|
||||
@@ -98,6 +129,14 @@ async function downloadSubscription(req, res) {
|
||||
if (url) {
|
||||
url = decodeURIComponent(url);
|
||||
$.info(`指定远程订阅 URL: ${url}`);
|
||||
if (!/^https?:\/\//.test(url)) {
|
||||
content = url;
|
||||
$.info(`URL 不是链接,视为本地订阅`);
|
||||
}
|
||||
}
|
||||
if (content) {
|
||||
content = decodeURIComponent(content);
|
||||
$.info(`指定本地订阅: ${content}`);
|
||||
}
|
||||
if (proxy) {
|
||||
proxy = decodeURIComponent(proxy);
|
||||
@@ -107,10 +146,7 @@ async function downloadSubscription(req, res) {
|
||||
ua = decodeURIComponent(ua);
|
||||
$.info(`指定远程订阅 User-Agent: ${ua}`);
|
||||
}
|
||||
if (content) {
|
||||
content = decodeURIComponent(content);
|
||||
$.info(`指定本地订阅: ${content}`);
|
||||
}
|
||||
|
||||
if (mergeSources) {
|
||||
mergeSources = decodeURIComponent(mergeSources);
|
||||
$.info(`指定合并来源: ${mergeSources}`);
|
||||
@@ -140,6 +176,13 @@ async function downloadSubscription(req, res) {
|
||||
const sub = findByName(allSubs, name);
|
||||
if (sub) {
|
||||
try {
|
||||
const passThroughUA = sub.passThroughUA;
|
||||
if (passThroughUA) {
|
||||
$.info(
|
||||
`订阅开启了透传 User-Agent, 使用请求的 User-Agent: ${reqUA}`,
|
||||
);
|
||||
ua = reqUA;
|
||||
}
|
||||
let output = await produceArtifact({
|
||||
type: 'subscription',
|
||||
name,
|
||||
|
||||
@@ -197,11 +197,21 @@ async function getFile(req, res) {
|
||||
}
|
||||
function getWholeFile(req, res) {
|
||||
let { name } = req.params;
|
||||
let { raw } = req.query;
|
||||
name = decodeURIComponent(name);
|
||||
const allFiles = $.read(FILES_KEY);
|
||||
const file = findByName(allFiles, name);
|
||||
if (file) {
|
||||
success(res, file);
|
||||
if (raw) {
|
||||
res.set('content-type', 'application/json')
|
||||
.set(
|
||||
'content-disposition',
|
||||
`attachment; filename="${encodeURIComponent(name)}.json"`,
|
||||
)
|
||||
.send(JSON.stringify(file));
|
||||
} else {
|
||||
success(res, file);
|
||||
}
|
||||
} else {
|
||||
failed(
|
||||
res,
|
||||
|
||||
@@ -73,7 +73,7 @@ async function produceArtifact({
|
||||
proxy || sub.proxy,
|
||||
undefined,
|
||||
awaitCustomCache,
|
||||
noCache,
|
||||
noCache || sub.noCache,
|
||||
true,
|
||||
);
|
||||
} catch (err) {
|
||||
@@ -122,7 +122,7 @@ async function produceArtifact({
|
||||
proxy || sub.proxy,
|
||||
undefined,
|
||||
awaitCustomCache,
|
||||
noCache,
|
||||
noCache || sub.noCache,
|
||||
true,
|
||||
);
|
||||
} catch (err) {
|
||||
@@ -244,7 +244,7 @@ async function produceArtifact({
|
||||
collection.proxy,
|
||||
undefined,
|
||||
undefined,
|
||||
noCache,
|
||||
noCache || sub.noCache,
|
||||
true,
|
||||
);
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user