Compare commits

..

6 Commits

Author SHA1 Message Date
xream
f9d120bac3 feat: 兼容 v2rayN 非标 TUIC URI
Some checks failed
build / build (push) Has been cancelled
2025-02-13 20:26:59 +08:00
xream
72a445ae33 doc: README 2025-02-12 22:39:18 +08:00
xream
5e2a87e250 fix: 修复 Shadowsocks URI 解析
Some checks are pending
build / build (push) Waiting to run
2025-02-12 19:21:24 +08:00
xream
71fc9affbf feat: 支持 v2ray SOCKS URI 的输入和输出
Some checks are pending
build / build (push) Waiting to run
2025-02-12 03:27:40 +08:00
xream
6f82294c49 fix: 修复 Egern VMess tcp 2025-02-11 23:56:45 +08:00
xream
7c398ba51c fix: 修复 mihomo 覆写配置无法使用普通脚本的问题
Some checks are pending
build / build (push) Waiting to run
2025-02-11 13:18:42 +08:00
7 changed files with 64 additions and 9 deletions

View File

@@ -32,7 +32,7 @@ Core functionalities:
example: `socks5+tls://user:pass@ip:port#name` example: `socks5+tls://user:pass@ip:port#name`
- [x] URI(SS, SSR, VMess, VLESS, Trojan, Hysteria, Hysteria 2, TUIC v5, WireGuard) - [x] URI(SOCKS, 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)
- [x] QX (SS, SSR, VMess, Trojan, HTTP, SOCKS5, VLESS) - [x] QX (SS, SSR, VMess, Trojan, HTTP, SOCKS5, VLESS)

View File

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

