add subcommand arg types

This commit is contained in:
Carson McManus 2022-06-19 10:38:59 -04:00
parent e6847975ff
commit b55df7ea26

View file

@ -121,6 +121,46 @@ impl FromStr for Verbosity {
} }
} }
struct ArgsSetup {
username: Option<String>,
}
impl From<Subcommands> for ArgsSetup {
fn from(sub: Subcommands) -> Self {
match sub {
Subcommands::Setup { username } => Self { username },
_ => panic!("ArgsSetup::from() called with non-Setup subcommand"),
}
}
}
struct ArgsImport {
files: Vec<String>,
}
impl From<Subcommands> for ArgsImport {
fn from(sub: Subcommands) -> Self {
match sub {
Subcommands::Import { files } => Self { files },
_ => panic!("ArgsImport::from() called with non-Import subcommand"),
}
}
}
struct ArgsTrade {
accept_all: bool,
fail_fast: bool,
}
impl From<Subcommands> for ArgsTrade {
fn from(sub: Subcommands) -> Self {
match sub {
Subcommands::Trade { accept_all, fail_fast } => Self { accept_all, fail_fast },
_ => panic!("ArgsTrade::from() called with non-Trade subcommand"),
}
}
}
fn cli() -> App<'static> { fn cli() -> App<'static> {
App::new("steamguard-cli") App::new("steamguard-cli")
.version(crate_version!()) .version(crate_version!())
@ -329,120 +369,18 @@ fn run() -> anyhow::Result<()> {
if let Some(subcmd) = new_args.sub { if let Some(subcmd) = new_args.sub {
match subcmd { match subcmd {
Subcommands::Setup{ username } => {}, Subcommands::Setup{ username } => {
s => { do_subcmd_setup(new_args.sub.unwrap().into(), &mut manifest)?;
error!("Unknown subcommand: {:?}", s);
}, },
Subcommands::Import { files } => {todo!()},
Subcommands::Encrypt {} => {todo!()},
Subcommands::Decrypt {} => {todo!()},
_ => {},
} }
} }
if matches.is_present("setup") { if matches.is_present("setup") {
println!("Log in to the account that you want to link to steamguard-cli");
print!("Username: ");
let username = tui::prompt();
let account_name = username.clone();
if manifest.account_exists(&username) {
bail!(
"Account {} already exists in manifest, remove it first",
username
);
}
let session =
do_login_raw(username).expect("Failed to log in. Account has not been linked.");
let mut linker = AccountLinker::new(session);
let account: SteamGuardAccount;
loop {
match linker.link() {
Ok(a) => {
account = a;
break;
}
Err(AccountLinkError::MustRemovePhoneNumber) => {
println!("There is already a phone number on this account, please remove it and try again.");
bail!("There is already a phone number on this account, please remove it and try again.");
}
Err(AccountLinkError::MustProvidePhoneNumber) => {
println!("Enter your phone number in the following format: +1 123-456-7890");
print!("Phone number: ");
linker.phone_number = tui::prompt().replace(&['(', ')', '-'][..], "");
}
Err(AccountLinkError::AuthenticatorPresent) => {
println!("An authenticator is already present on this account.");
bail!("An authenticator is already present on this account.");
}
Err(AccountLinkError::MustConfirmEmail) => {
println!("Check your email and click the link.");
tui::pause();
}
Err(err) => {
error!(
"Failed to link authenticator. Account has not been linked. {}",
err
);
return Err(err.into());
}
}
}
manifest.add_account(account);
match manifest.save() {
Ok(_) => {}
Err(err) => {
error!("Aborting the account linking process because we failed to save the manifest. This is really bad. Here is the error: {}", err);
println!(
"Just in case, here is the account info. Save it somewhere just in case!\n{:?}",
manifest.get_account(&account_name).unwrap().lock().unwrap()
);
return Err(err.into());
}
}
let account_arc = manifest.get_account(&account_name).unwrap();
let mut account = account_arc.lock().unwrap();
println!("Authenticator has not yet been linked. Before continuing with finalization, please take the time to write down your revocation code: {}", account.revocation_code);
tui::pause();
debug!("attempting link finalization");
print!("Enter SMS code: ");
let sms_code = tui::prompt();
let mut tries = 0;
loop {
match linker.finalize(&mut account, sms_code.clone()) {
Ok(_) => break,
Err(FinalizeLinkError::WantMore) => {
debug!("steam wants more 2fa codes (tries: {})", tries);
tries += 1;
if tries >= 30 {
error!("Failed to finalize: unable to generate valid 2fa codes");
bail!("Failed to finalize: unable to generate valid 2fa codes");
}
}
Err(err) => {
error!("Failed to finalize: {}", err);
return Err(err.into());
}
}
}
println!("Authenticator finalized.");
match manifest.save() {
Ok(_) => {}
Err(err) => {
println!(
"Failed to save manifest, but we were able to save it before. {}",
err
);
return Err(err);
}
}
println!(
"Authenticator has been finalized. Please actually write down your revocation code: {}",
account.revocation_code
);
return Ok(());
} else if let Some(import_matches) = matches.subcommand_matches("import") { } else if let Some(import_matches) = matches.subcommand_matches("import") {
for file_path in import_matches.values_of("files").unwrap() { for file_path in import_matches.values_of("files").unwrap() {
match manifest.import_account(file_path.into()) { match manifest.import_account(file_path.into()) {
@ -521,28 +459,6 @@ fn run() -> anyhow::Result<()> {
if let Some(subcmd) = new_args.sub { if let Some(subcmd) = new_args.sub {
match subcmd { match subcmd {
Subcommands::Trade{ accept_all, fail_fast } => { Subcommands::Trade{ accept_all, fail_fast } => {
todo!()
},
s => {
error!("Unknown subcommand: {:?}", s);
},
}
} else {
let server_time = steamapi::get_server_time();
debug!("Time used to generate codes: {}", server_time);
for account in selected_accounts {
info!(
"Generating code for {}",
account.lock().unwrap().account_name
);
trace!("{:?}", account);
let code = account.lock().unwrap().generate_code(server_time);
println!("{}", code);
}
}
if let Some(trade_matches) = matches.subcommand_matches("trade") {
info!("trade");
for a in selected_accounts.iter_mut() { for a in selected_accounts.iter_mut() {
let mut account = a.lock().unwrap(); let mut account = a.lock().unwrap();
@ -562,8 +478,7 @@ fn run() -> anyhow::Result<()> {
} }
let mut any_failed = false; let mut any_failed = false;
let fail_fast = trade_matches.is_present("fail-fast"); if accept_all {
if trade_matches.is_present("accept-all") {
info!("accepting all confirmations"); info!("accepting all confirmations");
for conf in &confirmations { for conf in &confirmations {
let result = account.accept_confirmation(conf); let result = account.accept_confirmation(conf);
@ -619,7 +534,8 @@ fn run() -> anyhow::Result<()> {
} }
manifest.save()?; manifest.save()?;
} else if let Some(_) = matches.subcommand_matches("remove") { },
Subcommands::Remove { username } => {
println!( println!(
"This will remove the mobile authenticator from {} accounts: {}", "This will remove the mobile authenticator from {} accounts: {}",
selected_accounts.len(), selected_accounts.len(),
@ -676,7 +592,25 @@ fn run() -> anyhow::Result<()> {
} }
manifest.save()?; manifest.save()?;
},
s => {
error!("Unknown subcommand: {:?}", s);
},
} }
} else {
let server_time = steamapi::get_server_time();
debug!("Time used to generate codes: {}", server_time);
for account in selected_accounts {
info!(
"Generating code for {}",
account.lock().unwrap().account_name
);
trace!("{:?}", account);
let code = account.lock().unwrap().generate_code(server_time);
println!("{}", code);
}
}
Ok(()) Ok(())
} }
@ -801,6 +735,114 @@ fn get_mafiles_dir() -> String {
return paths[0].to_str().unwrap().into(); return paths[0].to_str().unwrap().into();
} }
fn do_subcmd_setup(args: Subcommands) -> anyhow::Result<()> { fn do_subcmd_setup(args: ArgsSetup, manifest: &mut accountmanager::Manifest) -> anyhow::Result<()> {
println!("Log in to the account that you want to link to steamguard-cli");
print!("Username: ");
let username = args.username.unwrap_or(tui::prompt());
if args.username.is_some() {
println!("{}", username);
}
let account_name = username.clone();
if manifest.account_exists(&username) {
bail!(
"Account {} already exists in manifest, remove it first",
username
);
}
let session =
do_login_raw(username).expect("Failed to log in. Account has not been linked.");
let mut linker = AccountLinker::new(session);
let account: SteamGuardAccount;
loop {
match linker.link() {
Ok(a) => {
account = a;
break;
}
Err(AccountLinkError::MustRemovePhoneNumber) => {
println!("There is already a phone number on this account, please remove it and try again.");
bail!("There is already a phone number on this account, please remove it and try again.");
}
Err(AccountLinkError::MustProvidePhoneNumber) => {
println!("Enter your phone number in the following format: +1 123-456-7890");
print!("Phone number: ");
linker.phone_number = tui::prompt().replace(&['(', ')', '-'][..], "");
}
Err(AccountLinkError::AuthenticatorPresent) => {
println!("An authenticator is already present on this account.");
bail!("An authenticator is already present on this account.");
}
Err(AccountLinkError::MustConfirmEmail) => {
println!("Check your email and click the link.");
tui::pause();
}
Err(err) => {
error!(
"Failed to link authenticator. Account has not been linked. {}",
err
);
return Err(err.into());
}
}
}
manifest.add_account(account);
match manifest.save() {
Ok(_) => {}
Err(err) => {
error!("Aborting the account linking process because we failed to save the manifest. This is really bad. Here is the error: {}", err);
println!(
"Just in case, here is the account info. Save it somewhere just in case!\n{:?}",
manifest.get_account(&account_name).unwrap().lock().unwrap()
);
return Err(err.into());
}
}
let account_arc = manifest.get_account(&account_name).unwrap();
let mut account = account_arc.lock().unwrap();
println!("Authenticator has not yet been linked. Before continuing with finalization, please take the time to write down your revocation code: {}", account.revocation_code);
tui::pause();
debug!("attempting link finalization");
print!("Enter SMS code: ");
let sms_code = tui::prompt();
let mut tries = 0;
loop {
match linker.finalize(&mut account, sms_code.clone()) {
Ok(_) => break,
Err(FinalizeLinkError::WantMore) => {
debug!("steam wants more 2fa codes (tries: {})", tries);
tries += 1;
if tries >= 30 {
error!("Failed to finalize: unable to generate valid 2fa codes");
bail!("Failed to finalize: unable to generate valid 2fa codes");
}
}
Err(err) => {
error!("Failed to finalize: {}", err);
return Err(err.into());
}
}
}
println!("Authenticator finalized.");
match manifest.save() {
Ok(_) => {}
Err(err) => {
println!(
"Failed to save manifest, but we were able to save it before. {}",
err
);
return Err(err);
}
}
println!(
"Authenticator has been finalized. Please actually write down your revocation code: {}",
account.revocation_code
);
return Ok(());
} }