use clap::Parser;
use flawz::app::{App, AppResult};
use flawz::args::Args;
use flawz::cve::Cve;
use flawz::error::Error;
use flawz::event::{Event, EventHandler};
use flawz::handler::{handle_key_events, handle_mouse_events};
use flawz::terminal::Tui;
use flawz::widgets::SelectableList;
use ratatui::backend::CrosstermBackend;
use ratatui::Terminal;
use std::path::Path;
use std::{io, thread};
use nvd_cve::cache::{get_all, sync_blocking, CacheConfig};
use nvd_cve::client::{BlockingHttpClient, ReqwestBlockingClient};
fn main() -> AppResult<()> {
let args = Args::parse();
let config = CacheConfig {
url: args.url.to_string(),
feeds: args.feeds()?,
db: args.db.unwrap_or_else(CacheConfig::default_db_path),
show_progress: true,
force_update: args.force_update,
};
if !args.offline && !Path::new(&config.db).exists() || args.force_update {
let client = ReqwestBlockingClient::new(&config.url, None, None, None);
sync_blocking(&config, client).map_err(Error::CacheError)?;
}
let cves = get_all(&config).map_err(Error::CacheError)?;
let mut app = App::new(
cves.into_iter().map(Cve::from).collect(),
args.theme
.get_theme()
.ok_or_else(|| Error::ParseColorError)?,
args.query.clone().unwrap_or_default(),
);
let backend = CrosstermBackend::new(io::stderr());
let terminal = Terminal::new(backend)?;
let events = EventHandler::new(250);
let mut tui = Tui::new(terminal, events);
tui.init()?;
if !args.query.unwrap_or_default().is_empty() {
tui.events.sender.send(Event::Search)?;
}
while app.running {
tui.draw(&mut app)?;
match tui.events.next()? {
Event::Key(key_event) => handle_key_events(key_event, &mut app, &tui.events.sender)?,
Event::Mouse(mouse_event) => {
handle_mouse_events(mouse_event, &mut app, &tui.events.sender)?
}
Event::Resize(_, _) => {}
Event::Search => {
let query = app.input.value().to_lowercase();
let items = app.cves.clone();
let sender = tui.events.sender.clone();
thread::spawn(move || {
let items = items
.into_iter()
.filter(|cve| {
query.is_empty()
|| cve.id.to_lowercase().contains(&query)
|| cve
.description
.clone()
.unwrap_or_default()
.to_lowercase()
.contains(&query)
})
.collect();
sender
.send(Event::SearchResult(SelectableList::with_items(items)))
.unwrap();
});
}
Event::SearchResult(v) => {
app.list = v;
}
}
}
tui.exit()?;
Ok(())
}