@@ -76,7 +76,46 @@ function URI_PROXY() {
}; };
return { name, test, parse }; return { name, test, parse };
} }
function URI_SOCKS() {
const name = 'URI SOCKS Parser';
const test = (line) => {
return /^socks:\/\//.test(line);
};
const parse = (line) => {
// parse url
// eslint-disable-next-line no-unused-vars
let [__, type, auth, server, port, query, name] = line.match(
/^(socks)?:\/\/(?:(.*)@)?(.*?)(?::(\d+?))?(\?.*?)?(?:#(.*?))?$/,
);
if (port) {
port = parseInt(port, 10);
} else {
$.error(`port is not present in line: ${line}`);
throw new Error(`port is not present in line: ${line}`);
}
let username, password;
if (auth) {
const parsed = Base64.decode(decodeURIComponent(auth)).split(':');
username = parsed[0];
password = parsed[1];
}
const proxy = {
name:
name != null
? decodeURIComponent(name)
: `${type} ${server}:${port}`,
type: 'socks5',
server,
port,
username,
password,
};
return proxy;
};
return { name, test, parse };
}
// Parse SS URI format (only supports new SIP002, legacy format is depreciated). // Parse SS URI format (only supports new SIP002, legacy format is depreciated).
// reference: https://github.com/shadowsocks/shadowsocks-org/wiki/SIP002-URI-Scheme // reference: https://github.com/shadowsocks/shadowsocks-org/wiki/SIP002-URI-Scheme
function URI_SS() { function URI_SS() {
@@ -113,6 +152,7 @@ function URI_SS() {
query = parsed[2]; query = parsed[2];
} }
content = Base64.decode(content); content = Base64.decode(content);
if (query) { if (query) {
if (/(&|\?)v2ray-plugin=/.test(query)) { if (/(&|\?)v2ray-plugin=/.test(query)) {
const parsed = query.match(/(&|\?)v2ray-plugin=(.*?)(&|$)/); const parsed = query.match(/(&|\?)v2ray-plugin=(.*?)(&|$)/);
@@ -126,8 +166,8 @@ function URI_SS() {
} }
content = `${content}${query}`; content = `${content}${query}`;
} }
userInfoStr = content.split('@')[0]; userInfoStr = content.match(/(^.*)@/)?.[1];
serverAndPortArray = content.match(/@([^/]*)(\/|$)/); serverAndPortArray = content.match(/@([^/@]*)(\/|$)/);
} else if (content.includes('?')) { } else if (content.includes('?')) {
const parsed = content.match(/(\?.*)$/); const parsed = content.match(/(\?.*)$/);
query = parsed[1]; query = parsed[1];
@@ -799,8 +839,11 @@ function URI_TUIC() {
const parse = (line) => { const parse = (line) => {
line = line.split(/tuic:\/\//)[1]; line = line.split(/tuic:\/\//)[1];
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
let [__, uuid, password, server, ___, port, ____, addons = '', name] = let [__, auth, server, port, addons = '', name] =
/^(.*?):(.*?)@(.*?)(:(\d+))?\/?(\?(.*?))?(?:#(.*?))?$/.exec(line); /^(.*?)@(.*?)(?::(\d+))?\/?(?:\?(.*?))?(?:#(.*?))?$/.exec(line);
auth = decodeURIComponent(auth);
let [uuid, ...passwordParts] = auth.split(':');
let password = passwordParts.join(':');
port = parseInt(`${port}`, 10); port = parseInt(`${port}`, 10);
if (isNaN(port)) { if (isNaN(port)) {
port = 443; port = 443;
@@ -1467,6 +1510,7 @@ function isIP(ip) {
export default [ export default [
URI_PROXY(), URI_PROXY(),
URI_SOCKS(),
URI_SS(), URI_SS(),
URI_SSR(), URI_SSR(),
URI_VMess(), URI_VMess(),

View File

@@ -16,6 +16,7 @@ function Base64Encoded() {
const keys = [ const keys = [
'dm1lc3M', // vmess 'dm1lc3M', // vmess
'c3NyOi8v', // ssr:// 'c3NyOi8v', // ssr://
'c29ja3M6Ly', // socks://
'dHJvamFu', // trojan 'dHJvamFu', // trojan
'c3M6Ly', // ss:/ 'c3M6Ly', // ss:/
'c3NkOi8v', // ssd:// 'c3NkOi8v', // ssd://

View File

@@ -365,7 +365,9 @@ function ScriptOperator(script, targetPlatform, $arguments, source, $options) {
if (output?.$file?.type === 'mihomoProfile') { if (output?.$file?.type === 'mihomoProfile') {
try { try {
let patch = YAML.safeLoad(script); let patch = YAML.safeLoad(script);
if (typeof patch !== 'object') patch = {}; // if (typeof patch !== 'object') patch = {};
if (typeof patch !== 'object')
throw new Error('patch is not an object');
output.$content = ProxyUtils.yaml.safeDump( output.$content = ProxyUtils.yaml.safeDump(
deepMerge( deepMerge(
{ {

View File

@@ -241,9 +241,12 @@ export default function Egern_Producer() {
skip_tls_verify: proxy['skip-cert-verify'], skip_tls_verify: proxy['skip-cert-verify'],
}, },
}; };
} else if (proxy.network === 'tcp' || !proxy.network) { } else if (
(proxy.network === 'tcp' || !proxy.network) &&
proxy.tls
) {
proxy.transport = { proxy.transport = {
[proxy.tls ? 'tls' : 'tcp']: { tls: {
sni: proxy.tls ? proxy.sni : undefined, sni: proxy.tls ? proxy.sni : undefined,
skip_tls_verify: proxy.tls skip_tls_verify: proxy.tls
? proxy['skip-cert-verify'] ? proxy['skip-cert-verify']

View File

@@ -27,6 +27,11 @@ export default function URI_Producer() {
proxy.server = `[${proxy.server}]`; proxy.server = `[${proxy.server}]`;
} }
switch (proxy.type) { switch (proxy.type) {
case 'socks5':
result = `socks://${encodeURIComponent(
Base64.encode(`${proxy.username}:${proxy.password}`),
)}@${proxy.server}:${proxy.port}#${proxy.name}`;
break;
case 'ss': case 'ss':
const userinfo = `${proxy.cipher}:${proxy.password}`; const userinfo = `${proxy.cipher}:${proxy.password}`;
result = `ss://${ result = `ss://${