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 {
9 let link = link.trim();
11
12 if link.is_empty() {
14 return false;
15 }
16
17 if link.starts_with("vmess://") {
19 if super::vmess::explode_std_vmess_new(link, node) {
21 return true;
22 }
23
24 if super::vmess::explode_vmess(link, node) {
26 return true;
27 }
28
29 if super::vmess::explode_std_vmess(link, node) {
31 return true;
32 }
33
34 if super::vmess::explode_shadowrocket(link, node) {
35 return true;
36 }
37
38 if super::vmess::explode_kitsunebi(link, node) {
39 return true;
40 }
41
42 log::warn!("Failed to explode link: {}", link);
43
44 return false;
45 } else if link.starts_with("ss://") {
46 super::ss::explode_ss(link, node)
47 } else if link.starts_with("ssr://") {
48 false
50 } else if link.starts_with("socks://")
51 || link.starts_with("https://t.me/socks")
52 || link.starts_with("tg://socks")
53 {
54 super::socks::explode_socks(link, node)
55 } else if link.starts_with("http://") || link.starts_with("https://") {
56 if super::http::explode_http(link, node) {
58 return true;
59 }
60
61 super::httpsub::explode_http_sub(link, node)
63 } else if link.starts_with("trojan://") {
64 super::trojan::explode_trojan(link, node)
65 } else if link.starts_with("snell://") {
66 super::snell::explode_snell(link, node)
67 } else if link.starts_with("wg://") || link.starts_with("wireguard://") {
68 super::wireguard::explode_wireguard(link, node)
69 } else if link.starts_with("hysteria://") {
70 super::hysteria::explode_hysteria(link, node)
71 } else if link.starts_with("hysteria2://") || link.starts_with("hy2://") {
72 super::hysteria2::explode_hysteria2(link, node)
73 } else if link.starts_with("vmess+") {
74 false
75 } else if link.starts_with("vless://") {
77 super::vless::explode_vless(link, node)
78 } else {
79 false
80 }
81}
82
83pub fn explode_sub(sub: &str, nodes: &mut Vec<Proxy>) -> bool {
88 let sub = sub.trim();
90
91 if sub.is_empty() {
93 return false;
94 }
95
96 let mut processed = false;
97
98 if sub.starts_with("ssd://") {
100 if super::ss::explode_ssd(sub, nodes) {
101 processed = true;
102 }
103 }
104
105 if !processed
107 && (sub.contains("\"Proxy\":")
108 || sub.contains("\"proxies\":")
109 || sub.contains("Proxy:")
110 || sub.contains("proxies:"))
111 {
112 if super::explode_clash::explode_clash(sub, nodes) {
113 processed = true;
114 }
115 }
116
117 if !processed && super::surge::explode_surge(sub, nodes) {
119 processed = true;
120 }
121
122 if !processed {
124 let decoded = url_safe_base64_decode(sub);
126
127 if decoded.contains("vmess=")
129 || decoded.contains("shadowsocks=")
130 || decoded.contains("http=")
131 || decoded.contains("trojan=")
132 {
133 if super::surge::explode_surge(&decoded, nodes) {
134 return true;
135 }
136 }
137
138 let delimiter = if decoded.contains('\n') {
140 '\n'
141 } else if decoded.contains('\r') {
142 '\r'
143 } else {
144 ' '
145 };
146
147 let lines: Vec<&str> = decoded.split(delimiter).collect();
148
149 log::info!("Found {} lines in explode_sub process", lines.len());
150
151 for line in lines {
152 let line = line.trim().trim_end_matches('\r');
153 if line.is_empty() {
154 continue;
155 }
156
157 let mut node = Proxy::default();
158 if explode(line, &mut node) {
159 nodes.push(node);
160 }
161 }
162 }
163
164 !nodes.is_empty()
165}
166
167pub fn explode_conf_content(content: &str, nodes: &mut Vec<Proxy>) -> i32 {
179 let content = content.trim();
181
182 if content.is_empty() {
184 return 0;
185 }
186
187 let orig_size = nodes.len();
188 let mut parsed = false;
189
190 if content.starts_with('{') {
192 if super::vmess::explode_vmess_conf(content, nodes) {
194 parsed = true;
195 }
196 else if content.contains("\"server\"") && content.contains("\"port\"") {
198 if super::netch::explode_netch_conf(content, nodes) {
199 parsed = true;
200 }
201 }
202 }
203 else if content.contains("proxies:") || content.contains("Proxy:") {
205 if super::explode_clash::explode_clash(content, nodes) {
206 parsed = true;
207 }
208 }
209 else if content.starts_with("ssd://") {
211 if super::ss::explode_ssd(content, nodes) {
212 parsed = true;
213 }
214 }
215 else if content.contains("\"servers\":") || content.contains("\"configs\":") {
217 if super::sstap::explode_sstap(content, nodes) {
218 parsed = true;
219 }
220 }
221 else if content.contains("[Proxy]") {
223 if super::surge::explode_surge(content, nodes) {
224 parsed = true;
225 }
226 }
227 else if content.contains(" = vmess")
229 || content.contains(" = shadowsocks")
230 || content.contains(" = shadowsocksr")
231 || content.contains(" = http")
232 || content.contains(" = trojan")
233 {
234 if super::quan::explode_quan(content, nodes) {
235 parsed = true;
236 }
237 }
238
239 if !parsed && explode_sub(content, nodes) {
241 parsed = true;
242 }
243
244 if parsed {
245 (nodes.len() - orig_size) as i32
246 } else {
247 0
248 }
249}