proxy_scraper/
hysteria.rs1use regex::Regex;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(Debug, Serialize, Deserialize)]
7pub struct Hysteria {
8 pub version: u8,
10 pub host: String,
12 pub port: u32,
14 pub auth: String,
16 #[serde(flatten)]
18 pub parameters: Option<HashMap<String, String>>,
19}
20
21impl Hysteria {
22 pub fn to_url(&self) -> String {
40 let url_encoded_parameters = serde_urlencoded::to_string(&self.parameters).unwrap();
41 let hysteria_version = match self.version {
42 1 => "hysteria",
43 _ => "hy2",
44 };
45
46 format!(
47 "{}://{}@{}:{}?{}",
48 hysteria_version, self.auth, self.host, self.port, url_encoded_parameters
49 )
50 }
51
52 pub fn scrape(source: &str) -> Vec<Self> {
62 let source = crate::utils::seperate_links(source);
63 let mut proxy_list: Vec<Hysteria> = Vec::new();
64 let regex =
65 Regex::new(r#"(hy2|hysteria2|hysteria)://([A-Za-z0-9\-._~]+)@((.+):(\d+))\?(.+)#"#)
66 .unwrap();
67
68 for captures in regex.captures_iter(&source) {
69 let version = captures.get(1).map(|ver| ver.as_str()).unwrap_or("");
70 let auth = captures.get(2).map(|auth| auth.as_str()).unwrap_or("");
71 let host = captures.get(4).map(|host| host.as_str()).unwrap_or("");
72 let port = captures.get(5).map(|port| port.as_str()).unwrap_or("");
73 let url_parameters = captures.get(6).map(|params| params.as_str()).unwrap_or("");
74
75 if version.is_empty()
76 || auth.is_empty()
77 || host.is_empty()
78 || port.is_empty()
79 || url_parameters.is_empty()
80 {
81 continue;
82 }
83
84 let parameters: HashMap<String, String> =
85 serde_urlencoded::from_str(&url_parameters).unwrap();
86
87 let hysteria_version = match version {
88 "hy2" | "hysteria2" => 2,
89 _ => 1,
90 };
91
92 let hysteria_proxy = Hysteria {
93 version: hysteria_version,
94 host: host.to_string(),
95 port: port.parse::<u32>().unwrap_or(0),
96 auth: auth.to_string(),
97 parameters: Some(parameters),
98 };
99
100 proxy_list.push(hysteria_proxy);
101 }
102
103 proxy_list
104 }
105}