#[macro_use] mod macros; mod connection; mod repl; mod tls; use repl::ClientState; use zagan_bet::client::paths::{database_path, default_data_dir, parse_args, USAGE}; fn main() { let args = match parse_args(std::env::args().skip(1)) { Ok(args) => args, Err(message) => { eprintln!("{message}"); std::process::exit(2); } }; if args.help { println!("{USAGE}"); return; } // Every game board is drawn in place, so refuse a terminal that cannot fit // them before touching the network or the terminal mode. let size = crossterm::terminal::size(); let (columns, rows) = match &size { Ok((columns, rows)) => (*columns, *rows), Err(_) => (0, 0), }; if let Some(message) = zagan_bet::client::ui::terminal_too_small(columns, rows) { eprintln!("{message}"); if size.is_err() { eprintln!("Could not read the terminal size (is this a real terminal?)."); } std::process::exit(1); } if args.unsafe_mode { println!("WARNING: Running in UNSAFE mode - certificate verification disabled!"); } connection::set_unsafe_mode(args.unsafe_mode); let data_dir = args.data_dir.unwrap_or_else(default_data_dir); if let Err(error) = std::fs::create_dir_all(&data_dir) { eprintln!("Cannot create {}: {error}", data_dir.display()); std::process::exit(1); } let db_path = database_path(&data_dir); let mut state = match ClientState::new(&db_path) { Ok(state) => state, Err(error) => { eprintln!("{error}"); std::process::exit(1); } }; if let Some(host) = state.addr.clone() { state.connect_to(&host); } println!("Welcome to Zagan-Bet Client!"); println!("Type 'help' for available commands."); println!("Data: {}", db_path.display()); state.run(); }