whoisthere/
lib.rs

1use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc};
2use regex::Regex;
3
4pub struct DomainProps {
5    pub domain_name: String,
6    pub expiration_date: String,
7    pub is_registered: bool,
8    pub is_under_grace_period: bool,
9}
10
11pub fn parse_info(domain_name: &str, whois_info: &str) -> DomainProps {
12    let mut whois_data = DomainProps {
13        domain_name: String::from(domain_name),
14        expiration_date: String::new(),
15        is_registered: false,
16        is_under_grace_period: false,
17    };
18
19    let lines = whois_info.lines();
20    for line in lines {
21        let line_trimmed = line.trim();
22
23        // Determine if domain is registered
24        if line_trimmed.starts_with("Domain not found.")
25            || line_trimmed.starts_with("Domain not registered.")
26            || line_trimmed.starts_with("No match for")
27            || line_trimmed.starts_with("% No entries found for query")
28        {
29            break;
30        }
31
32        // Parse expiration date
33        if line_trimmed.starts_with("Registry Expiry Date:") {
34            let re = Regex::new(r"Registry Expiry Date:\s+(.*)").unwrap();
35            for caps in re.captures_iter(line_trimmed) {
36                let result = caps.get(1).unwrap().as_str();
37                let datetime_utc = result.parse::<DateTime<Utc>>().unwrap();
38                whois_data.is_registered = true;
39                whois_data.expiration_date = format!("{:?}", datetime_utc);
40            }
41            continue;
42        } else if line_trimmed.starts_with("Expiry date:") {
43            let re = Regex::new(r"Expiry date:\s+(.*)").unwrap();
44            for caps in re.captures_iter(line_trimmed) {
45                let naive_date =
46                    NaiveDate::parse_from_str(caps.get(1).unwrap().as_str(), "%d-%B-%Y").unwrap();
47                let naive_datetime: NaiveDateTime = naive_date.and_hms(0, 0, 0);
48                let datetime_utc = DateTime::<Utc>::from_utc(naive_datetime, Utc);
49                whois_data.is_registered = true;
50                whois_data.expiration_date = format!("{:?}", datetime_utc);
51            }
52            continue;
53        } else if line_trimmed.starts_with("expires:") {
54            let re = Regex::new(r"expires:\s+(.*)").unwrap();
55            for caps in re.captures_iter(line_trimmed) {
56                let naive_date =
57                    NaiveDate::parse_from_str(caps.get(1).unwrap().as_str(), "%B %d %Y").unwrap();
58                let naive_datetime: NaiveDateTime = naive_date.and_hms(0, 0, 0);
59                let datetime_utc = DateTime::<Utc>::from_utc(naive_datetime, Utc);
60                whois_data.is_registered = true;
61                whois_data.expiration_date = format!("{:?}", datetime_utc);
62            }
63            continue;
64        } else if line_trimmed.starts_with("Expiration date:") {
65            let re = Regex::new(r"Expiration date:\s+(.*)").unwrap();
66            for caps in re.captures_iter(line_trimmed) {
67                let naive_datetime = NaiveDateTime::parse_from_str(
68                    caps.get(1).unwrap().as_str(),
69                    "%d.%m.%Y %H:%M:%S",
70                )
71                .unwrap();
72                let datetime_utc = DateTime::<Utc>::from_utc(naive_datetime, Utc);
73                whois_data.is_registered = true;
74                whois_data.expiration_date = format!("{:?}", datetime_utc);
75            }
76            continue;
77        }
78
79        // Parse status
80        if line_trimmed.starts_with("Domain Status:") {
81            let re = Regex::new(r"Domain Status:\s+(.*)").unwrap();
82            for caps in re.captures_iter(line_trimmed) {
83                let result = caps.get(1).unwrap().as_str();
84                if result == "redemptionPeriod https://icann.org/epp#redemptionPeriod" {
85                    whois_data.is_under_grace_period = true;
86                }
87            }
88            continue;
89        }
90    }
91
92    // TODO: parse more outputs (e.g. registrar)
93    // TODO: throw errors instead of simply returning a struct
94
95    return whois_data;
96}