mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-06 17:10:13 +00:00
Implement interactive command console
This commit is contained in:
@@ -84,6 +84,10 @@ namespace ArchiSteamFarm {
|
||||
|
||||
InitBotsComparer(botsComparer);
|
||||
|
||||
if (!GlobalConfig.Headless) {
|
||||
Logging.StartInteractiveConsole();
|
||||
}
|
||||
|
||||
if (GlobalConfig.IPC) {
|
||||
await ArchiKestrel.Start().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -1621,7 +1621,7 @@ namespace ArchiSteamFarm {
|
||||
ArchiLogger.LogGenericWarning(Strings.BotAuthenticatorInvalidDeviceID);
|
||||
|
||||
if (string.IsNullOrEmpty(DeviceID)) {
|
||||
string deviceID = Program.GetUserInput(ASF.EUserInputType.DeviceID, BotName);
|
||||
string deviceID = await Logging.GetUserInput(ASF.EUserInputType.DeviceID, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(deviceID)) {
|
||||
return;
|
||||
@@ -1674,9 +1674,9 @@ namespace ArchiSteamFarm {
|
||||
SteamFamilySharingIDs.ReplaceIfNeededWith(steamIDs);
|
||||
}
|
||||
|
||||
private bool InitLoginAndPassword(bool requiresPassword) {
|
||||
private async Task<bool> InitLoginAndPassword(bool requiresPassword) {
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamLogin)) {
|
||||
string steamLogin = Program.GetUserInput(ASF.EUserInputType.Login, BotName);
|
||||
string steamLogin = await Logging.GetUserInput(ASF.EUserInputType.Login, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(steamLogin)) {
|
||||
return false;
|
||||
@@ -1686,7 +1686,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (requiresPassword && string.IsNullOrEmpty(BotConfig.DecryptedSteamPassword)) {
|
||||
string steamPassword = Program.GetUserInput(ASF.EUserInputType.Password, BotName);
|
||||
string steamPassword = await Logging.GetUserInput(ASF.EUserInputType.Password, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(steamPassword)) {
|
||||
return false;
|
||||
@@ -1881,7 +1881,7 @@ namespace ArchiSteamFarm {
|
||||
await BotDatabase.SetLoginKey().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!InitLoginAndPassword(string.IsNullOrEmpty(loginKey))) {
|
||||
if (!await InitLoginAndPassword(string.IsNullOrEmpty(loginKey)).ConfigureAwait(false)) {
|
||||
Stop();
|
||||
|
||||
return;
|
||||
@@ -2256,7 +2256,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
break;
|
||||
case EResult.AccountLogonDenied:
|
||||
string authCode = Program.GetUserInput(ASF.EUserInputType.SteamGuard, BotName);
|
||||
string authCode = await Logging.GetUserInput(ASF.EUserInputType.SteamGuard, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(authCode)) {
|
||||
Stop();
|
||||
@@ -2270,7 +2270,7 @@ namespace ArchiSteamFarm {
|
||||
case EResult.AccountLoginDeniedNeedTwoFactor:
|
||||
|
||||
if (!HasMobileAuthenticator) {
|
||||
string twoFactorCode = Program.GetUserInput(ASF.EUserInputType.TwoFactorAuthentication, BotName);
|
||||
string twoFactorCode = await Logging.GetUserInput(ASF.EUserInputType.TwoFactorAuthentication, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(twoFactorCode)) {
|
||||
Stop();
|
||||
@@ -2323,7 +2323,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(BotConfig.SteamParentalCode) && (BotConfig.SteamParentalCode.Length != 4)) {
|
||||
string steamParentalCode = Program.GetUserInput(ASF.EUserInputType.SteamParentalCode, BotName);
|
||||
string steamParentalCode = await Logging.GetUserInput(ASF.EUserInputType.SteamParentalCode, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(steamParentalCode) || (steamParentalCode.Length != 4)) {
|
||||
Stop();
|
||||
|
||||
45
ArchiSteamFarm/Localization/Strings.Designer.cs
generated
45
ArchiSteamFarm/Localization/Strings.Designer.cs
generated
@@ -763,6 +763,15 @@ namespace ArchiSteamFarm.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Enter command: .
|
||||
/// </summary>
|
||||
public static string EnterCommand {
|
||||
get {
|
||||
return ResourceManager.GetString("EnterCommand", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Aborted!.
|
||||
/// </summary>
|
||||
@@ -981,6 +990,15 @@ namespace ArchiSteamFarm.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Executing....
|
||||
/// </summary>
|
||||
public static string Executing {
|
||||
get {
|
||||
return ResourceManager.GetString("Executing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Exiting....
|
||||
/// </summary>
|
||||
@@ -1089,6 +1107,24 @@ namespace ArchiSteamFarm.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Interactive console is now active, type 'c' in order to enter command mode..
|
||||
/// </summary>
|
||||
public static string InteractiveConsoleEnabled {
|
||||
get {
|
||||
return ResourceManager.GetString("InteractiveConsoleEnabled", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Interactive console is not available due to missing {0} config property..
|
||||
/// </summary>
|
||||
public static string InteractiveConsoleNotAvailable {
|
||||
get {
|
||||
return ResourceManager.GetString("InteractiveConsoleNotAvailable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu IPC server ready!.
|
||||
/// </summary>
|
||||
@@ -1224,6 +1260,15 @@ namespace ArchiSteamFarm.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Response: {0}.
|
||||
/// </summary>
|
||||
public static string Response {
|
||||
get {
|
||||
return ResourceManager.GetString("Response", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Restarting....
|
||||
/// </summary>
|
||||
|
||||
@@ -696,4 +696,21 @@ StackTrace:
|
||||
<data name="PleaseWait" xml:space="preserve">
|
||||
<value>Please wait...</value>
|
||||
</data>
|
||||
<data name="EnterCommand" xml:space="preserve">
|
||||
<value>Enter command: </value>
|
||||
</data>
|
||||
<data name="Executing" xml:space="preserve">
|
||||
<value>Executing...</value>
|
||||
</data>
|
||||
<data name="InteractiveConsoleEnabled" xml:space="preserve">
|
||||
<value>Interactive console is now active, type 'c' in order to enter command mode.</value>
|
||||
</data>
|
||||
<data name="InteractiveConsoleNotAvailable" xml:space="preserve">
|
||||
<value>Interactive console is not available due to missing {0} config property.</value>
|
||||
<comment>{0} will be replaced by the name of the missing config property (string)</comment>
|
||||
</data>
|
||||
<data name="Response" xml:space="preserve">
|
||||
<value>Response: {0}</value>
|
||||
<comment>{0} will be replaced by the generated response (string)</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -19,19 +19,27 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.Collections;
|
||||
using ArchiSteamFarm.IPC;
|
||||
using ArchiSteamFarm.Localization;
|
||||
using JetBrains.Annotations;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.Targets;
|
||||
|
||||
namespace ArchiSteamFarm.NLog {
|
||||
internal static class Logging {
|
||||
private const byte ConsoleResponsivenessDelay = 250; // In miliseconds
|
||||
private const string GeneralLayout = @"${date:format=yyyy-MM-dd HH\:mm\:ss}|${processname}-${processid}|${level:uppercase=true}|" + LayoutMessage;
|
||||
private const string LayoutMessage = @"${logger}|${message}${onexception:inner= ${exception:format=toString,Data}}";
|
||||
|
||||
private static readonly ConcurrentHashSet<LoggingRule> ConsoleLoggingRules = new ConcurrentHashSet<LoggingRule>();
|
||||
private static readonly SemaphoreSlim ConsoleSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
private static bool IsUsingCustomConfiguration;
|
||||
private static bool IsWaitingForUserInput;
|
||||
@@ -53,6 +61,84 @@ namespace ArchiSteamFarm.NLog {
|
||||
}
|
||||
}
|
||||
|
||||
internal static async Task<string> GetUserInput(ASF.EUserInputType userInputType, string botName = SharedInfo.ASF) {
|
||||
if (userInputType == ASF.EUserInputType.Unknown) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ASF.GlobalConfig.Headless) {
|
||||
ASF.ArchiLogger.LogGenericWarning(Strings.ErrorUserInputRunningInHeadlessMode);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
await ConsoleSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
string result;
|
||||
|
||||
try {
|
||||
OnUserInputStart();
|
||||
|
||||
try {
|
||||
Console.Beep();
|
||||
|
||||
switch (userInputType) {
|
||||
case ASF.EUserInputType.DeviceID:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputDeviceID, botName));
|
||||
result = ConsoleReadLine();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Login:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamLogin, botName));
|
||||
result = ConsoleReadLine();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Password:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamPassword, botName));
|
||||
result = ConsoleReadLineMasked();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamGuard:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamGuard, botName));
|
||||
result = ConsoleReadLine();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamParentalCode:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamParentalCode, botName));
|
||||
result = ConsoleReadLineMasked();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.TwoFactorAuthentication:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteam2FA, botName));
|
||||
result = ConsoleReadLine();
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(userInputType), userInputType));
|
||||
Console.Write(Bot.FormatBotResponse(string.Format(Strings.UserInputUnknown, userInputType), botName));
|
||||
result = ConsoleReadLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Console.IsOutputRedirected) {
|
||||
Console.Clear(); // For security purposes
|
||||
}
|
||||
} catch (Exception e) {
|
||||
OnUserInputEnd();
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
OnUserInputEnd();
|
||||
} finally {
|
||||
ConsoleSemaphore.Release();
|
||||
}
|
||||
|
||||
return !string.IsNullOrEmpty(result) ? result.Trim() : null;
|
||||
}
|
||||
|
||||
internal static void InitCoreLoggers() {
|
||||
if (LogManager.Configuration != null) {
|
||||
IsUsingCustomConfiguration = true;
|
||||
@@ -105,42 +191,109 @@ namespace ArchiSteamFarm.NLog {
|
||||
ArchiKestrel.OnNewHistoryTarget(historyTarget);
|
||||
}
|
||||
|
||||
internal static void OnUserInputEnd() {
|
||||
IsWaitingForUserInput = false;
|
||||
internal static void StartInteractiveConsole() {
|
||||
if (ASF.GlobalConfig.SteamOwnerID == 0) {
|
||||
ASF.ArchiLogger.LogGenericWarning(string.Format(Strings.InteractiveConsoleNotAvailable, nameof(ASF.GlobalConfig.SteamOwnerID)));
|
||||
|
||||
if (ConsoleLoggingRules.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool reconfigure = false;
|
||||
|
||||
foreach (LoggingRule consoleLoggingRule in ConsoleLoggingRules.Where(consoleLoggingRule => !LogManager.Configuration.LoggingRules.Contains(consoleLoggingRule))) {
|
||||
LogManager.Configuration.LoggingRules.Add(consoleLoggingRule);
|
||||
reconfigure = true;
|
||||
Utilities.InBackground(HandleConsoleInteractively);
|
||||
ASF.ArchiLogger.LogGenericInfo(Strings.InteractiveConsoleEnabled);
|
||||
}
|
||||
|
||||
if (reconfigure) {
|
||||
LogManager.ReconfigExistingLoggers();
|
||||
private static string ConsoleReadLine() {
|
||||
Console.Beep();
|
||||
|
||||
return Console.ReadLine();
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
private static string ConsoleReadLineMasked(char mask = '*') {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
Console.Beep();
|
||||
|
||||
ConsoleKeyInfo keyInfo;
|
||||
|
||||
while ((keyInfo = Console.ReadKey(true)).Key != ConsoleKey.Enter) {
|
||||
if (!char.IsControl(keyInfo.KeyChar)) {
|
||||
result.Append(keyInfo.KeyChar);
|
||||
Console.Write(mask);
|
||||
} else if ((keyInfo.Key == ConsoleKey.Backspace) && (result.Length > 0)) {
|
||||
result.Length--;
|
||||
|
||||
if (Console.CursorLeft == 0) {
|
||||
Console.SetCursorPosition(Console.BufferWidth - 1, Console.CursorTop - 1);
|
||||
Console.Write(' ');
|
||||
Console.SetCursorPosition(Console.BufferWidth - 1, Console.CursorTop - 1);
|
||||
} else {
|
||||
// There are two \b characters here
|
||||
Console.Write(@" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void OnUserInputStart() {
|
||||
IsWaitingForUserInput = true;
|
||||
Console.WriteLine();
|
||||
|
||||
if (ConsoleLoggingRules.Count == 0) {
|
||||
return;
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
bool reconfigure = false;
|
||||
|
||||
foreach (LoggingRule consoleLoggingRule in ConsoleLoggingRules) {
|
||||
if (LogManager.Configuration.LoggingRules.Remove(consoleLoggingRule)) {
|
||||
reconfigure = true;
|
||||
}
|
||||
private static async Task HandleConsoleInteractively() {
|
||||
while (!Program.ShutdownSequenceInitialized) {
|
||||
try {
|
||||
if (IsWaitingForUserInput || !Console.KeyAvailable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (reconfigure) {
|
||||
LogManager.ReconfigExistingLoggers();
|
||||
await ConsoleSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
try {
|
||||
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
|
||||
|
||||
if (keyInfo.Key != ConsoleKey.C) {
|
||||
continue;
|
||||
}
|
||||
|
||||
OnUserInputStart();
|
||||
|
||||
try {
|
||||
Console.Write(@">> " + Strings.EnterCommand);
|
||||
string command = ConsoleReadLine();
|
||||
|
||||
if (string.IsNullOrEmpty(command)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Bot targetBot = Bot.Bots.OrderBy(bot => bot.Key).Select(bot => bot.Value).FirstOrDefault();
|
||||
|
||||
if (targetBot == null) {
|
||||
Console.WriteLine(@"<< " + Strings.ErrorNoBotsDefined);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine(@"<> " + Strings.Executing);
|
||||
|
||||
string response = await targetBot.Commands.Response(ASF.GlobalConfig.SteamOwnerID, command).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(response)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(response));
|
||||
Console.WriteLine(Strings.ErrorIsEmpty, nameof(response));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine(@"<< " + response);
|
||||
} finally {
|
||||
OnUserInputEnd();
|
||||
}
|
||||
} finally {
|
||||
ConsoleSemaphore.Release();
|
||||
}
|
||||
} finally {
|
||||
await Task.Delay(ConsoleResponsivenessDelay).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,5 +321,44 @@ namespace ArchiSteamFarm.NLog {
|
||||
HistoryTarget historyTarget = LogManager.Configuration.AllTargets.OfType<HistoryTarget>().FirstOrDefault();
|
||||
ArchiKestrel.OnNewHistoryTarget(historyTarget);
|
||||
}
|
||||
|
||||
private static void OnUserInputEnd() {
|
||||
IsWaitingForUserInput = false;
|
||||
|
||||
if (ConsoleLoggingRules.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool reconfigure = false;
|
||||
|
||||
foreach (LoggingRule consoleLoggingRule in ConsoleLoggingRules.Where(consoleLoggingRule => !LogManager.Configuration.LoggingRules.Contains(consoleLoggingRule))) {
|
||||
LogManager.Configuration.LoggingRules.Add(consoleLoggingRule);
|
||||
reconfigure = true;
|
||||
}
|
||||
|
||||
if (reconfigure) {
|
||||
LogManager.ReconfigExistingLoggers();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnUserInputStart() {
|
||||
IsWaitingForUserInput = true;
|
||||
|
||||
if (ConsoleLoggingRules.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool reconfigure = false;
|
||||
|
||||
foreach (LoggingRule consoleLoggingRule in ConsoleLoggingRules) {
|
||||
if (LogManager.Configuration.LoggingRules.Remove(consoleLoggingRule)) {
|
||||
reconfigure = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (reconfigure) {
|
||||
LogManager.ReconfigExistingLoggers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,15 +42,12 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal static bool ProcessRequired { get; private set; }
|
||||
internal static bool RestartAllowed { get; private set; } = true;
|
||||
|
||||
private static readonly object ConsoleLock = new object();
|
||||
internal static bool ShutdownSequenceInitialized { get; private set; }
|
||||
|
||||
// We need to keep this one assigned and not calculated on-demand
|
||||
private static readonly string ProcessFileName = Process.GetCurrentProcess().MainModule.FileName;
|
||||
|
||||
private static readonly TaskCompletionSource<byte> ShutdownResetEvent = new TaskCompletionSource<byte>();
|
||||
|
||||
private static bool ShutdownSequenceInitialized;
|
||||
private static bool SystemRequired;
|
||||
|
||||
internal static async Task Exit(byte exitCode = 0) {
|
||||
@@ -62,78 +59,6 @@ namespace ArchiSteamFarm {
|
||||
Environment.Exit(exitCode);
|
||||
}
|
||||
|
||||
internal static string GetUserInput(ASF.EUserInputType userInputType, string botName = SharedInfo.ASF) {
|
||||
if (userInputType == ASF.EUserInputType.Unknown) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ASF.GlobalConfig.Headless) {
|
||||
ASF.ArchiLogger.LogGenericWarning(Strings.ErrorUserInputRunningInHeadlessMode);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string result;
|
||||
|
||||
lock (ConsoleLock) {
|
||||
Logging.OnUserInputStart();
|
||||
|
||||
try {
|
||||
switch (userInputType) {
|
||||
case ASF.EUserInputType.DeviceID:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputDeviceID, botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Login:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamLogin, botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Password:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamPassword, botName));
|
||||
result = Utilities.ReadLineMasked();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamGuard:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamGuard, botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamParentalCode:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamParentalCode, botName));
|
||||
result = Utilities.ReadLineMasked();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.TwoFactorAuthentication:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteam2FA, botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(userInputType), userInputType));
|
||||
Console.Write(Bot.FormatBotResponse(string.Format(Strings.UserInputUnknown, userInputType), botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Console.IsOutputRedirected) {
|
||||
Console.Clear(); // For security purposes
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logging.OnUserInputEnd();
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Logging.OnUserInputEnd();
|
||||
}
|
||||
|
||||
return !string.IsNullOrEmpty(result) ? result.Trim() : null;
|
||||
}
|
||||
|
||||
internal static async Task Restart() {
|
||||
if (!await InitShutdownSequence().ConfigureAwait(false)) {
|
||||
return;
|
||||
@@ -200,7 +125,10 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private static async Task InitASF(IReadOnlyCollection<string> args) {
|
||||
ASF.ArchiLogger.LogGenericInfo(SharedInfo.PublicIdentifier + " V" + SharedInfo.Version + " (" + SharedInfo.BuildInfo.Variant + "/" + SharedInfo.ModuleVersion + " | " + OS.Variant + ")");
|
||||
string programIdentifier = SharedInfo.PublicIdentifier + " V" + SharedInfo.Version + " (" + SharedInfo.BuildInfo.Variant + "/" + SharedInfo.ModuleVersion + " | " + OS.Variant + ")";
|
||||
|
||||
Console.Title = programIdentifier;
|
||||
ASF.ArchiLogger.LogGenericInfo(programIdentifier);
|
||||
|
||||
await InitGlobalConfigAndLanguage().ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -265,34 +265,5 @@ namespace ArchiSteamFarm {
|
||||
return Random.Next();
|
||||
}
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
internal static string ReadLineMasked(char mask = '*') {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
ConsoleKeyInfo keyInfo;
|
||||
|
||||
while ((keyInfo = Console.ReadKey(true)).Key != ConsoleKey.Enter) {
|
||||
if (!char.IsControl(keyInfo.KeyChar)) {
|
||||
result.Append(keyInfo.KeyChar);
|
||||
Console.Write(mask);
|
||||
} else if ((keyInfo.Key == ConsoleKey.Backspace) && (result.Length > 0)) {
|
||||
result.Remove(result.Length - 1, 1);
|
||||
|
||||
if (Console.CursorLeft == 0) {
|
||||
Console.SetCursorPosition(Console.BufferWidth - 1, Console.CursorTop - 1);
|
||||
Console.Write(' ');
|
||||
Console.SetCursorPosition(Console.BufferWidth - 1, Console.CursorTop - 1);
|
||||
} else {
|
||||
// There are two \b characters here
|
||||
Console.Write(@" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user