use serde::{Deserialize, Serialize};
use crate::error::Result;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DomainRiskRequest {
pub domain: String,
#[serde(default = "default_timeout")]
pub timeout_secs: u64,
}
fn default_timeout() -> u64 { 10 }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DomainRiskResult {
pub domain: String,
pub risk_level: String,
pub domain_age_days: Option<i64>,
pub days_until_expiry: Option<i64>,
pub risk_signals: Vec<String>,
pub registrar: Option<String>,
pub whois_error: Option<String>,
}
pub async fn check_domain_risk(req: &DomainRiskRequest) -> Result<DomainRiskResult> {
let domain = req.domain.clone();
let timeout_secs = req.timeout_secs;
let whois_req = crate::api::WhoisCheckRequest {
domain: domain.clone(),
timeout_secs,
};
let whois_result = match crate::api::check_whois(&whois_req).await {
Ok(result) => result,
Err(e) => {
return Ok(DomainRiskResult {
domain,
risk_level: "unknown".to_string(),
domain_age_days: None,
days_until_expiry: None,
risk_signals: vec![],
registrar: None,
whois_error: Some(format!("{}", e)),
});
}
};
let mut risk_signals = Vec::new();
let mut domain_age_days: Option<i64> = None;
let mut days_until_expiry: Option<i64> = None;
if let Some(created_str) = &whois_result.created_date {
if let Some(created_secs) = crate::api::helpers::parse_rfc3339_secs(created_str) {
let now_secs = crate::api::helpers::now_timestamp();
let age = (now_secs.saturating_sub(created_secs) / 86400) as i64;
domain_age_days = Some(age);
if domain_age_days.unwrap_or(0) < 30 {
risk_signals.push("newly_registered".to_string());
} else if domain_age_days.unwrap_or(0) < 90 {
risk_signals.push("recently_registered".to_string());
}
}
}
if let Some(expiry_str) = &whois_result.expiration_date {
if let Some(expiry_secs) = crate::api::helpers::parse_rfc3339_secs(expiry_str) {
let now_secs = crate::api::helpers::now_timestamp();
let ttl = (expiry_secs as i64 - now_secs as i64) / 86400;
days_until_expiry = Some(ttl);
if days_until_expiry.unwrap_or(0) < 0 {
risk_signals.push("expired".to_string());
} else if days_until_expiry.unwrap_or(0) < 30 {
risk_signals.push("expiring_soon".to_string());
}
}
}
let risk_level = if risk_signals.len() >= 2 {
"high".to_string()
} else if risk_signals.len() == 1 {
"medium".to_string()
} else {
"low".to_string()
};
Ok(DomainRiskResult {
domain,
risk_level,
domain_age_days,
days_until_expiry,
risk_signals,
registrar: whois_result.registrar,
whois_error: whois_result.error,
})
}