From 7a5a9c8a51a0cbfde286a085fd47b7ae4e994b33 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Mon, 10 Aug 2020 13:24:12 +0200 Subject: [PATCH] Enhance TwoFactorAuthentication/Confirmations IPC API by allowing to specify additional parameters --- .../IPC/Controllers/Api/BotController.cs | 16 ++-- ...actorAuthenticationConfirmationsRequest.cs | 80 +++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs diff --git a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs index bac92c5bf..cde4d5570 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs @@ -448,7 +448,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [HttpPost("{botNames:required}/TwoFactorAuthentication/Confirmations/Accept")] [ProducesResponseType(typeof(GenericResponse>), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] - public async Task> TwoFactorAuthenticationConfirmationsAcceptPost(string botNames) => await TwoFactorAuthenticationConfirmationsPost(botNames, true).ConfigureAwait(false); + public async Task> TwoFactorAuthenticationConfirmationsAcceptPost(string botNames, [FromBody] TwoFactorAuthenticationConfirmationsRequest request) => await TwoFactorAuthenticationConfirmationsPost(botNames, request, true).ConfigureAwait(false); /// /// Denies 2FA confirmations of given bots, requires ASF 2FA module to be active on them. @@ -456,7 +456,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [HttpPost("{botNames:required}/TwoFactorAuthentication/Confirmations/Cancel")] [ProducesResponseType(typeof(GenericResponse>), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] - public async Task> TwoFactorAuthenticationConfirmationsCancelPost(string botNames) => await TwoFactorAuthenticationConfirmationsPost(botNames, false).ConfigureAwait(false); + public async Task> TwoFactorAuthenticationConfirmationsCancelPost(string botNames, [FromBody] TwoFactorAuthenticationConfirmationsRequest request) => await TwoFactorAuthenticationConfirmationsPost(botNames, request, false).ConfigureAwait(false); /// /// Fetches 2FA tokens of given bots, requires ASF 2FA module to be active on them. @@ -489,11 +489,15 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { return Ok(new GenericResponse>>(result)); } - private async Task> TwoFactorAuthenticationConfirmationsPost(string botNames, bool accept) { - if (string.IsNullOrEmpty(botNames)) { + private async Task> TwoFactorAuthenticationConfirmationsPost(string botNames, TwoFactorAuthenticationConfirmationsRequest request, bool accept) { + if (string.IsNullOrEmpty(botNames) || (request == null)) { ASF.ArchiLogger.LogNullError(nameof(botNames)); - return BadRequest(new GenericResponse>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames)))); + return BadRequest(new GenericResponse>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames) + " || " + nameof(request)))); + } + + if (request.AcceptedType.HasValue && ((request.AcceptedType.Value == MobileAuthenticator.Confirmation.EType.Unknown) || !Enum.IsDefined(typeof(MobileAuthenticator.Confirmation.EType), request.AcceptedType.Value))) { + return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, nameof(request.AcceptedType)))); } HashSet bots = Bot.GetBots(botNames); @@ -502,7 +506,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { return BadRequest(new GenericResponse>(false, string.Format(Strings.BotNotFound, botNames))); } - IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => bot.Actions.HandleTwoFactorAuthenticationConfirmations(accept))).ConfigureAwait(false); + IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => bot.Actions.HandleTwoFactorAuthenticationConfirmations(accept, request.AcceptedType, request.AcceptedCreatorIDs.Count > 0 ? request.AcceptedCreatorIDs : null, request.WaitIfNeeded))).ConfigureAwait(false); Dictionary result = new Dictionary(bots.Count, Bot.BotsComparer); diff --git a/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs b/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs new file mode 100644 index 000000000..37d56dd72 --- /dev/null +++ b/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs @@ -0,0 +1,80 @@ +// _ _ _ ____ _ _____ +// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ +// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ +// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | +// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| +// | +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using ArchiSteamFarm.Localization; +using Newtonsoft.Json; + +namespace ArchiSteamFarm.IPC.Requests { + [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] + public sealed class TwoFactorAuthenticationConfirmationsRequest { + /// + /// Specifies the accepted type of confirmations to handle. If not provided, all confirmation types are considered for an action. + /// + [JsonProperty(Required = Required.DisallowNull)] + public readonly MobileAuthenticator.Confirmation.EType? AcceptedType; + + /// + /// Specifies whether we should wait for the confirmations to arrive, in case they're not available immediately. This option makes sense only if is specified as well, and in this case ASF will add a few more tries if needed to ensure that all specified IDs are handled. Useful if confirmations are generated with a delay on Steam network side, which happens fairly often. + /// + [JsonProperty(Required = Required.DisallowNull)] + public readonly bool WaitIfNeeded; + + /// + /// Specifies IDs of the confirmations that we're supposed to handle. CreatorID of the confirmation is equal to ID of the object that triggered it - e.g. ID of the trade offer, or ID of market listing. If not provided, or empty array, all confirmation IDs are considered for an action. + /// + [JsonProperty(Required = Required.DisallowNull)] + public ImmutableHashSet AcceptedCreatorIDs { get; private set; } + + /// + /// A helper property which works the same as but with values written as strings - for javascript compatibility purposes. Use either this one, or , not both. + /// + [JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(AcceptedCreatorIDs), Required = Required.DisallowNull)] + private ImmutableHashSet SAcceptedCreatorIDs { + set { + if (value == null) { + ASF.ArchiLogger.LogNullError(nameof(value)); + + return; + } + + HashSet acceptedCreatorIDs = new HashSet(value.Count); + + foreach (string creatorIDText in value) { + if (!ulong.TryParse(creatorIDText, out ulong creatorID) || (creatorID == 0)) { + ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, nameof(SAcceptedCreatorIDs))); + + return; + } + + acceptedCreatorIDs.Add(creatorID); + } + + AcceptedCreatorIDs = acceptedCreatorIDs.ToImmutableHashSet(); + } + } + + [JsonConstructor] + private TwoFactorAuthenticationConfirmationsRequest() { } + } +}