Skip to content

Commit de98bc3

Browse files
committed
feat: VLESS URI 输入兼容 Shadowrocket 导出格式
1 parent f4c4cdb commit de98bc3

File tree

3 files changed

+49
-10
lines changed

3 files changed

+49
-10
lines changed

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sub-store",
3-
"version": "2.14.162",
3+
"version": "2.14.164",
44
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
55
"main": "src/main.js",
66
"scripts": {

backend/src/core/proxy-utils/parsers/index.js

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -331,15 +331,27 @@ function URI_VLESS() {
331331
};
332332
const parse = (line) => {
333333
line = line.split('vless://')[1];
334+
let isShadowrocket;
335+
let parsed = /^(.*?)@(.*?):(\d+)\/?(\?(.*?))?(?:#(.*?))?$/.exec(line);
336+
if (!parsed) {
337+
// eslint-disable-next-line no-unused-vars
338+
let [_, base64, other] = /^(.*?)(\?.*?$)/.exec(line);
339+
line = `${Base64.decode(base64)}${other}`;
340+
parsed = /^(.*?)@(.*?):(\d+)\/?(\?(.*?))?(?:#(.*?))?$/.exec(line);
341+
isShadowrocket = true;
342+
}
334343
// eslint-disable-next-line no-unused-vars
335-
let [__, uuid, server, port, ___, addons = '', name] =
336-
/^(.*?)@(.*?):(\d+)\/?(\?(.*?))?(?:#(.*?))?$/.exec(line);
344+
let [__, uuid, server, port, ___, addons = '', name] = parsed;
345+
if (isShadowrocket) {
346+
uuid = uuid.replace(/^.*?:/g, '');
347+
}
348+
337349
port = parseInt(`${port}`, 10);
338350
uuid = decodeURIComponent(uuid);
339351
if (name != null) {
340352
name = decodeURIComponent(name);
341353
}
342-
name = name ?? `VLESS ${server}:${port}`;
354+
343355
const proxy = {
344356
type: 'vless',
345357
name,
@@ -355,9 +367,29 @@ function URI_VLESS() {
355367
params[key] = value;
356368
}
357369

370+
proxy.name = name ?? params.remarks ?? `VLESS ${server}:${port}`;
371+
358372
proxy.tls = params.security && params.security !== 'none';
359-
proxy.sni = params.sni;
373+
if (
374+
isShadowrocket &&
375+
!proxy.tls &&
376+
params.tls &&
377+
!/0|none|false/.test(params.tls)
378+
) {
379+
proxy.tls = true;
380+
params.security = params.security ?? 'reality';
381+
}
382+
proxy.sni = params.sni ?? params.peer;
360383
proxy.flow = params.flow;
384+
if (!proxy.flow && isShadowrocket && params.xtls) {
385+
// "none" is undefined
386+
const flow = [undefined, 'xtls-rprx-direct', 'xtls-rprx-vision'][
387+
params.xtls
388+
];
389+
if (flow) {
390+
proxy.flow = flow;
391+
}
392+
}
361393
proxy['client-fingerprint'] = params.fp;
362394
proxy.alpn = params.alpn ? params.alpn.split(',') : undefined;
363395
proxy['skip-cert-verify'] = /(TRUE)|1/i.test(params.allowInsecure);
@@ -371,21 +403,28 @@ function URI_VLESS() {
371403
opts['short-id'] = params.sid;
372404
}
373405
if (Object.keys(opts).length > 0) {
406+
// proxy[`${params.security}-opts`] = opts;
374407
proxy[`${params.security}-opts`] = opts;
375408
}
376409
}
377410

378411
proxy.network = params.type;
412+
if (!proxy.network && isShadowrocket && params.obfs) {
413+
proxy.network = params.obfs;
414+
}
379415
if (proxy.network && !['tcp', 'none'].includes(proxy.network)) {
380416
const opts = {};
381-
if (params.path) {
382-
opts.path = params.path;
383-
}
384417
if (params.host) {
385418
opts.headers = { Host: params.host };
386419
}
387420
if (params.serviceName) {
388421
opts[`${proxy.network}-service-name`] = params.serviceName;
422+
} else if (isShadowrocket && params.path) {
423+
opts[`${proxy.network}-service-name`] = params.path;
424+
delete params.path;
425+
}
426+
if (params.path) {
427+
opts.path = params.path;
389428
}
390429
// https://github.com/XTLS/Xray-core/issues/91
391430
if (['grpc'].includes(proxy.network)) {

backend/src/utils/flow.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export async function getFlowHeaders(url, ua, timeout) {
3131
const cached = headersResourceCache.get(url);
3232
let flowInfo;
3333
if (!$arguments?.noCache && cached) {
34-
$.info(`使用缓存的流量信息: ${url}`);
34+
// $.info(`使用缓存的流量信息: ${url}`);
3535
flowInfo = cached;
3636
} else {
3737
const { defaultFlowUserAgent, defaultTimeout } = $.read(SETTINGS_KEY);
@@ -42,7 +42,7 @@ export async function getFlowHeaders(url, ua, timeout) {
4242
const requestTimeout = timeout || defaultTimeout;
4343
const http = HTTP();
4444
try {
45-
$.info(`使用 HEAD 方法获取流量信息: ${url}`);
45+
// $.info(`使用 HEAD 方法获取流量信息: ${url}`);
4646
const { headers } = await http.head({
4747
url: url
4848
.split(/[\r\n]+/)

0 commit comments

Comments
 (0)