diff --git a/Core/LoginWindowState.cs b/Core/LoginWindowState.cs index c5e96c3..bd585e5 100644 --- a/Core/LoginWindowState.cs +++ b/Core/LoginWindowState.cs @@ -8,6 +8,7 @@ enum LoginWindowState Selection, Login, Code, + CodeOption, Loading, Success } diff --git a/Core/WindowUtils.cs b/Core/WindowUtils.cs index c5fcc1f..5f737cb 100644 --- a/Core/WindowUtils.cs +++ b/Core/WindowUtils.cs @@ -285,6 +285,18 @@ public static LoginWindowState GetLoginWindowState(WindowHandle loginWindow) { return LoginWindowState.Error; } + else if (inputs.Count == 0 && buttons.Count == 0 && groups.Count == 0 && images.Count == 3 && texts.Count == 7) + { + // Check if "Enter a code instead" text is present + foreach (var text in texts) + { + string content = text.Name; + if (content.Contains("Enter a code instead") || content.Contains("_2YsaRupK3XuabHMh9_BfZP")) + { + return LoginWindowState.CodeOption; + } + } + } else if (inputs.Count == 0 && images.Count >= 2 && buttons.Count > 0 && texts.Count == 0) { return LoginWindowState.Selection; @@ -584,5 +596,90 @@ public static IDataObject GetClipboardDataObjectSTA() thread.Join(); return data; } + + public static LoginWindowState HandleCodeOption(WindowHandle loginWindow) + { + using (var automation = new UIA3Automation()) + { + try + { + AutomationElement window = automation.FromHandle(loginWindow.RawPtr); + + if (window == null) + { + return LoginWindowState.Invalid; + } + + window.Focus(); + + AutomationElement document = window.FindFirstDescendant(e => e.ByControlType(ControlType.Document)); + AutomationElement[] texts = document.FindAllChildren(e => e.ByControlType(ControlType.Text)); + + // Find and click the "Enter a code instead" text element + foreach (var text in texts) + { + string content = text.Name; + if (content.Contains("Enter a code instead")) + { + // Try to click the text element directly + try + { + text.Focus(); + text.Click(); + Thread.Sleep(500); // Wait for transition + return LoginWindowState.Code; + } + catch + { + // If direct click fails, try using coordinates + var rect = text.Properties.BoundingRectangle; + if (rect.IsSupported && rect.Value.X > 0) + { + double centerX = rect.Value.X + rect.Value.Width / 2; + double centerY = rect.Value.Y + rect.Value.Height / 2; + Mouse.Click(new System.Drawing.Point((int)centerX, (int)centerY)); + Thread.Sleep(500); + return LoginWindowState.Code; + } + } + } + } + + // Alternative: try to find clickable elements in the area where "Enter a code instead" appears + AutomationElement[] allElements = document.FindAllDescendants(); + foreach (var element in allElements) + { + if (element.Name.Contains("Enter a code instead")) + { + try + { + element.Focus(); + element.Click(); + Thread.Sleep(500); + return LoginWindowState.Code; + } + catch + { + var rect = element.Properties.BoundingRectangle; + if (rect.IsSupported && rect.Value.X > 0) + { + double centerX = rect.Value.X + rect.Value.Width / 2; + double centerY = rect.Value.Y + rect.Value.Height / 2; + Mouse.Click(new System.Drawing.Point((int)centerX, (int)centerY)); + Thread.Sleep(500); + return LoginWindowState.Code; + } + } + } + } + } + catch (Exception e) + { + Console.WriteLine("HandleCodeOption error: " + e.Message); + } + } + + return LoginWindowState.CodeOption; // Return same state if click failed + } } } diff --git a/Views/AccountsWindow.xaml.cs b/Views/AccountsWindow.xaml.cs index f971711..d7f6087 100644 --- a/Views/AccountsWindow.xaml.cs +++ b/Views/AccountsWindow.xaml.cs @@ -1405,7 +1405,7 @@ private void EnterCredentials(Process steamProcess, Account account, int tryCoun SetWindowTitle("Working"); LoginWindowState state = LoginWindowState.None; - while (state != LoginWindowState.Success && state != LoginWindowState.Code) + while (state != LoginWindowState.Success && state != LoginWindowState.Code && state != LoginWindowState.CodeOption) { if (steamProcess.HasExited || state == LoginWindowState.Error) { @@ -1427,6 +1427,14 @@ private void EnterCredentials(Process steamProcess, Account account, int tryCoun string password = StringCipher.Decrypt(account.Password, eKey); state = WindowUtils.TryCredentialsEntry(steamLoginWindow, account.Name, password, settings.User.RememberPassword); } + + if (state == LoginWindowState.CodeOption) + { + // Handle "Enter a code instead" option + state = WindowUtils.HandleCodeOption(steamLoginWindow); + // Continue the loop to check if we're now in Code state + continue; + } } string secret = StringCipher.Decrypt(account.SharedSecret, eKey); @@ -1508,6 +1516,14 @@ private void EnterReact2FA(Process steamProcess, Account account, int tryCount) state = WindowUtils.GetLoginWindowState(steamLoginWindow); + if (state == LoginWindowState.CodeOption) + { + // Handle "Enter a code instead" option + state = WindowUtils.HandleCodeOption(steamLoginWindow); + // Continue the loop to check if we're now in Code state + continue; + } + if (state == LoginWindowState.Code) { state = WindowUtils.TryCodeEntry(steamLoginWindow, secret); @@ -2505,8 +2521,6 @@ private void AccountsDataGrid_PreviewMouseRightButtonDown(object sender, MouseBu } } - #endregion - private void AccountsDataGrid_ColumnReordered(object sender, DataGridColumnEventArgs e) { foreach (DataGridColumn column in AccountsDataGrid.Columns) @@ -2682,5 +2696,7 @@ private void ShowMessage(string title, string message) await this.ShowMessageAsync(title, message); }); } + + #endregion } }