feat: fix ss
This commit is contained in:
@@ -6,6 +6,12 @@ export interface ParsedNode {
|
||||
surgeLine: string;
|
||||
}
|
||||
|
||||
// Surge 使用与标准 Shadowsocks 不同的加密方式命名,需做别名映射
|
||||
const ENCRYPT_METHOD_ALIASES: Record<string, string> = {
|
||||
'chacha20-poly1305': 'chacha20-ietf-poly1305',
|
||||
'xchacha20-poly1305': 'xchacha20-ietf-poly1305',
|
||||
};
|
||||
|
||||
export function parseSS(uri: string): ParsedNode {
|
||||
const url = new URL(uri);
|
||||
const name = decodeURIComponent(url.hash.slice(1));
|
||||
@@ -14,11 +20,18 @@ export function parseSS(uri: string): ParsedNode {
|
||||
|
||||
const decoded = Buffer.from(url.username, 'base64').toString();
|
||||
const firstColon = decoded.indexOf(':');
|
||||
const method = decoded.slice(0, firstColon);
|
||||
const rawMethod = decoded.slice(0, firstColon);
|
||||
const method = ENCRYPT_METHOD_ALIASES[rawMethod] ?? rawMethod;
|
||||
const password = decoded.slice(firstColon + 1);
|
||||
|
||||
// SS 2022 has built-in encryption, Surge does not support SS over TLS
|
||||
const surgeLine = `${name} = ss, ${server}, ${port}, encrypt-method=${method}, password=${password}`;
|
||||
|
||||
return { name, type: 'ss', server, port, surgeLine };
|
||||
// Surge's `ss` proxy type has no WebSocket/TLS transport support at all (unlike
|
||||
// trojan/vmess/vless) — this Xray-style ss+ws+tls link can never work in Surge,
|
||||
// so it's tagged 'ss-ws' and excluded from Surge output (see generator.ts).
|
||||
// Clash/SSR generators re-parse the raw uri independently and are unaffected.
|
||||
const type = url.searchParams.get('type') === 'ws' ? 'ss-ws' : 'ss';
|
||||
|
||||
return { name, type, server, port, surgeLine };
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ParsedNode } from './ss.js';
|
||||
import { normalizeWsPath } from './util.js';
|
||||
|
||||
export function parseTrojan(uri: string): ParsedNode {
|
||||
const url = new URL(uri);
|
||||
@@ -9,7 +10,13 @@ export function parseTrojan(uri: string): ParsedNode {
|
||||
const params = url.searchParams;
|
||||
const sni = params.get('sni') || server;
|
||||
|
||||
const surgeLine = `${name} = trojan, ${server}, ${port}, password=${password}, tls=true, sni=${sni}, skip-cert-verify=false`;
|
||||
let surgeLine = `${name} = trojan, ${server}, ${port}, password=${password}, tls=true, sni=${sni}, skip-cert-verify=false`;
|
||||
|
||||
if (params.get('type') === 'ws') {
|
||||
const path = params.get('path') || '/';
|
||||
const host = params.get('host') || sni;
|
||||
surgeLine += `, ws=true, ws-path=${normalizeWsPath(path)}, ws-headers=Host:${host}`;
|
||||
}
|
||||
|
||||
return { name, type: 'trojan', server, port, surgeLine };
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ function renameSurgeLine(surgeLine: string, oldName: string, newName: string): s
|
||||
return surgeLine;
|
||||
}
|
||||
|
||||
const rows = db.prepare('SELECT id, name, uri, surge_line FROM static_nodes').all() as Array<{
|
||||
const rows = db.prepare('SELECT id, name, uri, surge_line, type FROM static_nodes').all() as Array<{
|
||||
id: number;
|
||||
name: string;
|
||||
uri: string;
|
||||
surge_line: string;
|
||||
type: string;
|
||||
}>;
|
||||
|
||||
const update = db.prepare('UPDATE static_nodes SET surge_line = ?, type = ? WHERE id = ?');
|
||||
@@ -31,7 +32,7 @@ for (const row of rows) {
|
||||
continue;
|
||||
}
|
||||
const newLine = renameSurgeLine(node.surgeLine, node.name, row.name);
|
||||
if (newLine !== row.surge_line) {
|
||||
if (newLine !== row.surge_line || node.type !== row.type) {
|
||||
update.run(newLine, node.type, row.id);
|
||||
changed++;
|
||||
console.log(`[updated] id=${row.id} "${row.name}"`);
|
||||
|
||||
@@ -15,18 +15,21 @@ export function generateSurgeConfig(hostUrl: string, whitelist?: Set<string>): s
|
||||
return '# No subscription config available. Add and fetch a subscription first.';
|
||||
}
|
||||
|
||||
// Collect fetched nodes (exclude vless — Surge doesn't support it; tuic uses `tuic-v5`)
|
||||
// Exclude vless and ss-ws (Surge doesn't support either transport)
|
||||
const UNSUPPORTED = "type NOT IN ('vless', 'ss-ws')";
|
||||
|
||||
// Collect fetched nodes (tuic uses `tuic-v5`)
|
||||
const fetchedNodes = db.prepare(
|
||||
whitelist
|
||||
? "SELECT surge_line FROM fetched_nodes WHERE type != 'vless' ORDER BY subscription_id, sort_order, id"
|
||||
: "SELECT surge_line FROM fetched_nodes WHERE enabled = 1 AND type != 'vless' ORDER BY subscription_id, sort_order, id"
|
||||
? `SELECT surge_line FROM fetched_nodes WHERE ${UNSUPPORTED} ORDER BY subscription_id, sort_order, id`
|
||||
: `SELECT surge_line FROM fetched_nodes WHERE enabled = 1 AND ${UNSUPPORTED} ORDER BY subscription_id, sort_order, id`
|
||||
).all() as any[];
|
||||
|
||||
// Collect static nodes (these go FIRST, exclude vless)
|
||||
// Collect static nodes (these go FIRST)
|
||||
const staticNodes = db.prepare(
|
||||
whitelist
|
||||
? "SELECT surge_line FROM static_nodes WHERE type != 'vless' ORDER BY sort_order, id"
|
||||
: "SELECT surge_line FROM static_nodes WHERE enabled = 1 AND type != 'vless' ORDER BY sort_order, id"
|
||||
? `SELECT surge_line FROM static_nodes WHERE ${UNSUPPORTED} ORDER BY sort_order, id`
|
||||
: `SELECT surge_line FROM static_nodes WHERE enabled = 1 AND ${UNSUPPORTED} ORDER BY sort_order, id`
|
||||
).all() as any[];
|
||||
|
||||
// Collect enabled rules
|
||||
|
||||
Reference in New Issue
Block a user