mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-10 15:14:41 +00:00
Add /Api/{Bots}/Input endpoint
Makes https://github.com/JustArchiNET/ASF-ui/issues/888 (and similar actions) possible
This commit is contained in:
parent
d9355ceab0
commit
a5d85a211d
6 changed files with 140 additions and 43 deletions
|
@ -877,7 +877,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
[PublicAPI]
|
||||
public enum EUserInputType : byte {
|
||||
Unknown,
|
||||
None,
|
||||
DeviceID,
|
||||
Login,
|
||||
Password,
|
||||
|
|
|
@ -94,6 +94,7 @@ namespace ArchiSteamFarm {
|
|||
[PublicAPI]
|
||||
public uint GamesToRedeemInBackgroundCount => BotDatabase?.GamesToRedeemInBackgroundCount ?? 0;
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public bool HasMobileAuthenticator => BotDatabase?.MobileAuthenticator != null;
|
||||
|
||||
|
@ -153,23 +154,34 @@ namespace ArchiSteamFarm {
|
|||
#pragma warning restore IDE0051
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public EAccountFlags AccountFlags { get; private set; }
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public BotConfig BotConfig { get; private set; }
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public bool KeepRunning { get; private set; }
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public string Nickname { get; private set; }
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public ASF.EUserInputType RequiredInput { get; private set; }
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public ulong SteamID { get; private set; }
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public long WalletBalance { get; private set; }
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public ECurrencyCode WalletCurrency { get; private set; }
|
||||
|
||||
|
@ -477,11 +489,11 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
[PublicAPI]
|
||||
public void SetUserInput(ASF.EUserInputType inputType, string inputValue) {
|
||||
if ((inputType == ASF.EUserInputType.Unknown) || !Enum.IsDefined(typeof(ASF.EUserInputType), inputType) || string.IsNullOrEmpty(inputValue)) {
|
||||
public bool SetUserInput(ASF.EUserInputType inputType, string inputValue) {
|
||||
if ((inputType == ASF.EUserInputType.None) || !Enum.IsDefined(typeof(ASF.EUserInputType), inputType) || string.IsNullOrEmpty(inputValue)) {
|
||||
ArchiLogger.LogNullError(nameof(inputType) + " || " + nameof(inputValue));
|
||||
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// This switch should cover ONLY bot properties
|
||||
|
@ -491,26 +503,32 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
case ASF.EUserInputType.Login:
|
||||
if (BotConfig != null) {
|
||||
BotConfig.SteamLogin = inputValue;
|
||||
if (BotConfig == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BotConfig.SteamLogin = inputValue;
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Password:
|
||||
if (BotConfig != null) {
|
||||
BotConfig.DecryptedSteamPassword = inputValue;
|
||||
if (BotConfig == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BotConfig.DecryptedSteamPassword = inputValue;
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamGuard:
|
||||
AuthCode = inputValue;
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamParentalCode:
|
||||
if (BotConfig != null) {
|
||||
BotConfig.SteamParentalCode = inputValue;
|
||||
if (BotConfig == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BotConfig.SteamParentalCode = inputValue;
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.TwoFactorAuthentication:
|
||||
TwoFactorCode = inputValue;
|
||||
|
@ -521,6 +539,12 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
if (RequiredInput == inputType) {
|
||||
RequiredInput = ASF.EUserInputType.None;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void AddGamesToRedeemInBackground(IOrderedDictionary gamesToRedeemInBackground) {
|
||||
|
@ -1733,13 +1757,13 @@ namespace ArchiSteamFarm {
|
|||
ArchiLogger.LogGenericWarning(Strings.BotAuthenticatorInvalidDeviceID);
|
||||
|
||||
if (string.IsNullOrEmpty(DeviceID)) {
|
||||
RequiredInput = ASF.EUserInputType.DeviceID;
|
||||
|
||||
string deviceID = await Logging.GetUserInput(ASF.EUserInputType.DeviceID, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(deviceID)) {
|
||||
if (string.IsNullOrEmpty(deviceID) || !SetUserInput(ASF.EUserInputType.DeviceID, deviceID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetUserInput(ASF.EUserInputType.DeviceID, deviceID);
|
||||
}
|
||||
|
||||
if (!MobileAuthenticator.IsValidDeviceID(DeviceID)) {
|
||||
|
@ -1789,23 +1813,23 @@ namespace ArchiSteamFarm {
|
|||
|
||||
private async Task<bool> InitLoginAndPassword(bool requiresPassword) {
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamLogin)) {
|
||||
RequiredInput = ASF.EUserInputType.Login;
|
||||
|
||||
string steamLogin = await Logging.GetUserInput(ASF.EUserInputType.Login, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(steamLogin)) {
|
||||
if (string.IsNullOrEmpty(steamLogin) || !SetUserInput(ASF.EUserInputType.Login, steamLogin)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SetUserInput(ASF.EUserInputType.Login, steamLogin);
|
||||
}
|
||||
|
||||
if (requiresPassword && string.IsNullOrEmpty(BotConfig.DecryptedSteamPassword)) {
|
||||
RequiredInput = ASF.EUserInputType.Password;
|
||||
|
||||
string steamPassword = await Logging.GetUserInput(ASF.EUserInputType.Password, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(steamPassword)) {
|
||||
if (string.IsNullOrEmpty(steamPassword) || !SetUserInput(ASF.EUserInputType.Password, steamPassword)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SetUserInput(ASF.EUserInputType.Password, steamPassword);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1815,6 +1839,7 @@ namespace ArchiSteamFarm {
|
|||
AccountFlags = EAccountFlags.NormalUser;
|
||||
AvatarHash = Nickname = null;
|
||||
MasterChatGroupID = 0;
|
||||
RequiredInput = ASF.EUserInputType.None;
|
||||
WalletBalance = 0;
|
||||
WalletCurrency = ECurrencyCode.Invalid;
|
||||
|
||||
|
@ -2406,28 +2431,24 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
case EResult.AccountLogonDenied:
|
||||
RequiredInput = ASF.EUserInputType.SteamGuard;
|
||||
|
||||
string authCode = await Logging.GetUserInput(ASF.EUserInputType.SteamGuard, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(authCode)) {
|
||||
if (string.IsNullOrEmpty(authCode) || !SetUserInput(ASF.EUserInputType.SteamGuard, authCode)) {
|
||||
Stop();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
SetUserInput(ASF.EUserInputType.SteamGuard, authCode);
|
||||
|
||||
break;
|
||||
case EResult.AccountLoginDeniedNeedTwoFactor:
|
||||
if (!HasMobileAuthenticator) {
|
||||
RequiredInput = ASF.EUserInputType.TwoFactorAuthentication;
|
||||
|
||||
string twoFactorCode = await Logging.GetUserInput(ASF.EUserInputType.TwoFactorAuthentication, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(twoFactorCode)) {
|
||||
if (string.IsNullOrEmpty(twoFactorCode) || !SetUserInput(ASF.EUserInputType.TwoFactorAuthentication, twoFactorCode)) {
|
||||
Stop();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
SetUserInput(ASF.EUserInputType.TwoFactorAuthentication, twoFactorCode);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2474,32 +2495,36 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!string.IsNullOrEmpty(steamParentalCode)) {
|
||||
if (BotConfig.SteamParentalCode != steamParentalCode) {
|
||||
SetUserInput(ASF.EUserInputType.SteamParentalCode, steamParentalCode);
|
||||
}
|
||||
} else if (string.IsNullOrEmpty(BotConfig.SteamParentalCode) || (BotConfig.SteamParentalCode.Length != BotConfig.SteamParentalCodeLength)) {
|
||||
steamParentalCode = await Logging.GetUserInput(ASF.EUserInputType.SteamParentalCode, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(steamParentalCode) || (steamParentalCode.Length != BotConfig.SteamParentalCodeLength)) {
|
||||
if (!SetUserInput(ASF.EUserInputType.SteamParentalCode, steamParentalCode)) {
|
||||
Stop();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (string.IsNullOrEmpty(BotConfig.SteamParentalCode) || (BotConfig.SteamParentalCode.Length != BotConfig.SteamParentalCodeLength)) {
|
||||
RequiredInput = ASF.EUserInputType.SteamParentalCode;
|
||||
|
||||
SetUserInput(ASF.EUserInputType.SteamParentalCode, steamParentalCode);
|
||||
steamParentalCode = await Logging.GetUserInput(ASF.EUserInputType.SteamParentalCode, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(steamParentalCode) || (steamParentalCode.Length != BotConfig.SteamParentalCodeLength) || !SetUserInput(ASF.EUserInputType.SteamParentalCode, steamParentalCode)) {
|
||||
Stop();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SteamParentalActive = false;
|
||||
}
|
||||
} else if (SteamParentalActive && !string.IsNullOrEmpty(BotConfig.SteamParentalCode) && (BotConfig.SteamParentalCode.Length != BotConfig.SteamParentalCodeLength)) {
|
||||
RequiredInput = ASF.EUserInputType.SteamParentalCode;
|
||||
|
||||
string steamParentalCode = await Logging.GetUserInput(ASF.EUserInputType.SteamParentalCode, BotName).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(steamParentalCode) || (steamParentalCode.Length != BotConfig.SteamParentalCodeLength)) {
|
||||
if (string.IsNullOrEmpty(steamParentalCode) || (steamParentalCode.Length != BotConfig.SteamParentalCodeLength) || !SetUserInput(ASF.EUserInputType.SteamParentalCode, steamParentalCode)) {
|
||||
Stop();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
SetUserInput(ASF.EUserInputType.SteamParentalCode, steamParentalCode);
|
||||
}
|
||||
|
||||
ArchiWebHandler.OnVanityURLChanged(callback.VanityURL);
|
||||
|
|
|
@ -1416,7 +1416,7 @@ namespace ArchiSteamFarm {
|
|||
return FormatBotResponse(Strings.ErrorFunctionOnlyInHeadlessMode);
|
||||
}
|
||||
|
||||
if (!Enum.TryParse(propertyName, true, out ASF.EUserInputType inputType) || (inputType == ASF.EUserInputType.Unknown) || !Enum.IsDefined(typeof(ASF.EUserInputType), inputType)) {
|
||||
if (!Enum.TryParse(propertyName, true, out ASF.EUserInputType inputType) || (inputType == ASF.EUserInputType.None) || !Enum.IsDefined(typeof(ASF.EUserInputType), inputType)) {
|
||||
return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(inputType)));
|
||||
}
|
||||
|
||||
|
|
|
@ -242,6 +242,35 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
return Ok(new GenericResponse<IReadOnlyDictionary<string, IOrderedDictionary>>(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides input value to given bot for next usage.
|
||||
/// </summary>
|
||||
[Consumes("application/json")]
|
||||
[HttpPost("{botNames:required}/Input")]
|
||||
[ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)]
|
||||
public async Task<ActionResult<GenericResponse>> InputPost(string botNames, [FromBody] BotInputRequest request) {
|
||||
if (string.IsNullOrEmpty(botNames) || (request == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames) + " || " + nameof(request));
|
||||
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames) + " || " + nameof(request))));
|
||||
}
|
||||
|
||||
if ((request.Type == ASF.EUserInputType.None) || !Enum.IsDefined(typeof(ASF.EUserInputType), request.Type) || string.IsNullOrEmpty(request.Value)) {
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, nameof(request.Type) + " || " + nameof(request.Value))));
|
||||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
||||
IList<bool> results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.SetUserInput(request.Type, request.Value)))).ConfigureAwait(false);
|
||||
|
||||
return Ok(results.All(result => result) ? new GenericResponse(true) : new GenericResponse(false, Strings.WarningFailed));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses given bots.
|
||||
/// </summary>
|
||||
|
|
43
ArchiSteamFarm/IPC/Requests/BotInputRequest.cs
Normal file
43
ArchiSteamFarm/IPC/Requests/BotInputRequest.cs
Normal file
|
@ -0,0 +1,43 @@
|
|||
// _ _ _ ____ _ _____
|
||||
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// |
|
||||
// Copyright 2015-2020 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
// |
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// |
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// |
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm.IPC.Requests {
|
||||
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
|
||||
public sealed class BotInputRequest {
|
||||
/// <summary>
|
||||
/// Specifies the type of the input.
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public readonly ASF.EUserInputType Type;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the value for given input type (declared in <see cref="Type" />)
|
||||
/// </summary>
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public readonly string Value;
|
||||
|
||||
[JsonConstructor]
|
||||
private BotInputRequest() { }
|
||||
}
|
||||
}
|
|
@ -65,7 +65,9 @@ namespace ArchiSteamFarm.NLog {
|
|||
}
|
||||
|
||||
internal static async Task<string> GetUserInput(ASF.EUserInputType userInputType, string botName = SharedInfo.ASF) {
|
||||
if (userInputType == ASF.EUserInputType.Unknown) {
|
||||
if ((userInputType == ASF.EUserInputType.None) || !Enum.IsDefined(typeof(ASF.EUserInputType), userInputType) || string.IsNullOrEmpty(botName)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(userInputType) + " || " + nameof(botName));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -118,10 +120,8 @@ namespace ArchiSteamFarm.NLog {
|
|||
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;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Console.IsOutputRedirected) {
|
||||
|
@ -132,9 +132,9 @@ namespace ArchiSteamFarm.NLog {
|
|||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
} finally {
|
||||
OnUserInputEnd();
|
||||
}
|
||||
} finally {
|
||||
ConsoleSemaphore.Release();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue