use seer_core::{RecordType, SeerConfig};
use crate::query::{self, Clients, Query};
use crate::tui::action::{FetchReq, LensData};
pub async fn fetch(
req: FetchReq,
clients: &Clients,
config: &SeerConfig,
) -> Result<LensData, String> {
match to_query(req) {
Ok(query) => {
let outcome = query::run(query, clients, config, false)
.await
.map_err(|e| e.to_string())?;
Ok(outcome.payload)
}
Err(Store::Watch) => watchlist(config).await,
Err(Store::History) => history().await,
}
}
#[derive(Debug, PartialEq, Eq)]
enum Store {
Watch,
History,
}
fn to_query(req: FetchReq) -> Result<Query, Store> {
Ok(match req {
FetchReq::Overview(d) => Query::Lookup(d),
FetchReq::Whois(d) => Query::Whois(d),
FetchReq::RdapDomain(q) | FetchReq::RdapIp(q) => Query::Rdap(q),
FetchReq::RdapAsn(asn) => Query::Rdap(format!("AS{asn}")),
FetchReq::Dns {
domain,
record_type,
nameserver,
} => Query::Dig {
name: domain,
types: vec![record_type],
server: nameserver,
short: false,
},
FetchReq::Dnssec(d) => Query::Dnssec(d),
FetchReq::Compare {
domain,
record_type,
a,
b,
} => Query::Compare {
domain,
record_type,
server_a: a,
server_b: b,
},
FetchReq::Trace {
domain,
record_type,
} => Query::Trace {
name: domain,
record_type,
short: false,
},
FetchReq::Ssl(d) => Query::Ssl(d),
FetchReq::Status(d) => Query::Status(d),
FetchReq::Prop(d) => Query::Prop {
domain: d,
record_type: RecordType::A,
},
FetchReq::Reverse(ip) => Query::Reverse(ip),
FetchReq::Avail(d) => Query::Avail(d),
FetchReq::Tld(t) => Query::Tld(t),
FetchReq::Diff { a, b } => Query::Diff(a, b),
FetchReq::Subdomains(d) => Query::Subdomains {
domain: d,
resolve: false,
diff: false,
record: false,
},
FetchReq::Headers(d) => Query::Headers(d),
FetchReq::Takeover(d) => Query::Takeover {
domain: d,
hosts: Vec::new(),
},
FetchReq::Watch => return Err(Store::Watch),
FetchReq::History => return Err(Store::History),
})
}
async fn watchlist(config: &SeerConfig) -> Result<LensData, String> {
let wl = crate::ops::load_watchlist().await?;
Ok(LensData::Watch(Box::new(
seer_core::check_watchlist_with_config(&wl.domains, config).await,
)))
}
async fn history() -> Result<LensData, String> {
let h = crate::ops::load_history().await?;
let mut flat: Vec<seer_core::HistoryEntry> = h.entries.into_values().flatten().collect();
flat.sort_by_key(|e| std::cmp::Reverse(e.timestamp));
Ok(LensData::History(flat))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn requests_map_to_the_cli_commands() {
assert!(matches!(
to_query(FetchReq::Takeover("www.example.com".into())),
Ok(Query::Takeover { ref domain, ref hosts }) if domain == "www.example.com" && hosts.is_empty()
));
assert!(matches!(
to_query(FetchReq::Overview("example.com".into())),
Ok(Query::Lookup(ref d)) if d == "example.com"
));
assert!(matches!(
to_query(FetchReq::RdapAsn(15169)),
Ok(Query::Rdap(ref q)) if q == "AS15169"
));
assert!(matches!(
to_query(FetchReq::Dns {
domain: "example.com".into(),
record_type: RecordType::MX,
nameserver: Some("1.1.1.1".into()),
}),
Ok(Query::Dig { ref types, ref server, short: false, .. })
if *types == [RecordType::MX] && server.as_deref() == Some("1.1.1.1")
));
assert!(matches!(
to_query(FetchReq::Subdomains("example.com".into())),
Ok(Query::Subdomains {
resolve: false,
diff: false,
record: false,
..
})
));
assert!(matches!(to_query(FetchReq::Watch), Err(Store::Watch)));
assert!(matches!(to_query(FetchReq::History), Err(Store::History)));
}
}