libsubconverter/parser/explodes/
socks.rs1use crate::models::{Proxy, SOCKS_DEFAULT_GROUP};
2use crate::utils::base64::url_safe_base64_decode;
3use std::collections::HashMap;
4use url::Url;
5
6pub fn explode_socks(link: &str, node: &mut Proxy) -> bool {
8 if link.starts_with("socks://") {
10 return parse_v2rayn_socks(link, node);
11 }
12 else if link.starts_with("https://t.me/socks") || link.starts_with("tg://socks") {
14 return parse_telegram_socks(link, node);
15 }
16
17 false
18}
19
20fn parse_v2rayn_socks(link: &str, node: &mut Proxy) -> bool {
23 let mut remarks = String::new();
25 let mut trimmed_link = link.to_string();
26 if let Some(pos) = link.find('#') {
27 remarks = link[pos + 1..].to_string();
28 trimmed_link = link[..pos].to_string();
29 }
30
31 let decoded = url_safe_base64_decode(&trimmed_link[8..]);
33 if decoded.is_empty() {
34 return false;
35 }
36
37 let mut username = String::new();
39 let mut password = String::new();
40 let mut _server = String::new();
41 let mut _port = 0;
42
43 if decoded.contains('@') {
44 let parts: Vec<&str> = decoded.split('@').collect();
45 if parts.len() < 2 {
46 return false;
47 }
48
49 let userinfo: Vec<&str> = parts[0].split(':').collect();
51 if userinfo.len() < 2 {
52 return false;
53 }
54 username = userinfo[0].to_string();
55 password = userinfo[1].to_string();
56
57 let server_port: Vec<&str> = parts[1].split(':').collect();
59 if server_port.len() < 2 {
60 return false;
61 }
62 _server = server_port[0].to_string();
63 _port = match server_port[1].parse::<u16>() {
64 Ok(p) => p,
65 Err(_) => return false,
66 };
67 } else {
68 let server_port: Vec<&str> = decoded.split(':').collect();
70 if server_port.len() < 2 {
71 return false;
72 }
73 _server = server_port[0].to_string();
74 _port = match server_port[1].parse::<u16>() {
75 Ok(p) => p,
76 Err(_) => return false,
77 };
78 }
79
80 if _port == 0 {
81 return false;
82 }
83
84 if remarks.is_empty() {
86 remarks = format!("{} ({})", _server, _port);
87 }
88
89 *node = Proxy::socks_construct(
91 SOCKS_DEFAULT_GROUP,
92 &remarks,
93 &_server,
94 _port,
95 &username,
96 &password,
97 None,
98 None,
99 None,
100 "",
101 );
102
103 true
104}
105
106fn parse_telegram_socks(link: &str, node: &mut Proxy) -> bool {
110 let url = match Url::parse(link) {
112 Ok(url) => url,
113 Err(_) => return false,
114 };
115
116 let query_pairs: HashMap<String, String> = url
118 .query_pairs()
119 .map(|(k, v)| (k.to_string(), v.to_string()))
120 .collect();
121
122 let server = match query_pairs.get("server") {
124 Some(s) => s,
125 None => return false,
126 };
127
128 let port_str = match query_pairs.get("port") {
129 Some(p) => p,
130 None => return false,
131 };
132
133 let port = match port_str.parse::<u16>() {
134 Ok(p) => p,
135 Err(_) => return false,
136 };
137
138 if port == 0 {
139 return false;
140 }
141
142 let username = query_pairs.get("user").map_or("", |s| s);
144 let password = query_pairs.get("pass").map_or("", |s| s);
145
146 let group = query_pairs.get("group").map_or(SOCKS_DEFAULT_GROUP, |s| s);
147
148 let remarks = if let Some(r) = query_pairs.get("remarks") {
149 if !r.is_empty() {
150 r.as_str()
151 } else {
152 &format!("{} ({})", server, port)
153 }
154 } else {
155 &format!("{} ({})", server, port)
156 };
157
158 *node = Proxy::socks_construct(
160 group, remarks, server, port, username, password, None, None, None, "",
161 );
162
163 true
164}