proxy_scraper/
tuic.rs

1use regex::Regex;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5/// Represents a TUIC proxy.
6#[derive(Debug, Serialize, Deserialize)]
7pub struct TUIC {
8    /// The host address of the TUIC proxy.
9    pub host: String,
10    /// The port number for the TUIC proxy.
11    pub port: u32,
12    /// The authentication string associated with the TUIC proxy.
13    pub auth: String,
14    /// Additional parameters associated with the TUIC proxy.
15    #[serde(flatten)]
16    pub parameters: Option<HashMap<String, String>>,
17}
18
19impl TUIC {
20    /// Converts the TUIC proxy information into a TUIC URL.
21    ///
22    /// # Example
23    ///
24    /// ```
25    /// use proxy_scraper::tuic::TUIC;
26    /// use std::collections::HashMap;
27    /// let proxy = TUIC {
28    ///     host: "example.com".to_string(),
29    ///     port: 443,
30    ///     auth: "auth123".to_string(),
31    ///     parameters: Some(HashMap::new()), // Insert additional parameters here
32    /// };
33    /// let url = proxy.to_url();
34    /// assert_eq!(url, "tuic://auth123@example.com:443?");
35    /// ```
36    pub fn to_url(&self) -> String {
37        let url_encoded_parameters = serde_urlencoded::to_string(&self.parameters).unwrap();
38        format!(
39            "tuic://{}@{}:{}?{}",
40            self.auth, self.host, self.port, url_encoded_parameters
41        )
42    }
43
44    /// Scrapes TUIC proxy information from the provided source string and returns a vector of TUIC instances.
45    ///
46    /// # Arguments
47    ///
48    /// * `source` - A string containing the source code or text from which to extract TUIC proxy information.
49    ///
50    /// # Returns
51    ///
52    /// A vector of `TUIC` instances parsed from the source string.
53    pub fn scrape(source: &str) -> Vec<Self> {
54        let source = crate::utils::seperate_links(source);
55        let mut proxy_list: Vec<TUIC> = Vec::new();
56        let regex = Regex::new(r#"tuic://([A-Za-z0-9\-._~]+)@((.+):(\d+))\?(.+)#"#).unwrap();
57
58        for captures in regex.captures_iter(&source) {
59            let auth = captures.get(1).map(|auth| auth.as_str()).unwrap_or("");
60            let host = captures.get(3).map(|host| host.as_str()).unwrap_or("");
61            let port = captures.get(4).map(|port| port.as_str()).unwrap_or("");
62            let url_parameters = captures.get(5).map(|params| params.as_str()).unwrap_or("");
63
64            if auth.is_empty() || host.is_empty() || port.is_empty() || url_parameters.is_empty() {
65                continue;
66            }
67
68            let parameters: HashMap<String, String> =
69                serde_urlencoded::from_str(&url_parameters).unwrap();
70
71            let tuic_proxy = TUIC {
72                host: host.to_string(),
73                port: port.parse::<u32>().unwrap_or(0),
74                auth: auth.to_string(),
75                parameters: Some(parameters),
76            };
77
78            proxy_list.push(tuic_proxy);
79        }
80
81        proxy_list
82    }
83}