1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum SeerError {
5 #[error("WHOIS lookup failed: {0}")]
6 WhoisError(String),
7
8 #[error("WHOIS server not found for TLD: {0}")]
9 WhoisServerNotFound(String),
10
11 #[error("WHOIS connection failed: {0}")]
12 WhoisConnectionFailed(#[from] std::io::Error),
13
14 #[error("RDAP lookup failed: {0}")]
15 RdapError(String),
16
17 #[error("RDAP bootstrap failed: {0}")]
18 RdapBootstrapError(String),
19
20 #[error("DNS resolution failed: {0}")]
21 DnsError(String),
22
23 #[error("DNS resolver error: {0}")]
24 DnsResolverError(#[from] hickory_resolver::error::ResolveError),
25
26 #[error("Invalid domain name: {0}")]
27 InvalidDomain(String),
28
29 #[error("Domain not allowed: TLD '{tld}' is not in the allowlist")]
30 DomainNotAllowed { domain: String, tld: String },
31
32 #[error("Invalid IP address: {0}")]
33 InvalidIpAddress(String),
34
35 #[error("Invalid record type: {0}")]
36 InvalidRecordType(String),
37
38 #[error("HTTP request failed: {0}")]
39 HttpError(String),
40
41 #[error("Reqwest error: {0}")]
42 ReqwestError(#[from] reqwest::Error),
43
44 #[error("JSON parsing failed: {0}")]
45 JsonError(#[from] serde_json::Error),
46
47 #[error("Timeout: {0}")]
48 Timeout(String),
49
50 #[error("Rate limited: {0}")]
51 RateLimited(String),
52
53 #[error("Certificate error: {0}")]
54 CertificateError(String),
55
56 #[error("Bulk operation failed: {context}")]
57 BulkOperationError {
58 context: String,
59 failures: Vec<(String, String)>,
60 },
61
62 #[error("Lookup failed for {domain}: {details}\n\nTip: Try checking the registry directly at: {registry_url}")]
63 LookupFailed {
64 domain: String,
65 details: String,
66 registry_url: String,
67 },
68
69 #[error("{0}")]
70 Other(String),
71
72 #[error("Operation failed after {attempts} attempts: {last_error}")]
73 RetryExhausted { attempts: usize, last_error: String },
74}
75
76impl SeerError {
77 pub fn sanitized_message(&self) -> String {
80 match self {
81 SeerError::WhoisError(_) => "WHOIS lookup failed".to_string(),
82 SeerError::WhoisServerNotFound(_) => "WHOIS server not found for this TLD".to_string(),
83 SeerError::WhoisConnectionFailed(_) => "WHOIS connection failed".to_string(),
84 SeerError::RdapError(_) => "RDAP lookup failed".to_string(),
85 SeerError::RdapBootstrapError(_) => {
86 "RDAP service unavailable for this resource".to_string()
87 }
88 SeerError::DnsError(_) => "DNS resolution failed".to_string(),
89 SeerError::DnsResolverError(_) => "DNS resolution failed".to_string(),
90 SeerError::InvalidDomain(domain) => format!("Invalid domain name: {}", domain),
91 SeerError::DomainNotAllowed { tld, .. } => {
92 format!("Domain not allowed: TLD '{}' is not in the allowlist", tld)
93 }
94 SeerError::InvalidIpAddress(ip) => format!("Invalid IP address: {}", ip),
95 SeerError::InvalidRecordType(rt) => format!("Invalid record type: {}", rt),
96 SeerError::HttpError(_) => "HTTP request failed".to_string(),
97 SeerError::ReqwestError(_) => "HTTP request failed".to_string(),
98 SeerError::JsonError(_) => "Response parsing failed".to_string(),
99 SeerError::Timeout(_) => "Operation timed out".to_string(),
100 SeerError::RateLimited(_) => "Rate limited - please try again later".to_string(),
101 SeerError::CertificateError(_) => "Certificate validation failed".to_string(),
102 SeerError::BulkOperationError { .. } => "Bulk operation partially failed".to_string(),
103 SeerError::LookupFailed { domain, .. } => format!("Lookup failed for {}", domain),
104 SeerError::Other(_) => "Operation failed".to_string(),
105 SeerError::RetryExhausted { attempts, .. } => {
106 format!("Operation failed after {} attempts", attempts)
107 }
108 }
109 }
110}
111
112pub type Result<T> = std::result::Result<T, SeerError>;