@@ -4,21 +4,38 @@ import { CLASH_CONFIG, SELECTORS_LIST } from './config.js';
4
4
import { DeepCopy } from './utils.js' ;
5
5
6
6
export class ClashConfigBuilder {
7
- constructor ( inputString ) {
8
- this . inputString = inputString ;
9
- this . config = DeepCopy ( CLASH_CONFIG ) ;
10
- }
7
+ constructor ( inputString ) {
8
+ this . inputString = inputString ;
9
+ this . config = DeepCopy ( CLASH_CONFIG ) ;
10
+ }
11
11
12
- async build ( ) {
13
- const customProxies = await this . parseCustomProxies ( ) ;
14
- this . addCustomProxies ( customProxies ) ;
15
- return yaml . dump ( this . config ) ;
16
- }
12
+ async build ( ) {
13
+ const customProxies = await this . parseCustomProxies ( ) ;
14
+ this . addCustomProxies ( customProxies ) ;
15
+ return yaml . dump ( this . config ) ;
16
+ }
17
17
18
- async parseCustomProxies ( ) {
19
- const urls = this . inputString . split ( '\n' ) . filter ( url => url . trim ( ) !== '' ) ;
20
- return Promise . all ( urls . map ( url => ProxyParser . parse ( url ) ) ) ;
21
- }
18
+ async parseCustomProxies ( ) {
19
+ const urls = this . inputString . split ( '\n' ) . filter ( url => url . trim ( ) !== '' ) ;
20
+ const parsedProxies = [ ] ;
21
+
22
+ for ( const url of urls ) {
23
+ const result = await ProxyParser . parse ( url ) ;
24
+ if ( Array . isArray ( result ) ) {
25
+ // If the result is an array, it's from an HTTP(S) source
26
+ for ( const subUrl of result ) {
27
+ const subResult = await ProxyParser . parse ( subUrl ) ;
28
+ if ( subResult ) {
29
+ parsedProxies . push ( subResult ) ;
30
+ }
31
+ }
32
+ } else if ( result ) {
33
+ parsedProxies . push ( result ) ;
34
+ }
35
+ }
36
+
37
+ return parsedProxies ;
38
+ }
22
39
23
40
addCustomProxies ( customProxies ) {
24
41
customProxies . forEach ( proxy => {
@@ -27,6 +44,7 @@ export class ClashConfigBuilder {
27
44
}
28
45
} ) ;
29
46
const proxyList = customProxies . filter ( proxy => proxy ?. tag !== undefined ) . map ( proxy => proxy ?. tag ) ;
47
+ proxyList . push ( 'DIRECT' , 'REJECT' ) ;
30
48
SELECTORS_LIST . forEach ( selector => {
31
49
if ( ! this . config [ 'proxy-groups' ] . some ( g => g . name === selector ) ) {
32
50
this . config [ 'proxy-groups' ] . push ( {
@@ -38,76 +56,102 @@ export class ClashConfigBuilder {
38
56
} ) ;
39
57
}
40
58
41
- convertToClashProxy ( proxy ) {
42
- // Convert sing-box proxy format to Clash format
43
- switch ( proxy . type ) {
44
- case 'shadowsocks' :
45
- return {
46
- name : proxy . tag ,
47
- type : 'ss' ,
48
- server : proxy . server ,
49
- port : proxy . server_port ,
50
- cipher : proxy . method ,
51
- password : proxy . password
52
- } ;
53
- case 'vmess' :
54
- return {
55
- name : proxy . tag ,
56
- type : proxy . type ,
57
- server : proxy . server ,
58
- port : proxy . server_port ,
59
- uuid : proxy . uuid ,
60
- alterId : proxy . alter_id ,
61
- cipher : proxy . security ,
62
- tls : proxy . tls ?. enabled || false ,
63
- servername : proxy . tls ?. server_name || '' ,
64
- network : proxy . transport ?. type || 'tcp' ,
65
- 'ws-opts' : proxy . transport ?. type === 'ws' ? {
66
- path : proxy . transport . path ,
67
- headers : proxy . transport . headers
68
- } : undefined
69
- } ;
70
- case 'vless' :
71
- return {
72
- name : proxy . tag ,
73
- type : proxy . type ,
74
- server : proxy . server ,
75
- port : proxy . server_port ,
76
- uuid : proxy . uuid ,
77
- cipher : proxy . security ,
78
- tls : proxy . tls ?. enabled || false ,
79
- 'client-fingerprint' :proxy . tls . utls ?. fingerprint ,
80
- servername : proxy . tls ?. server_name || '' ,
81
- network : proxy . transport ?. type || 'tcp' ,
82
- 'ws-opts' : proxy . transport ?. type === 'ws' ? {
83
- path : proxy . transport . path ,
84
- headers : proxy . transport . headers
85
- } : undefined ,
86
- 'reality-opts' : proxy . tls . reality ?. enabled ? {
87
- 'public-key' : proxy . tls . reality . public_key ,
88
- 'short-id' : proxy . tls . reality . short_id ,
89
- } : undefined ,
59
+ convertToClashProxy ( proxy ) {
60
+ switch ( proxy . type ) {
61
+ case 'shadowsocks' :
62
+ return {
63
+ name : proxy . tag ,
64
+ type : 'ss' ,
65
+ server : proxy . server ,
66
+ port : proxy . server_port ,
67
+ cipher : proxy . method ,
68
+ password : proxy . password
69
+ } ;
70
+ case 'vmess' :
71
+ return {
72
+ name : proxy . tag ,
73
+ type : proxy . type ,
74
+ server : proxy . server ,
75
+ port : proxy . server_port ,
76
+ uuid : proxy . uuid ,
77
+ alterId : proxy . alter_id ,
78
+ cipher : proxy . security ,
79
+ tls : proxy . tls ?. enabled || false ,
80
+ servername : proxy . tls ?. server_name || '' ,
81
+ network : proxy . transport ?. type || 'tcp' ,
82
+ 'ws-opts' : proxy . transport ?. type === 'ws' ? {
83
+ path : proxy . transport . path ,
84
+ headers : proxy . transport . headers
85
+ } : undefined
86
+ } ;
87
+ case 'vless' :
88
+ return {
89
+ name : proxy . tag ,
90
+ type : proxy . type ,
91
+ server : proxy . server ,
92
+ port : proxy . server_port ,
93
+ uuid : proxy . uuid ,
94
+ cipher : proxy . security ,
95
+ tls : proxy . tls ?. enabled || false ,
96
+ 'client-fingerprint' : proxy . tls . utls ?. fingerprint ,
97
+ servername : proxy . tls ?. server_name || '' ,
98
+ network : proxy . transport ?. type || 'tcp' ,
99
+ 'ws-opts' : proxy . transport ?. type === 'ws' ? {
100
+ path : proxy . transport . path ,
101
+ headers : proxy . transport . headers
102
+ } : undefined ,
103
+ 'reality-opts' : proxy . tls . reality ?. enabled ? {
104
+ 'public-key' : proxy . tls . reality . public_key ,
105
+ 'short-id' : proxy . tls . reality . short_id ,
106
+ } : undefined ,
90
107
'grpc-opts' : proxy . transport ?. type === 'grpc' ? {
91
108
'grpc-mode' : 'gun' ,
92
109
'grpc-service-name' : proxy . transport . service_name ,
93
110
} : undefined ,
94
111
tfo : proxy . tcp_fast_open ,
95
112
'skip-cert-verify' : proxy . tls . insecure ,
96
113
'flow' : proxy . flow ?? undefined ,
97
- } ;
98
- case 'hysteria2' :
114
+ } ;
115
+ case 'hysteria2' :
116
+ return {
117
+ name : proxy . tag ,
118
+ type : proxy . type ,
119
+ server : proxy . server ,
120
+ port : proxy . server_port ,
121
+ password : proxy . password ,
122
+ auth : proxy . password ,
123
+ 'skip-cert-verify' : proxy . tls . insecure ,
124
+ } ;
125
+ case 'trojan' :
99
126
return {
100
- name : proxy . tag ,
101
- type : proxy . type ,
102
- server : proxy . server ,
103
- port : proxy . server_port ,
104
- password : proxy . password ,
105
- auth : proxy . password ,
106
- 'skip-cert-verify' : proxy . tls . insecure ,
107
- } ;
108
-
109
- default :
110
- return proxy ; // Return as-is if no specific conversion is defined
111
- }
112
- }
113
- }
127
+ name : proxy . tag ,
128
+ type : proxy . type ,
129
+ server : proxy . server ,
130
+ port : proxy . server_port ,
131
+ password : proxy . password ,
132
+ cipher : proxy . security ,
133
+ tls : proxy . tls ?. enabled || false ,
134
+ 'client-fingerprint' : proxy . tls . utls ?. fingerprint ,
135
+ servername : proxy . tls ?. server_name || '' ,
136
+ network : proxy . transport ?. type || 'tcp' ,
137
+ 'ws-opts' : proxy . transport ?. type === 'ws' ? {
138
+ path : proxy . transport . path ,
139
+ headers : proxy . transport . headers
140
+ } : undefined ,
141
+ 'reality-opts' : proxy . tls . reality ?. enabled ? {
142
+ 'public-key' : proxy . tls . reality . public_key ,
143
+ 'short-id' : proxy . tls . reality . short_id ,
144
+ } : undefined ,
145
+ 'grpc-opts' : proxy . transport ?. type === 'grpc' ? {
146
+ 'grpc-mode' : 'gun' ,
147
+ 'grpc-service-name' : proxy . transport . service_name ,
148
+ } : undefined ,
149
+ tfo : proxy . tcp_fast_open ,
150
+ 'skip-cert-verify' : proxy . tls . insecure ,
151
+ 'flow' : proxy . flow ?? undefined ,
152
+ }
153
+ default :
154
+ return proxy ; // Return as-is if no specific conversion is defined
155
+ }
156
+ }
157
+ }
0 commit comments