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(String),
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("SSL error: {0}")]
57 SslError(String),
58
59 #[error("Bulk operation failed: {context}")]
60 BulkOperationError {
61 context: String,
62 failures: Vec<(String, String)>,
63 },
64
65 #[error("Lookup failed for {domain}: {details}\n\nTip: Try checking the registry directly at: {registry_url}")]
66 LookupFailed {
67 domain: String,
68 details: String,
69 registry_url: String,
70 },
71
72 #[error("Configuration error: {0}")]
73 ConfigError(String),
74
75 #[error("{0}")]
76 Other(String),
77
78 #[error("Operation failed after {attempts} attempts: {last_error}")]
79 RetryExhausted { attempts: usize, last_error: String },
80}
81
82impl SeerError {
83 pub fn sanitized_message(&self) -> String {
86 match self {
87 SeerError::WhoisError(_) => "WHOIS lookup failed".to_string(),
88 SeerError::WhoisServerNotFound(_) => "WHOIS server not found for this TLD".to_string(),
89 SeerError::WhoisConnectionFailed(_) => "WHOIS connection failed".to_string(),
90 SeerError::RdapError(_) => "RDAP lookup failed".to_string(),
91 SeerError::RdapBootstrapError(_) => {
92 "RDAP service unavailable for this resource".to_string()
93 }
94 SeerError::DnsError(_) => "DNS resolution failed".to_string(),
95 SeerError::DnsResolverError(_) => "DNS resolution failed".to_string(),
96 SeerError::InvalidDomain(domain) => format!("Invalid domain name: {}", domain),
97 SeerError::DomainNotAllowed { tld, .. } => {
98 format!("Domain not allowed: TLD '{}' is not in the allowlist", tld)
99 }
100 SeerError::InvalidIpAddress(ip) => format!("Invalid IP address: {}", ip),
101 SeerError::InvalidRecordType(rt) => format!("Invalid record type: {}", rt),
102 SeerError::HttpError(_) => "HTTP request failed".to_string(),
103 SeerError::ReqwestError(_) => "HTTP request failed".to_string(),
104 SeerError::JsonError(_) => "Response parsing failed".to_string(),
105 SeerError::Timeout(_) => "Operation timed out".to_string(),
106 SeerError::RateLimited(_) => "Rate limited - please try again later".to_string(),
107 SeerError::CertificateError(_) => "Certificate validation failed".to_string(),
108 SeerError::SslError(_) => "SSL inspection failed".to_string(),
109 SeerError::BulkOperationError { .. } => "Bulk operation partially failed".to_string(),
110 SeerError::LookupFailed { domain, .. } => format!("Lookup failed for {}", domain),
111 SeerError::ConfigError(msg) => format!("Configuration error: {}", msg),
112 SeerError::Other(_) => "Operation failed".to_string(),
113 SeerError::RetryExhausted { attempts, .. } => {
114 format!("Operation failed after {} attempts", attempts)
115 }
116 }
117 }
118}
119
120pub type Result<T> = std::result::Result<T, SeerError>;