1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc};
use regex::Regex;

pub struct DomainProps {
    pub domain_name: String,
    pub expiration_date: String,
    pub is_registered: bool,
    pub is_under_grace_period: bool,
}

pub fn parse_info(domain_name: &str, whois_info: &str) -> DomainProps {
    let mut whois_data = DomainProps {
        domain_name: String::from(domain_name),
        expiration_date: String::new(),
        is_registered: false,
        is_under_grace_period: false,
    };

    let lines = whois_info.lines();
    for line in lines {
        let line_trimmed = line.trim();

        // Determine if domain is registered
        if line_trimmed.starts_with("Domain not found.")
            || line_trimmed.starts_with("Domain not registered.")
            || line_trimmed.starts_with("No match for")
            || line_trimmed.starts_with("% No entries found for query")
        {
            break;
        }

        // Parse expiration date
        if line_trimmed.starts_with("Registry Expiry Date:") {
            let re = Regex::new(r"Registry Expiry Date:\s+(.*)").unwrap();
            for caps in re.captures_iter(line_trimmed) {
                let result = caps.get(1).unwrap().as_str();
                let datetime_utc = result.parse::<DateTime<Utc>>().unwrap();
                whois_data.is_registered = true;
                whois_data.expiration_date = format!("{:?}", datetime_utc);
            }
            continue;
        } else if line_trimmed.starts_with("Expiry date:") {
            let re = Regex::new(r"Expiry date:\s+(.*)").unwrap();
            for caps in re.captures_iter(line_trimmed) {
                let naive_date =
                    NaiveDate::parse_from_str(caps.get(1).unwrap().as_str(), "%d-%B-%Y").unwrap();
                let naive_datetime: NaiveDateTime = naive_date.and_hms(0, 0, 0);
                let datetime_utc = DateTime::<Utc>::from_utc(naive_datetime, Utc);
                whois_data.is_registered = true;
                whois_data.expiration_date = format!("{:?}", datetime_utc);
            }
            continue;
        } else if line_trimmed.starts_with("expires:") {
            let re = Regex::new(r"expires:\s+(.*)").unwrap();
            for caps in re.captures_iter(line_trimmed) {
                let naive_date =
                    NaiveDate::parse_from_str(caps.get(1).unwrap().as_str(), "%B %d %Y").unwrap();
                let naive_datetime: NaiveDateTime = naive_date.and_hms(0, 0, 0);
                let datetime_utc = DateTime::<Utc>::from_utc(naive_datetime, Utc);
                whois_data.is_registered = true;
                whois_data.expiration_date = format!("{:?}", datetime_utc);
            }
            continue;
        } else if line_trimmed.starts_with("Expiration date:") {
            let re = Regex::new(r"Expiration date:\s+(.*)").unwrap();
            for caps in re.captures_iter(line_trimmed) {
                let naive_datetime = NaiveDateTime::parse_from_str(
                    caps.get(1).unwrap().as_str(),
                    "%d.%m.%Y %H:%M:%S",
                )
                .unwrap();
                let datetime_utc = DateTime::<Utc>::from_utc(naive_datetime, Utc);
                whois_data.is_registered = true;
                whois_data.expiration_date = format!("{:?}", datetime_utc);
            }
            continue;
        }

        // Parse status
        if line_trimmed.starts_with("Domain Status:") {
            let re = Regex::new(r"Domain Status:\s+(.*)").unwrap();
            for caps in re.captures_iter(line_trimmed) {
                let result = caps.get(1).unwrap().as_str();
                if result == "redemptionPeriod https://icann.org/epp#redemptionPeriod" {
                    whois_data.is_under_grace_period = true;
                }
            }
            continue;
        }
    }

    // TODO: parse more outputs (e.g. registrar)
    // TODO: throw errors instead of simply returning a struct

    return whois_data;
}