diff --git a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs
index 00e79b613..255a3977e 100644
--- a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs
+++ b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs
@@ -35,7 +35,6 @@ using ArchiSteamFarm.IPC.Responses;
using ArchiSteamFarm.Localization;
using ArchiSteamFarm.Steam;
using ArchiSteamFarm.Steam.Integration.Callbacks;
-using ArchiSteamFarm.Steam.Security;
using ArchiSteamFarm.Steam.Storage;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
diff --git a/ArchiSteamFarm/IPC/Controllers/Api/TwoFactorAuthenticationController.cs b/ArchiSteamFarm/IPC/Controllers/Api/TwoFactorAuthenticationController.cs
index 024eb9d83..0ab71d234 100644
--- a/ArchiSteamFarm/IPC/Controllers/Api/TwoFactorAuthenticationController.cs
+++ b/ArchiSteamFarm/IPC/Controllers/Api/TwoFactorAuthenticationController.cs
@@ -39,64 +39,6 @@ using Microsoft.AspNetCore.Mvc;
namespace ArchiSteamFarm.IPC.Controllers.Api {
[Route("Api/Bot/{botNames:required}/TwoFactorAuthentication")]
public sealed class TwoFactorAuthenticationController : ArchiController {
- ///
- /// Deletes the MobileAuthenticator of given bots if an ASF 2FA module is active on them.
- ///
- [HttpDelete]
- [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.OK)]
- [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)]
- public async Task> AuthenticatorDelete(string botNames) {
- if (string.IsNullOrEmpty(botNames)) {
- throw new ArgumentNullException(nameof(botNames));
- }
-
- HashSet? bots = Bot.GetBots(botNames);
-
- if ((bots == null) || (bots.Count == 0)) {
- return BadRequest(new GenericResponse>>(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
- }
-
- IList<(bool Success, string? Message)> results = await Utilities.InParallel(bots.Select(static bot => Task.Run(bot.RemoveAuthenticator))).ConfigureAwait(false);
-
- Dictionary> result = new (bots.Count, Bot.BotsComparer);
-
- foreach (Bot bot in bots) {
- (bool success, string? message) = results[result.Count];
- result[bot.BotName] = new GenericResponse(success, message);
- }
-
- return Ok(new GenericResponse>>(result));
- }
-
- ///
- /// Imports a MobileAuthenticator into the ASF 2FA module of a given bot.
- ///
- [Consumes("application/json")]
- [HttpPost]
- [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.OK)]
- [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)]
- public ActionResult AuthenticatorPost(string botNames, [FromBody] MobileAuthenticator authenticator) {
- if (string.IsNullOrEmpty(botNames)) {
- throw new ArgumentNullException(nameof(botNames));
- }
-
- Bot? bot = Bot.GetBot(botNames);
-
- if (bot == null) {
- return BadRequest(new GenericResponse>>(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
- }
-
- if (authenticator == null) {
- throw new ArgumentNullException(nameof(authenticator));
- }
-
- if (bot.TryImportAuthenticator(authenticator)) {
- return Ok(new GenericResponse(true));
- }
-
- return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.WarningFailed)));
- }
-
///
/// Handles 2FA confirmations of given bots, requires ASF 2FA module to be active on them.
///
@@ -135,6 +77,69 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return Ok(new GenericResponse>>>(result));
}
+ ///
+ /// Deletes the MobileAuthenticator of given bots if an ASF 2FA module is active on them.
+ ///
+ [HttpDelete]
+ [ProducesResponseType(typeof(GenericResponse>>), (int) HttpStatusCode.OK)]
+ [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)]
+ public async Task> Delete(string botNames) {
+ if (string.IsNullOrEmpty(botNames)) {
+ throw new ArgumentNullException(nameof(botNames));
+ }
+
+ HashSet? bots = Bot.GetBots(botNames);
+
+ if ((bots == null) || (bots.Count == 0)) {
+ return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
+ }
+
+ IList<(bool Success, string? Message)> results = await Utilities.InParallel(bots.Select(static bot => Task.Run(bot.RemoveAuthenticator))).ConfigureAwait(false);
+
+ Dictionary> result = new(bots.Count, Bot.BotsComparer);
+
+ foreach (Bot bot in bots) {
+ (bool success, string? message) = results[result.Count];
+ result[bot.BotName] = new GenericResponse(success, message);
+ }
+
+ return Ok(new GenericResponse>>(result));
+ }
+
+ ///
+ /// Imports a MobileAuthenticator into the ASF 2FA module of a given bot.
+ ///
+ [Consumes("application/json")]
+ [HttpPost]
+ [ProducesResponseType(typeof(GenericResponse>), (int) HttpStatusCode.OK)]
+ [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)]
+ public async Task> Post(string botNames, [FromBody] MobileAuthenticator authenticator) {
+ if (string.IsNullOrEmpty(botNames)) {
+ throw new ArgumentNullException(nameof(botNames));
+ }
+
+ if (authenticator == null) {
+ throw new ArgumentNullException(nameof(authenticator));
+ }
+
+ HashSet? bots = Bot.GetBots(botNames);
+
+ if ((bots == null) || (bots.Count == 0)) {
+ return BadRequest(new GenericResponse>>(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
+ }
+
+ IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.TryImportAuthenticator(authenticator)))).ConfigureAwait(false);
+
+ Dictionary result = new(bots.Count, Bot.BotsComparer);
+
+ foreach (Bot bot in bots) {
+ bool success = results[result.Count];
+ result[bot.BotName] = new GenericResponse(success);
+ }
+
+ return Ok(new GenericResponse>(result));
+ }
+
///
/// Fetches 2FA tokens of given bots, requires ASF 2FA module to be active on them.
///
@@ -154,7 +159,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
IList<(bool Success, string? Token, string Message)> results = await Utilities.InParallel(bots.Select(static bot => bot.Actions.GenerateTwoFactorAuthenticationToken())).ConfigureAwait(false);
- Dictionary> result = new (bots.Count, Bot.BotsComparer);
+ Dictionary> result = new(bots.Count, Bot.BotsComparer);
foreach (Bot bot in bots) {
(bool success, string? token, string message) = results[result.Count];
diff --git a/ArchiSteamFarm/Steam/Bot.cs b/ArchiSteamFarm/Steam/Bot.cs
index 55e86375d..50a21957b 100644
--- a/ArchiSteamFarm/Steam/Bot.cs
+++ b/ArchiSteamFarm/Steam/Bot.cs
@@ -1568,6 +1568,19 @@ namespace ArchiSteamFarm.Steam {
bot.InitStart();
}
+ internal (bool Success, string? Message) RemoveAuthenticator() {
+ MobileAuthenticator? authenticator = BotDatabase.MobileAuthenticator;
+
+ if (authenticator == null) {
+ return (false, Strings.BotNoASFAuthenticator);
+ }
+
+ BotDatabase.MobileAuthenticator = null;
+ authenticator.Dispose();
+
+ return (true, null);
+ }
+
internal async Task Rename(string newBotName) {
if (string.IsNullOrEmpty(newBotName)) {
throw new ArgumentNullException(nameof(newBotName));
@@ -1685,6 +1698,29 @@ namespace ArchiSteamFarm.Steam {
}
}
+ internal bool TryImportAuthenticator(MobileAuthenticator authenticator) {
+ if (authenticator == null) {
+ throw new ArgumentNullException(nameof(authenticator));
+ }
+
+ if (HasMobileAuthenticator) {
+ return false;
+ }
+
+ try {
+ authenticator.Init(this);
+ BotDatabase.MobileAuthenticator = authenticator;
+ } catch (Exception e) {
+ ArchiLogger.LogGenericException(e);
+
+ return false;
+ }
+
+ ArchiLogger.LogGenericInfo(Strings.BotAuthenticatorImportFinished);
+
+ return true;
+ }
+
internal static IOrderedDictionary ValidateGamesToRedeemInBackground(IOrderedDictionary gamesToRedeemInBackground) {
if ((gamesToRedeemInBackground == null) || (gamesToRedeemInBackground.Count == 0)) {
throw new ArgumentNullException(nameof(gamesToRedeemInBackground));
@@ -1958,42 +1994,6 @@ namespace ArchiSteamFarm.Steam {
ArchiLogger.LogGenericInfo(Strings.BotAuthenticatorImportFinished);
}
- internal bool TryImportAuthenticator(MobileAuthenticator authenticator) {
- if (authenticator == null) {
- throw new ArgumentNullException(nameof(authenticator));
- }
-
- if (HasMobileAuthenticator) {
- return false;
- }
-
- try {
- authenticator.Init(this);
- BotDatabase.MobileAuthenticator = authenticator;
- } catch (Exception e) {
- ArchiLogger.LogGenericException(e);
-
- return false;
- }
-
- ArchiLogger.LogGenericInfo(Strings.BotAuthenticatorImportFinished);
-
- return true;
- }
-
- internal (bool Success, string? Message) RemoveAuthenticator() {
- MobileAuthenticator? authenticator = BotDatabase.MobileAuthenticator;
-
- if (authenticator == null) {
- return (false, Strings.BotNoASFAuthenticator);
- }
-
- BotDatabase.MobileAuthenticator = null;
- authenticator.Dispose();
-
- return (true, null);
- }
-
private void InitConnectionFailureTimer() {
if (ConnectionFailureTimer != null) {
return;