use crate::utils::base64::url_safe_base64_decode;
use crate::Proxy;
pub fn explode(link: &str, node: &mut Proxy) -> bool {
let link = link.trim();
if link.is_empty() {
return false;
}
if link.starts_with("vmess://") {
if super::vmess::explode_std_vmess_new(link, node) {
return true;
}
if super::vmess::explode_vmess(link, node) {
return true;
}
if super::vmess::explode_std_vmess(link, node) {
return true;
}
if super::vmess::explode_shadowrocket(link, node) {
return true;
}
if super::vmess::explode_kitsunebi(link, node) {
return true;
}
log::warn!("Failed to explode link: {}", link);
return false;
} else if link.starts_with("ss://") {
super::ss::explode_ss(link, node)
} else if link.starts_with("ssr://") {
false
} else if link.starts_with("socks://")
|| link.starts_with("https://t.me/socks")
|| link.starts_with("tg://socks")
{
super::socks::explode_socks(link, node)
} else if link.starts_with("http://") || link.starts_with("https://") {
if super::http::explode_http(link, node) {
return true;
}
super::httpsub::explode_http_sub(link, node)
} else if link.starts_with("trojan://") {
super::trojan::explode_trojan(link, node)
} else if link.starts_with("snell://") {
super::snell::explode_snell(link, node)
} else if link.starts_with("wg://") || link.starts_with("wireguard://") {
super::wireguard::explode_wireguard(link, node)
} else if link.starts_with("hysteria://") {
super::hysteria::explode_hysteria(link, node)
} else if link.starts_with("hysteria2://") || link.starts_with("hy2://") {
super::hysteria2::explode_hysteria2(link, node)
} else if link.starts_with("vmess+") {
false
} else if link.starts_with("vless://") {
super::vless::explode_vless(link, node)
} else {
false
}
}
pub fn explode_sub(sub: &str, nodes: &mut Vec<Proxy>) -> bool {
let sub = sub.trim();
if sub.is_empty() {
return false;
}
let mut processed = false;
if sub.starts_with("ssd://") {
if super::ss::explode_ssd(sub, nodes) {
processed = true;
}
}
if !processed
&& (sub.contains("\"Proxy\":")
|| sub.contains("\"proxies\":")
|| sub.contains("Proxy:")
|| sub.contains("proxies:"))
{
if super::explode_clash::explode_clash(sub, nodes) {
processed = true;
}
}
if !processed && super::surge::explode_surge(sub, nodes) {
processed = true;
}
if !processed {
let decoded = url_safe_base64_decode(sub);
if decoded.contains("vmess=")
|| decoded.contains("shadowsocks=")
|| decoded.contains("http=")
|| decoded.contains("trojan=")
{
if super::surge::explode_surge(&decoded, nodes) {
return true;
}
}
let delimiter = if decoded.contains('\n') {
'\n'
} else if decoded.contains('\r') {
'\r'
} else {
' '
};
let lines: Vec<&str> = decoded.split(delimiter).collect();
log::info!("Found {} lines in explode_sub process", lines.len());
for line in lines {
let line = line.trim().trim_end_matches('\r');
if line.is_empty() {
continue;
}
let mut node = Proxy::default();
if explode(line, &mut node) {
nodes.push(node);
}
}
}
!nodes.is_empty()
}
pub fn explode_conf_content(content: &str, nodes: &mut Vec<Proxy>) -> i32 {
let content = content.trim();
if content.is_empty() {
return 0;
}
let orig_size = nodes.len();
let mut parsed = false;
if content.starts_with('{') {
if super::vmess::explode_vmess_conf(content, nodes) {
parsed = true;
}
else if content.contains("\"server\"") && content.contains("\"port\"") {
if super::netch::explode_netch_conf(content, nodes) {
parsed = true;
}
}
}
else if content.contains("proxies:") || content.contains("Proxy:") {
if super::explode_clash::explode_clash(content, nodes) {
parsed = true;
}
}
else if content.starts_with("ssd://") {
if super::ss::explode_ssd(content, nodes) {
parsed = true;
}
}
else if content.contains("\"servers\":") || content.contains("\"configs\":") {
if super::sstap::explode_sstap(content, nodes) {
parsed = true;
}
}
else if content.contains("[Proxy]") {
if super::surge::explode_surge(content, nodes) {
parsed = true;
}
}
else if content.contains(" = vmess")
|| content.contains(" = shadowsocks")
|| content.contains(" = shadowsocksr")
|| content.contains(" = http")
|| content.contains(" = trojan")
{
if super::quan::explode_quan(content, nodes) {
parsed = true;
}
}
if !parsed && explode_sub(content, nodes) {
parsed = true;
}
if parsed {
(nodes.len() - orig_size) as i32
} else {
0
}
}