libsubconverter/parser/explodes/
common.rs1use crate::utils::base64::url_safe_base64_decode;
2use crate::Proxy;
3
4pub fn explode(link: &str, node: &mut Proxy) -> bool {
8 let link = link.trim();
10
11 if link.is_empty() {
13 return false;
14 }
15
16 if link.starts_with("vmess://") {
18 if super::vmess::explode_vmess(link, node) {
20 return true;
21 }
22
23 if super::vmess::explode_std_vmess(link, node) {
25 return true;
26 }
27
28 if super::vmess::explode_shadowrocket(link, node) {
29 return true;
30 }
31
32 if super::vmess::explode_kitsunebi(link, node) {
33 return true;
34 }
35
36 return false;
37 } else if link.starts_with("ss://") {
38 super::ss::explode_ss(link, node)
39 } else if link.starts_with("ssr://") {
40 false
42 } else if link.starts_with("socks://")
43 || link.starts_with("https://t.me/socks")
44 || link.starts_with("tg://socks")
45 {
46 super::socks::explode_socks(link, node)
47 } else if link.starts_with("http://") || link.starts_with("https://") {
48 if super::http::explode_http(link, node) {
50 return true;
51 }
52
53 super::httpsub::explode_http_sub(link, node)
55 } else if link.starts_with("trojan://") {
56 super::trojan::explode_trojan(link, node)
57 } else if link.starts_with("snell://") {
58 super::snell::explode_snell(link, node)
59 } else if link.starts_with("wg://") || link.starts_with("wireguard://") {
60 super::wireguard::explode_wireguard(link, node)
61 } else if link.starts_with("hysteria://") {
62 super::hysteria::explode_hysteria(link, node)
63 } else if link.starts_with("hysteria2://") || link.starts_with("hy2://") {
64 super::hysteria2::explode_hysteria2(link, node)
65 } else if link.starts_with("vmess+") {
66 false
67 } else if link.starts_with("vless://") {
69 super::vless::explode_vless(link, node)
70 } else {
71 false
72 }
73}
74
75pub fn explode_sub(sub: &str, nodes: &mut Vec<Proxy>) -> bool {
80 let sub = sub.trim();
82
83 if sub.is_empty() {
85 return false;
86 }
87
88 let mut processed = false;
89
90 if sub.starts_with("ssd://") {
92 if super::ss::explode_ssd(sub, nodes) {
93 processed = true;
94 }
95 }
96
97 if !processed
99 && (sub.contains("\"Proxy\":")
100 || sub.contains("\"proxies\":")
101 || sub.contains("Proxy:")
102 || sub.contains("proxies:"))
103 {
104 if super::explode_clash::explode_clash(sub, nodes) {
105 processed = true;
106 }
107 }
108
109 if !processed && super::surge::explode_surge(sub, nodes) {
111 processed = true;
112 }
113
114 if !processed {
116 let decoded = url_safe_base64_decode(sub);
118
119 if decoded.contains("vmess=")
121 || decoded.contains("shadowsocks=")
122 || decoded.contains("http=")
123 || decoded.contains("trojan=")
124 {
125 if super::surge::explode_surge(&decoded, nodes) {
126 return true;
127 }
128 }
129
130 let delimiter = if decoded.contains('\n') {
132 '\n'
133 } else if decoded.contains('\r') {
134 '\r'
135 } else {
136 ' '
137 };
138
139 let lines: Vec<&str> = decoded.split(delimiter).collect();
140
141 for line in lines {
142 let line = line.trim().trim_end_matches('\r');
143 if line.is_empty() {
144 continue;
145 }
146
147 let mut node = Proxy::default();
148 if explode(line, &mut node) {
149 nodes.push(node);
150 }
151 }
152 }
153
154 !nodes.is_empty()
155}
156
157pub fn explode_conf_content(content: &str, nodes: &mut Vec<Proxy>) -> i32 {
169 let content = content.trim();
171
172 if content.is_empty() {
174 return 0;
175 }
176
177 let orig_size = nodes.len();
178 let mut parsed = false;
179
180 if content.starts_with('{') {
182 if super::vmess::explode_vmess_conf(content, nodes) {
184 parsed = true;
185 }
186 else if content.contains("\"server\"") && content.contains("\"port\"") {
188 if super::netch::explode_netch_conf(content, nodes) {
189 parsed = true;
190 }
191 }
192 }
193 else if content.contains("proxies:") || content.contains("Proxy:") {
195 if super::explode_clash::explode_clash(content, nodes) {
196 parsed = true;
197 }
198 }
199 else if content.starts_with("ssd://") {
201 if super::ss::explode_ssd(content, nodes) {
202 parsed = true;
203 }
204 }
205 else if content.contains("\"servers\":") || content.contains("\"configs\":") {
207 if super::sstap::explode_sstap(content, nodes) {
208 parsed = true;
209 }
210 }
211 else if content.contains("[Proxy]") {
213 if super::surge::explode_surge(content, nodes) {
214 parsed = true;
215 }
216 }
217 else if content.contains(" = vmess")
219 || content.contains(" = shadowsocks")
220 || content.contains(" = shadowsocksr")
221 || content.contains(" = http")
222 || content.contains(" = trojan")
223 {
224 if super::quan::explode_quan(content, nodes) {
225 parsed = true;
226 }
227 }
228
229 if !parsed && explode_sub(content, nodes) {
231 parsed = true;
232 }
233
234 if parsed {
235 (nodes.len() - orig_size) as i32
236 } else {
237 0
238 }
239}