diff --git a/Program.cs b/Program.cs index 5dca1ad..828a214 100644 --- a/Program.cs +++ b/Program.cs @@ -308,4 +308,333 @@ public static class Program } return true; } + + static void Setup(string username = "") + { + if (Verbose) Console.WriteLine("Opening manifest..."); + Manifest = Manifest.GetManifest(true); + + if (string.IsNullOrWhiteSpace(username)) + { + Console.Write("Username: "); + username = Console.ReadLine(); + } + Console.Write("Password: "); + var password = Console.ReadLine(); + + UserLogin login = new UserLogin(username, password); + Console.Write($"Logging in {username}... "); + LoginResult loginResult = login.DoLogin(); + Console.WriteLine(loginResult); + if (!login.LoggedIn) return; + + AuthenticatorLinker linker = new AuthenticatorLinker(login.Session); + AuthenticatorLinker.LinkResult linkResult = AuthenticatorLinker.LinkResult.GeneralFailure; + + do + { + linkResult = linker.AddAuthenticator(); + Console.WriteLine($"Link result: {linkResult}"); + switch (linkResult) + { + case AuthenticatorLinker.LinkResult.MustProvidePhoneNumber: + var phonenumber = ""; + do + { + Console.WriteLine("Enter your mobile phone number in the following format: +{cC} phoneNumber. EG, +1 123-456-7890"); + phonenumber = Console.ReadLine(); + phonenumber = FilterPhoneNumber(phonenumber); + linker.PhoneNumber = phonenumber; + } while (!PhoneNumberOkay(phonenumber)); + break; + case AuthenticatorLinker.LinkResult.MustRemovePhoneNumber: + linker.PhoneNumber = null; + break; + case AuthenticatorLinker.LinkResult.AwaitingFinalization: + break; + case AuthenticatorLinker.LinkResult.GeneralFailure: + Console.WriteLine("error: Unable to add your phone number. Steam returned GeneralFailure"); + return; + case AuthenticatorLinker.LinkResult.AuthenticatorPresent: + Console.WriteLine("error: Can't link authenticator, remove the previous authenticator."); + return; + default: + Console.WriteLine($"error: Unexpected linker result: {linkResult}"); + return; + } + } while (linkResult != AuthenticatorLinker.LinkResult.AwaitingFinalization); + + string passKey = null; + if (Manifest.Entries.Count == 0) + { + Console.WriteLine("Looks like we are setting up your first account."); + passKey = Manifest.PromptSetupPassKey(); + } + else if (Manifest.Entries.Count > 0 && Manifest.Encrypted) + { + passKey = Manifest.PromptForPassKey(); + } + + //Save the file immediately; losing this would be bad. + if (!Manifest.SaveAccount(linker.LinkedAccount, passKey != null, passKey)) + { + Manifest.RemoveAccount(linker.LinkedAccount); + Console.WriteLine("Unable to save mobile authenticator file. The mobile authenticator has not been linked."); + return; + } + + Console.WriteLine( + $"The Mobile Authenticator has not yet been linked. Before finalizing the authenticator, please write down your revocation code: {linker.LinkedAccount.RevocationCode}"); + + AuthenticatorLinker.FinalizeResult finalizeResponse = AuthenticatorLinker.FinalizeResult.GeneralFailure; + do + { + Console.Write("Please input the SMS message sent to your phone number: "); + string smsCode = Console.ReadLine(); + + finalizeResponse = linker.FinalizeAddAuthenticator(smsCode); + if (Verbose) Console.WriteLine(finalizeResponse); + + switch (finalizeResponse) + { + case AuthenticatorLinker.FinalizeResult.BadSMSCode: + continue; + + case AuthenticatorLinker.FinalizeResult.UnableToGenerateCorrectCodes: + Console.WriteLine( + "Unable to generate the proper codes to finalize this authenticator. The authenticator should not have been linked."); + Console.WriteLine( + $"In the off-chance it was, please write down your revocation code, as this is the last chance to see it: {linker.LinkedAccount.RevocationCode}"); + Manifest.RemoveAccount(linker.LinkedAccount); + return; + + case AuthenticatorLinker.FinalizeResult.GeneralFailure: + Console.WriteLine("Unable to finalize this authenticator. The authenticator should not have been linked."); + Console.WriteLine( + $"In the off-chance it was, please write down your revocation code, as this is the last chance to see it: {linker.LinkedAccount.RevocationCode}"); + Manifest.RemoveAccount(linker.LinkedAccount); + return; + } + } while (finalizeResponse != AuthenticatorLinker.FinalizeResult.Success); + + //Linked, finally. Re-save with FullyEnrolled property. + Manifest.SaveAccount(linker.LinkedAccount, passKey != null, passKey); + Console.WriteLine( + $"Mobile authenticator successfully linked. Please actually write down your revocation code: {linker.LinkedAccount.RevocationCode}"); + } + + public static string FilterPhoneNumber(string phoneNumber) + => phoneNumber.Replace("-", "").Replace("(", "").Replace(")", ""); + + public static bool PhoneNumberOkay(string phoneNumber) + { + if (phoneNumber == null || phoneNumber.Length == 0) return false; + if (phoneNumber[0] != '+') return false; + return true; + } + + static void Trade(string user = "") + { + if (Verbose) Console.WriteLine("Opening manifest..."); + Manifest = Manifest.GetManifest(true); + if (Verbose) Console.WriteLine("Reading accounts from manifest..."); + if (Manifest.Encrypted) + { + var passkey = Manifest.PromptForPassKey(); + SteamGuardAccounts = Manifest.GetAllAccounts(passkey); + } + else + { + SteamGuardAccounts = Manifest.GetAllAccounts(); + } + if (SteamGuardAccounts.Length == 0) + { + Console.WriteLine("error: No accounts read."); + return; + } + + foreach (var account in SteamGuardAccounts) + { + if (user != "") + if (!string.Equals(account.AccountName, user, StringComparison.CurrentCultureIgnoreCase)) + break; + + processConfirmations(account); + } + } + + enum TradeAction + { + Accept = 1, + Deny = 0, + Ignore = -1 + } + + static void processConfirmations(SteamGuardAccount account) + { + if (Verbose) Console.WriteLine("Refeshing Session..."); + account.RefreshSession(); + Console.WriteLine("Retrieving trade confirmations..."); + var trades = account.FetchConfirmations(); + var tradeActions = new TradeAction[trades.Length]; + for (var i = 0; i < tradeActions.Length; i++) + { + tradeActions[i] = TradeAction.Ignore; + } + if (trades.Length == 0) + { + Console.WriteLine($"No trade confirmations for {account.AccountName}."); + return; + } + var selected = 0; + var colorAccept = ConsoleColor.Green; + var colorDeny = ConsoleColor.Red; + var colorIgnore = ConsoleColor.Gray; + var colorSelected = ConsoleColor.Yellow; + var confirm = false; + + do + { + Console.Clear(); + if (selected >= trades.Length) + selected = trades.Length - 1; + else if (selected < 0) + selected = 0; + Console.ResetColor(); + Console.WriteLine($"Trade confirmations for {account.AccountName}..."); + Console.WriteLine("No action will be made without your confirmation."); + Console.WriteLine("[a]ccept [d]eny [i]gnore [enter] Confirm [q]uit"); // accept = 1, deny = 0, ignore = -1 + Console.WriteLine(); + + for (var t = 0; t < trades.Length; t++) + { + ConsoleColor itemColor; + switch (tradeActions[t]) + { + case TradeAction.Accept: + itemColor = colorAccept; + break; + case TradeAction.Deny: + itemColor = colorDeny; + break; + case TradeAction.Ignore: + itemColor = colorIgnore; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + Console.ForegroundColor = t == selected ? colorSelected : itemColor; + + Console.WriteLine($" [{t}] [{tradeActions[t]}] {trades[t].Description}"); + } + var key = Console.ReadKey(); + switch (key.Key) + { + case ConsoleKey.UpArrow: + case ConsoleKey.W: + selected--; + break; + case ConsoleKey.DownArrow: + case ConsoleKey.S: + selected++; + break; + case ConsoleKey.A: + tradeActions[selected] = TradeAction.Accept; + break; + case ConsoleKey.D: + tradeActions[selected] = TradeAction.Deny; + break; + case ConsoleKey.I: + tradeActions[selected] = TradeAction.Ignore; + break; + case ConsoleKey.Enter: + confirm = true; + break; + case ConsoleKey.Escape: + case ConsoleKey.Q: + Console.ResetColor(); + Console.WriteLine("Quitting..."); + return; + default: + break; + } + } while (!confirm); + Console.ResetColor(); + Console.WriteLine(); + Console.WriteLine("Processing..."); + for (var t = 0; t < trades.Length; t++) + { + bool success = false; + switch (tradeActions[t]) + { + case TradeAction.Accept: + if (Verbose) Console.Write($"Accepting {trades[t].Description}..."); + success = account.AcceptConfirmation(trades[t]); + break; + case TradeAction.Deny: + if (Verbose) Console.Write($"Denying {trades[t].Description}..."); + success = account.AcceptConfirmation(trades[t]); + break; + case TradeAction.Ignore: + if (Verbose) Console.Write($"Ignoring {trades[t].Description}..."); + success = true; + break; + default: + throw new ArgumentOutOfRangeException(); + } + if (Verbose) Console.WriteLine(success); + } + Console.WriteLine("Done."); + } + + static void AcceptAllTrades(string user = "") + { + if (Verbose) Console.WriteLine("Opening manifest..."); + Manifest = Manifest.GetManifest(true); + if (Verbose) Console.WriteLine("Reading accounts from manifest..."); + if (Manifest.Encrypted) + { + string passkey = Manifest.PromptForPassKey(); + SteamGuardAccounts = Manifest.GetAllAccounts(passkey); + } + else + { + SteamGuardAccounts = Manifest.GetAllAccounts(); + } + if (SteamGuardAccounts.Length == 0) + { + Console.WriteLine("error: No accounts read."); + return; + } + + for (int i = 0; i < SteamGuardAccounts.Length; i++) + { + SteamGuardAccount account = SteamGuardAccounts[i]; + if (user != "") + { + if (account.AccountName.ToLower() == user.ToLower()) + { + Console.WriteLine($"Accepting Confirmations on {account.AccountName}"); + if (Verbose) Console.WriteLine("Refeshing Session..."); + account.RefreshSession(); + if (Verbose) Console.WriteLine("Fetching Confirmations..."); + Confirmation[] confirmations = account.FetchConfirmations(); + if (Verbose) Console.WriteLine("Accepting Confirmations..."); + account.AcceptMultipleConfirmations(confirmations); + break; + } + } + else + { + Console.WriteLine($"Accepting Confirmations on {account.AccountName}"); + if (Verbose) Console.WriteLine("Refeshing Session..."); + account.RefreshSession(); + if (Verbose) Console.WriteLine("Fetching Confirmations..."); + Confirmation[] confirmations = account.FetchConfirmations(); + if (Verbose) Console.WriteLine("Accepting Confirmations..."); + account.AcceptMultipleConfirmations(confirmations); + } + } + } }