proxy_scraper/
trojan.rs

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