feat: init proj

This commit is contained in:
2026-03-31 13:11:54 +08:00
commit 8f75ea24d6
38 changed files with 6826 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
import { parseSS, type ParsedNode } from './ss.js';
import { parseVMess } from './vmess.js';
import { parseTrojan } from './trojan.js';
export type { ParsedNode };
export function parseNodeUri(uri: string): ParsedNode | null {
try {
if (uri.startsWith('ss://')) return parseSS(uri);
if (uri.startsWith('vmess://')) return parseVMess(uri);
if (uri.startsWith('trojan://')) return parseTrojan(uri);
return null;
} catch {
return null;
}
}
export function parseSubscriptionContent(content: string): ParsedNode[] {
// Try base64 decode first (common subscription format)
let text = content;
try {
const decoded = Buffer.from(content.trim(), 'base64').toString();
if (decoded.includes('://')) {
text = decoded;
}
} catch {
// Not base64, use as-is
}
// If it's a Surge config (contains sections), extract proxy lines
if (text.includes('[Proxy]') || text.includes('[General]')) {
return parseSurgeConfig(text);
}
// Otherwise treat as URI list
const lines = text.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#'));
const nodes: ParsedNode[] = [];
for (const line of lines) {
const node = parseNodeUri(line);
if (node) nodes.push(node);
}
return nodes;
}
function parseSurgeConfig(config: string): ParsedNode[] {
const lines = config.split('\n');
const nodes: ParsedNode[] = [];
let inProxySection = false;
for (const line of lines) {
const trimmed = line.trim();
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
inProxySection = trimmed === '[Proxy]';
continue;
}
if (!inProxySection) continue;
if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('//')) continue;
// Parse "Name = type, server, port, ..."
const eqIdx = trimmed.indexOf('=');
if (eqIdx === -1) continue;
const name = trimmed.slice(0, eqIdx).trim();
const rest = trimmed.slice(eqIdx + 1).trim();
const parts = rest.split(',').map(p => p.trim());
const type = parts[0] || '';
const server = parts[1] || '';
const port = parseInt(parts[2] || '0', 10);
if (name && type && server) {
nodes.push({
name,
type,
server,
port,
surgeLine: trimmed,
});
}
}
return nodes;
}