Skip to content

Commit a5ef7ff

Browse files
author
jiangwy
committed
feat: 优化SingboxClient和Parser类的配置获取与解析逻辑,增加错误处理机制
1 parent ad3a982 commit a5ef7ff

6 files changed

Lines changed: 99 additions & 79 deletions

File tree

src/core/confuse/client/singbox.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import type { SingboxOutboundType, SingboxType } from '../../../types';
22
import { fetchWithRetry } from 'cloudflare-tools';
3+
import { isJson } from '../../../shared/index';
34
import { PsUtil } from '../../../shared/ps';
45

56
export class SingboxClient {
67
public async getConfig(urls: string[]): Promise<SingboxType> {
78
try {
8-
const result = await Promise.all(
9-
urls.map(url => fetchWithRetry(url, { retries: 3 }).then(r => r.data.json())) as SingboxType[]
10-
);
11-
return this.mergeConfig(result);
9+
const result = await Promise.all(urls.map(url => fetchWithRetry(url, { retries: 3 }).then(r => r.data.text())));
10+
const configs = result.filter(it => isJson(it)).map(it => JSON.parse(it)) as SingboxType[];
11+
return this.mergeConfig(configs);
1212
} catch (error: any) {
1313
throw new Error(`Failed to get singbox config: ${error.message || error}`);
1414
}

src/core/parser/index.ts

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -32,45 +32,49 @@ export class Parser extends Convert {
3232

3333
public async parse(vps: string[] = this.vps): Promise<void> {
3434
for await (const v of vps) {
35-
const processVps = this.updateVpsPs(v);
36-
37-
if (processVps) {
38-
let parser: ParserType | null = null;
39-
40-
if (processVps.startsWith('vless://') && this.hasProtocol('vless')) {
41-
parser = new VlessParser(processVps);
42-
} else if (processVps.startsWith('vmess://') && this.hasProtocol('vmess')) {
43-
parser = new VmessParser(processVps);
44-
} else if (processVps.startsWith('trojan://') && this.hasProtocol('trojan')) {
45-
parser = new TrojanParser(processVps);
46-
} else if (processVps.startsWith('ss://') && this.hasProtocol('shadowsocks')) {
47-
parser = new SsParser(processVps);
48-
} else if (this.isHysteria2(processVps) && this.hasProtocol('hysteria', 'hysteria2', 'hy2')) {
49-
parser = new Hysteria2Parser(processVps);
50-
}
35+
try {
36+
const processVps = this.updateVpsPs(v);
37+
38+
if (processVps) {
39+
let parser: ParserType | null = null;
40+
41+
if (processVps.startsWith('vless://') && this.hasProtocol('vless')) {
42+
parser = new VlessParser(processVps);
43+
} else if (processVps.startsWith('vmess://') && this.hasProtocol('vmess')) {
44+
parser = new VmessParser(processVps);
45+
} else if (processVps.startsWith('trojan://') && this.hasProtocol('trojan')) {
46+
parser = new TrojanParser(processVps);
47+
} else if (processVps.startsWith('ss://') && this.hasProtocol('shadowsocks')) {
48+
parser = new SsParser(processVps);
49+
} else if (this.isHysteria2(processVps) && this.hasProtocol('hysteria', 'hysteria2', 'hy2')) {
50+
parser = new Hysteria2Parser(processVps);
51+
}
5152

52-
if (parser) {
53-
this.setStore(processVps, parser);
53+
if (parser) {
54+
this.setStore(processVps, parser);
55+
}
5456
}
55-
}
5657

57-
if (v.startsWith('https://') || v.startsWith('http://')) {
58-
const subContent = await fetchWithRetry(v, { retries: 3 }).then(r => r.data.text());
59-
const { subType, content } = this.getSubType(subContent);
58+
if (v.startsWith('https://') || v.startsWith('http://')) {
59+
const subContent = await fetchWithRetry(v, { retries: 3 }).then(r => r.data.text());
60+
const { subType, content } = this.getSubType(subContent);
6061

61-
if (subType === 'base64' && content) {
62-
this.updateExist(Array.from(this.originUrls));
63-
await this.parse(content.split('\n').filter(Boolean));
64-
}
65-
66-
if (subType === 'yaml' && content) {
67-
const proxies = content.proxies;
68-
if (proxies.length) {
62+
if (subType === 'base64' && content) {
6963
this.updateExist(Array.from(this.originUrls));
70-
const vps = getYamlProxies(proxies);
71-
await this.parse(vps.filter(Boolean));
64+
await this.parse(content.split('\n').filter(Boolean));
65+
}
66+
67+
if (subType === 'yaml' && content) {
68+
const proxies = content.proxies;
69+
if (proxies.length) {
70+
this.updateExist(Array.from(this.originUrls));
71+
const vps = getYamlProxies(proxies);
72+
await this.parse(vps.filter(Boolean));
73+
}
7274
}
7375
}
76+
} catch {
77+
continue;
7478
}
7579
}
7680
}

src/core/parser/yaml/index.ts

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,35 @@ import { vmessConvert } from './protocol/vmess';
1010
export function getYamlProxies(proxies: ClashType['proxies']): string[] {
1111
const proxiesList: string[] = [];
1212
for (const proxy of proxies) {
13-
if (proxy.type === 'vmess') {
14-
proxiesList.push(vmessConvert(proxy));
15-
}
16-
17-
if (proxy.type === 'trojan') {
18-
proxiesList.push(trojanConvert(proxy));
19-
}
20-
21-
if (proxy.type === 'vless') {
22-
proxiesList.push(vlessConvert(proxy));
23-
}
24-
25-
if (proxy.type === 'ss') {
26-
proxiesList.push(shadowsocksConvert(proxy));
27-
}
28-
if (proxy.type === 'ssr') {
29-
proxiesList.push(shadowsocksRConvert(proxy));
30-
}
31-
32-
if (proxy.type === 'hysteria2' || proxy.type === 'hy2') {
33-
proxiesList.push(hysteria2Convert(proxy));
34-
}
35-
36-
if (proxy.type === 'hysteria') {
37-
proxiesList.push(hysteriaConvert(proxy));
13+
try {
14+
if (proxy.type === 'vmess') {
15+
proxiesList.push(vmessConvert(proxy));
16+
}
17+
18+
if (proxy.type === 'trojan') {
19+
proxiesList.push(trojanConvert(proxy));
20+
}
21+
22+
if (proxy.type === 'vless') {
23+
proxiesList.push(vlessConvert(proxy));
24+
}
25+
26+
if (proxy.type === 'ss') {
27+
proxiesList.push(shadowsocksConvert(proxy));
28+
}
29+
if (proxy.type === 'ssr') {
30+
proxiesList.push(shadowsocksRConvert(proxy));
31+
}
32+
33+
if (proxy.type === 'hysteria2' || proxy.type === 'hy2') {
34+
proxiesList.push(hysteria2Convert(proxy));
35+
}
36+
37+
if (proxy.type === 'hysteria') {
38+
proxiesList.push(hysteriaConvert(proxy));
39+
}
40+
} catch {
41+
continue;
3842
}
3943
}
4044

src/core/restore/client/clash.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,25 @@ export class ClashClient {
2525
}
2626

2727
private restoreProxies(proxies: Array<Record<string, string>> | null, vpsMap: VpsMap): Array<Record<string, string>> {
28-
try {
29-
if (!proxies) {
30-
return [];
31-
}
32-
33-
const result: Array<Record<string, string>> = [];
34-
for (const proxy of proxies) {
28+
const result: Array<Record<string, string>> = [];
29+
if (!proxies) {
30+
return result;
31+
}
32+
for (const proxy of proxies) {
33+
try {
3534
const [originPs, confusePs] = PsUtil.getPs(proxy.name);
3635
if (vpsMap.has(confusePs)) {
3736
const vps = vpsMap.get(confusePs);
3837
vps?.restoreClash(proxy, originPs);
3938
result.push(proxy);
4039
}
40+
} catch (error: any) {
41+
console.warn(`Restore proxies failed: ${error.message || error}, function trace: ${error.stack}`);
42+
continue;
4143
}
42-
43-
return result;
44-
} catch (error: any) {
45-
throw new Error(`Restore proxies failed: ${error.message || error}, function trace: ${error.stack}`);
4644
}
45+
46+
return result;
4747
}
4848

4949
private updateProxiesGroups(proxies: string[]): string[] {

src/core/restore/client/singbox.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ export class SingboxClient {
1818
}
1919

2020
private restoreOutbounds(outbounds: SingboxType['outbounds'] = [], vpsMap: VpsMap): SingboxType['outbounds'] {
21-
try {
22-
const result: SingboxType['outbounds'] = [];
23-
for (const outbound of outbounds) {
21+
const result: SingboxType['outbounds'] = [];
22+
if (!outbounds) {
23+
return result;
24+
}
25+
for (const outbound of outbounds) {
26+
try {
2427
if (this.isConfuseVps(outbound.tag)) {
2528
const [originPs, confusePs] = PsUtil.getPs(outbound.tag);
2629
const vps = vpsMap.get(confusePs);
@@ -31,12 +34,12 @@ export class SingboxClient {
3134
outbound.outbounds = this.updateOutbouns(outbound.outbounds);
3235
}
3336
result.push(outbound);
37+
} catch (error: any) {
38+
console.warn(`Restore outbounds failed: ${error.message || error}, function trace: ${error.stack}`);
39+
continue;
3440
}
35-
36-
return result;
37-
} catch (error: any) {
38-
throw new Error(`Restore outbounds failed: ${error.message || error}, function trace: ${error.stack}`);
3941
}
42+
return result;
4043
}
4144

4245
private updateOutbouns(outbounds: string[] | undefined = []): string[] {
@@ -57,3 +60,4 @@ export class SingboxClient {
5760
return PsUtil.isConfigType(tag);
5861
}
5962
}
63+

src/shared/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,11 @@ export function getUrlGroup(urls: string[], chunkCount: number = 10): string[] {
2020
return urlGroup;
2121
}
2222

23+
export function isJson(text: string): boolean {
24+
try {
25+
JSON.parse(text);
26+
return true;
27+
} catch {
28+
return false;
29+
}
30+
}

0 commit comments

Comments
 (0)