#![deny(unused_must_use)] extern crate elefren; #[macro_use] extern crate log; #[macro_use] extern crate serde; // #[macro_use] // extern crate smart_default; #[macro_use] extern crate thiserror; use clap::Arg; use log::LevelFilter; use crate::store::{NewGroupOptions, StoreOptions}; use crate::utils::acct_to_server; mod command; mod error; mod group_handler; mod store; mod utils; #[tokio::main] async fn main() -> anyhow::Result<()> { let args = clap::App::new("groups") .arg( Arg::with_name("verbose") .short("v") .multiple(true) .help("increase logging, can be repeated"), ) .arg( Arg::with_name("config") .short("c") .long("config") .takes_value(true) .help("set custom storage file, defaults to groups.json"), ) .arg( Arg::with_name("auth") .short("a") .long("auth") .takes_value(true) .value_name("HANDLE") .help("authenticate to a new server (always using https)"), ) .arg( Arg::with_name("reauth") .short("A") .long("reauth") .takes_value(true) .value_name("HANDLE") .help("authenticate to a new server (always using https)"), ) .get_matches(); const LEVELS: [LevelFilter; 5] = [ LevelFilter::Error, LevelFilter::Warn, LevelFilter::Info, LevelFilter::Debug, LevelFilter::Trace, ]; let default_level = 2; let level = (default_level + args.occurrences_of("verbose") as usize).min(LEVELS.len()); env_logger::Builder::new() .filter_level(LEVELS[level]) .write_style(env_logger::WriteStyle::Always) .filter_module("rustls", LevelFilter::Warn) .filter_module("reqwest", LevelFilter::Warn) .init(); let store = store::ConfigStore::new(StoreOptions { store_path: args.value_of("config").unwrap_or("groups.json").to_string(), save_pretty: true, }) .await?; if let Some(handle) = args.value_of("auth") { let handle = handle.to_lowercase(); let acct = handle.trim_start_matches('@'); if store.group_exists(acct).await { anyhow::bail!("Group already exists in config!"); } if let Some(server) = acct_to_server(acct) { let g = store .auth_new_group(NewGroupOptions { server: format!("https://{}", server), acct: acct.to_string(), }) .await?; eprintln!("New group @{} added to config!", g.config.get_acct()); return Ok(()); } else { anyhow::bail!("--auth handle must be username@server, got: \"{}\"", handle); } } if let Some(acct) = args.value_of("reauth") { let acct = acct.trim_start_matches('@'); let _ = store.reauth_group(acct).await?; eprintln!("Group @{} re-authed!", acct); return Ok(()); } // Start let groups = store.spawn_groups().await; let mut handles = vec![]; for mut g in groups { handles.push(tokio::spawn(async move { g.run().await })); } futures::future::join_all(handles).await; eprintln!("Main loop ended!"); Ok(()) }