From 60ae4977dacf1fed33e4956f1a70cc539eb8c8db Mon Sep 17 00:00:00 2001 From: JustArchi Date: Wed, 11 Nov 2020 16:51:31 +0100 Subject: [PATCH] Initial code cleanup --- ArchiSteamFarm.sln.DotSettings | 2 +- ArchiSteamFarm/ArchiSteamFarm.csproj | 1 + .../Collections/ConcurrentEnumerator.cs | 12 +- .../Collections/ConcurrentHashSet.cs | 22 +++- ArchiSteamFarm/Helpers/ArchiCacheable.cs | 3 +- .../Helpers/CrossProcessFileBasedSemaphore.cs | 6 +- ArchiSteamFarm/Helpers/SerializableFile.cs | 6 +- .../IPC/Controllers/Api/ASFController.cs | 17 ++- .../IPC/Controllers/Api/BotController.cs | 111 ++++++++++++------ .../IPC/Controllers/Api/CommandController.cs | 7 +- .../IPC/Controllers/Api/NLogController.cs | 35 ++++-- .../IPC/Controllers/Api/PluginsController.cs | 3 +- .../Controllers/Api/StructureController.cs | 5 +- .../IPC/Controllers/Api/TypeController.cs | 7 +- .../IPC/Controllers/Api/WWWController.cs | 25 ++-- .../ApiAuthenticationMiddleware.cs | 10 +- .../IPC/Integration/EnumSchemaFilter.cs | 17 ++- .../IPC/Requests/ASFEncryptRequest.cs | 4 +- ArchiSteamFarm/IPC/Requests/ASFHashRequest.cs | 4 +- ArchiSteamFarm/IPC/Requests/ASFRequest.cs | 2 +- .../BotGamesToRedeemInBackgroundRequest.cs | 2 +- .../IPC/Requests/BotInputRequest.cs | 4 +- .../IPC/Requests/BotPauseRequest.cs | 4 +- .../IPC/Requests/BotRedeemRequest.cs | 2 +- .../IPC/Requests/BotRenameRequest.cs | 2 +- ArchiSteamFarm/IPC/Requests/BotRequest.cs | 2 +- ArchiSteamFarm/IPC/Requests/CommandRequest.cs | 2 +- ...actorAuthenticationConfirmationsRequest.cs | 9 +- ArchiSteamFarm/IPC/Requests/WWWSendRequest.cs | 2 +- ArchiSteamFarm/IPC/Responses/ASFResponse.cs | 26 ++-- .../GamesToRedeemInBackgroundResponse.cs | 4 +- .../IPC/Responses/GenericResponse.cs | 6 +- .../IPC/Responses/GitHubReleaseResponse.cs | 8 +- ArchiSteamFarm/IPC/Responses/TypeResponse.cs | 21 ++-- ArchiSteamFarm/IPC/Startup.cs | 15 ++- 35 files changed, 254 insertions(+), 154 deletions(-) diff --git a/ArchiSteamFarm.sln.DotSettings b/ArchiSteamFarm.sln.DotSettings index edd59a4af..9a909bdea 100644 --- a/ArchiSteamFarm.sln.DotSettings +++ b/ArchiSteamFarm.sln.DotSettings @@ -278,7 +278,7 @@ WARNING WARNING WARNING - PESSIMISTIC + <?xml version="1.0" encoding="utf-16"?><Profile name="Archi"><CSReorderTypeMembers>True</CSReorderTypeMembers><AspOptimizeRegisterDirectives>True</AspOptimizeRegisterDirectives><HtmlReformatCode>True</HtmlReformatCode><JsInsertSemicolon>True</JsInsertSemicolon><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><VariablesToInnerScopesDescriptor>True</VariablesToInnerScopesDescriptor><StringToTemplatesDescriptor>True</StringToTemplatesDescriptor><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs><OptimizeReferenceCommentsTs>True</OptimizeReferenceCommentsTs><PublicModifierStyleTs>True</PublicModifierStyleTs><ExplicitAnyTs>True</ExplicitAnyTs><TypeAnnotationStyleTs>True</TypeAnnotationStyleTs><RelativePathStyleTs>True</RelativePathStyleTs><AsInsteadOfCastTs>True</AsInsteadOfCastTs><XMLReformatCode>True</XMLReformatCode><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeArgumentsStyle="True" ArrangeCodeBodyStyle="True" ArrangeVarStyle="True" /><RemoveCodeRedundanciesVB>True</RemoveCodeRedundanciesVB><CssAlphabetizeProperties>True</CssAlphabetizeProperties><VBOptimizeImports>True</VBOptimizeImports><VBShortenReferences>True</VBShortenReferences><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CssReformatCode>True</CssReformatCode><VBReformatCode>True</VBReformatCode><VBFormatDocComments>True</VBFormatDocComments><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile> Archi USE_TABS_ONLY diff --git a/ArchiSteamFarm/ArchiSteamFarm.csproj b/ArchiSteamFarm/ArchiSteamFarm.csproj index 471561b8d..7c50e0a1b 100644 --- a/ArchiSteamFarm/ArchiSteamFarm.csproj +++ b/ArchiSteamFarm/ArchiSteamFarm.csproj @@ -4,6 +4,7 @@ true false Exe + 9 diff --git a/ArchiSteamFarm/Collections/ConcurrentEnumerator.cs b/ArchiSteamFarm/Collections/ConcurrentEnumerator.cs index 8cb0bd8ab..b09426e99 100644 --- a/ArchiSteamFarm/Collections/ConcurrentEnumerator.cs +++ b/ArchiSteamFarm/Collections/ConcurrentEnumerator.cs @@ -28,22 +28,22 @@ namespace ArchiSteamFarm.Collections { public T Current => Enumerator.Current; private readonly IEnumerator Enumerator; - private readonly IDisposable Lock; + private readonly IDisposable LockObject; object? IEnumerator.Current => Current; - internal ConcurrentEnumerator(IReadOnlyCollection collection, IDisposable @lock) { - if ((collection == null) || (@lock == null)) { - throw new ArgumentNullException(nameof(collection) + " || " + nameof(@lock)); + internal ConcurrentEnumerator(IReadOnlyCollection collection, IDisposable lockObject) { + if (collection == null) { + throw new ArgumentNullException(nameof(collection)); } - Lock = @lock; + LockObject = lockObject ?? throw new ArgumentNullException(nameof(lockObject)); Enumerator = collection.GetEnumerator(); } public void Dispose() { Enumerator.Dispose(); - Lock.Dispose(); + LockObject.Dispose(); } public bool MoveNext() => Enumerator.MoveNext(); diff --git a/ArchiSteamFarm/Collections/ConcurrentHashSet.cs b/ArchiSteamFarm/Collections/ConcurrentHashSet.cs index 33098f1cd..b2970f4f8 100644 --- a/ArchiSteamFarm/Collections/ConcurrentHashSet.cs +++ b/ArchiSteamFarm/Collections/ConcurrentHashSet.cs @@ -128,13 +128,27 @@ namespace ArchiSteamFarm.Collections { IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - // We use Count() and not Any() because we must ensure full loop pass [PublicAPI] - public bool AddRange(IEnumerable items) => items.Count(Add) > 0; + public bool AddRange(IEnumerable items) { + bool result = false; + + foreach (T _ in items.Where(Add)) { + result = true; + } + + return result; + } - // We use Count() and not Any() because we must ensure full loop pass [PublicAPI] - public bool RemoveRange(IEnumerable items) => items.Count(Remove) > 0; + public bool RemoveRange(IEnumerable items) { + bool result = false; + + foreach (T _ in items.Where(Remove)) { + result = true; + } + + return result; + } [PublicAPI] public bool ReplaceIfNeededWith(IReadOnlyCollection other) { diff --git a/ArchiSteamFarm/Helpers/ArchiCacheable.cs b/ArchiSteamFarm/Helpers/ArchiCacheable.cs index fee71dba2..f15bb38ff 100644 --- a/ArchiSteamFarm/Helpers/ArchiCacheable.cs +++ b/ArchiSteamFarm/Helpers/ArchiCacheable.cs @@ -20,6 +20,7 @@ // limitations under the License. using System; +using System.Globalization; using System.Threading; using System.Threading.Tasks; using ArchiSteamFarm.Localization; @@ -73,7 +74,7 @@ namespace ArchiSteamFarm.Helpers { case EFallback.SuccessPreviously: return (false, InitializedValue); default: - ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(fallback), fallback)); + ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(fallback), fallback)); goto case EFallback.DefaultForType; } diff --git a/ArchiSteamFarm/Helpers/CrossProcessFileBasedSemaphore.cs b/ArchiSteamFarm/Helpers/CrossProcessFileBasedSemaphore.cs index 581cefbac..303f1a2b4 100644 --- a/ArchiSteamFarm/Helpers/CrossProcessFileBasedSemaphore.cs +++ b/ArchiSteamFarm/Helpers/CrossProcessFileBasedSemaphore.cs @@ -55,7 +55,7 @@ namespace ArchiSteamFarm.Helpers { void ICrossProcessSemaphore.Release() { lock (LocalSemaphore) { if (FileLock == null) { - throw new ArgumentNullException(nameof(FileLock)); + throw new InvalidOperationException(nameof(FileLock)); } FileLock.Dispose(); @@ -75,7 +75,7 @@ namespace ArchiSteamFarm.Helpers { try { lock (LocalSemaphore) { if (FileLock != null) { - throw new ArgumentNullException(nameof(FileLock)); + throw new InvalidOperationException(nameof(FileLock)); } EnsureFileExists(); @@ -120,7 +120,7 @@ namespace ArchiSteamFarm.Helpers { try { lock (LocalSemaphore) { if (FileLock != null) { - throw new ArgumentNullException(nameof(FileLock)); + throw new InvalidOperationException(nameof(FileLock)); } EnsureFileExists(); diff --git a/ArchiSteamFarm/Helpers/SerializableFile.cs b/ArchiSteamFarm/Helpers/SerializableFile.cs index 0cba805e6..d1ce4d41e 100644 --- a/ArchiSteamFarm/Helpers/SerializableFile.cs +++ b/ArchiSteamFarm/Helpers/SerializableFile.cs @@ -34,7 +34,11 @@ namespace ArchiSteamFarm.Helpers { private bool ReadOnly; private bool SavingScheduled; - public virtual void Dispose() => FileSemaphore.Dispose(); + public virtual void Dispose() { + FileSemaphore.Dispose(); + + GC.SuppressFinalize(this); + } protected async Task Save() { if (string.IsNullOrEmpty(FilePath)) { diff --git a/ArchiSteamFarm/IPC/Controllers/Api/ASFController.cs b/ArchiSteamFarm/IPC/Controllers/Api/ASFController.cs index 8a65b3828..ab5409442 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/ASFController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/ASFController.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Threading.Tasks; @@ -46,7 +47,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { } if (string.IsNullOrEmpty(request.StringToEncrypt)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(request.StringToEncrypt)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(request.StringToEncrypt)))); } string? encryptedString = Actions.Encrypt(request.CryptoMethod, request.StringToEncrypt!); @@ -84,7 +85,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { } if (string.IsNullOrEmpty(request.StringToHash)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(request.StringToHash)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(request.StringToHash)))); } string hash = Actions.Hash(request.HashingMethod, request.StringToHash!); @@ -100,12 +101,16 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] public async Task> ASFPost([FromBody] ASFRequest request) { - if ((request == null) || (ASF.GlobalConfig == null)) { - throw new ArgumentNullException(nameof(request) + " || " + nameof(ASF.GlobalConfig)); + if (request == null) { + throw new ArgumentNullException(nameof(request)); + } + + if (ASF.GlobalConfig == null) { + throw new InvalidOperationException(nameof(ASF.GlobalConfig)); } if (request.GlobalConfig == null) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(request.GlobalConfig)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(request.GlobalConfig)))); } (bool valid, string? errorMessage) = request.GlobalConfig.CheckValidation(); @@ -137,7 +142,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { if (string.IsNullOrEmpty(filePath)) { ASF.ArchiLogger.LogNullError(filePath); - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, nameof(filePath)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(filePath)))); } bool result = await GlobalConfig.Write(filePath, request.GlobalConfig).ConfigureAwait(false); diff --git a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs index 7d925fe01..a6009a4d5 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Globalization; using System.Linq; using System.Net; using System.Threading.Tasks; @@ -48,7 +49,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList results = await Utilities.InParallel(bots.Select(bot => bot.DeleteAllRelatedFiles())).ConfigureAwait(false); @@ -70,7 +71,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { HashSet? bots = Bot.GetBots(botNames); if (bots == null) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, nameof(bots)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(bots)))); } return Ok(new GenericResponse>(bots.Where(bot => !string.IsNullOrEmpty(bot.BotName)).ToDictionary(bot => bot.BotName, bot => bot, Bot.BotsComparer)!)); @@ -84,12 +85,20 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(GenericResponse>), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] public async Task> BotPost(string botNames, [FromBody] BotRequest request) { - if (string.IsNullOrEmpty(botNames) || (request == null) || (Bot.Bots == null)) { - throw new ArgumentNullException(nameof(botNames) + " || " + nameof(request) + " || " + nameof(Bot.Bots)); + if (string.IsNullOrEmpty(botNames)) { + throw new ArgumentNullException(nameof(botNames)); + } + + if (request == null) { + throw new ArgumentNullException(nameof(request)); + } + + if (Bot.Bots == null) { + throw new InvalidOperationException(nameof(Bot.Bots)); } if (request.BotConfig == null) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(request.BotConfig)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(request.BotConfig)))); } (bool valid, string? errorMessage) = request.BotConfig.CheckValidation(); @@ -120,7 +129,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { request.BotConfig.SteamParentalCode = bot.BotConfig.SteamParentalCode; } - if ((bot.BotConfig.AdditionalProperties != null) && (bot.BotConfig.AdditionalProperties.Count > 0)) { + if (bot.BotConfig.AdditionalProperties?.Count > 0) { request.BotConfig.AdditionalProperties ??= new Dictionary(bot.BotConfig.AdditionalProperties.Count, bot.BotConfig.AdditionalProperties.Comparer); foreach ((string key, JToken value) in bot.BotConfig.AdditionalProperties.Where(property => !request.BotConfig.AdditionalProperties.ContainsKey(property.Key))) { @@ -136,7 +145,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { if (string.IsNullOrEmpty(filePath)) { ASF.ArchiLogger.LogNullError(filePath); - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, nameof(filePath)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(filePath)))); } result[botName] = await BotConfig.Write(filePath, request.BotConfig).ConfigureAwait(false); @@ -159,7 +168,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.DeleteRedeemedKeysFiles))).ConfigureAwait(false); @@ -181,7 +190,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList<(Dictionary? UnusedKeys, Dictionary? UsedKeys)> results = await Utilities.InParallel(bots.Select(bot => bot.GetUsedAndUnusedKeys())).ConfigureAwait(false); @@ -204,24 +213,28 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(GenericResponse>), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] public async Task> GamesToRedeemInBackgroundPost(string botNames, [FromBody] BotGamesToRedeemInBackgroundRequest request) { - if (string.IsNullOrEmpty(botNames) || (request == null)) { - throw new ArgumentNullException(nameof(botNames) + " || " + nameof(request)); + if (string.IsNullOrEmpty(botNames)) { + throw new ArgumentNullException(nameof(botNames)); + } + + if (request == null) { + throw new ArgumentNullException(nameof(request)); } if ((request.GamesToRedeemInBackground == null) || (request.GamesToRedeemInBackground.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(request.GamesToRedeemInBackground)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(request.GamesToRedeemInBackground)))); } HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IOrderedDictionary validGamesToRedeemInBackground = Bot.ValidateGamesToRedeemInBackground(request.GamesToRedeemInBackground); if (validGamesToRedeemInBackground.Count == 0) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(validGamesToRedeemInBackground)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(validGamesToRedeemInBackground)))); } await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.AddGamesToRedeemInBackground(validGamesToRedeemInBackground)))).ConfigureAwait(false); @@ -243,18 +256,22 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] public async Task> InputPost(string botNames, [FromBody] BotInputRequest request) { - if (string.IsNullOrEmpty(botNames) || (request == null)) { - throw new ArgumentNullException(nameof(botNames) + " || " + nameof(request)); + if (string.IsNullOrEmpty(botNames)) { + throw new ArgumentNullException(nameof(botNames)); + } + + if (request == null) { + throw new ArgumentNullException(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)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(request.Type) + " || " + nameof(request.Value)))); } HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.SetUserInput(request.Type, request.Value!)))).ConfigureAwait(false); @@ -270,14 +287,18 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] public async Task> PausePost(string botNames, [FromBody] BotPauseRequest request) { - if (string.IsNullOrEmpty(botNames) || (request == null)) { - throw new ArgumentNullException(nameof(botNames) + " || " + nameof(request)); + if (string.IsNullOrEmpty(botNames)) { + throw new ArgumentNullException(nameof(botNames)); + } + + if (request == null) { + throw new ArgumentNullException(nameof(request)); } HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => bot.Actions.Pause(request.Permanent, request.ResumeInSeconds))).ConfigureAwait(false); @@ -297,18 +318,22 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(GenericResponse>>), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] public async Task> RedeemPost(string botNames, [FromBody] BotRedeemRequest request) { - if (string.IsNullOrEmpty(botNames) || (request == null)) { - throw new ArgumentNullException(nameof(botNames) + " || " + nameof(request)); + if (string.IsNullOrEmpty(botNames)) { + throw new ArgumentNullException(nameof(botNames)); + } + + if (request == null) { + throw new ArgumentNullException(nameof(request)); } if ((request.KeysToRedeem == null) || (request.KeysToRedeem.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(request.KeysToRedeem)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(request.KeysToRedeem)))); } HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList results = await Utilities.InParallel(bots.Select(bot => request.KeysToRedeem.Select(key => bot.Actions.RedeemKey(key))).SelectMany(task => task)).ConfigureAwait(false); @@ -337,16 +362,24 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] public async Task> RenamePost(string botName, [FromBody] BotRenameRequest request) { - if (string.IsNullOrEmpty(botName) || (request == null) || (Bot.Bots == null)) { - throw new ArgumentNullException(nameof(botName) + " || " + nameof(request) + " || " + nameof(Bot.Bots)); + if (string.IsNullOrEmpty(botName)) { + throw new ArgumentNullException(nameof(botName)); } - if (string.IsNullOrEmpty(request.NewName) || request.NewName!.Equals(SharedInfo.ASF) || Bot.Bots.ContainsKey(request.NewName)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, nameof(request.NewName)))); + if (request == null) { + throw new ArgumentNullException(nameof(request)); + } + + if (Bot.Bots == null) { + throw new InvalidOperationException(nameof(Bot.Bots)); + } + + if (string.IsNullOrEmpty(request.NewName) || request.NewName!.Equals(SharedInfo.ASF, StringComparison.OrdinalIgnoreCase) || Bot.Bots.ContainsKey(request.NewName)) { + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(request.NewName)))); } if (!Bot.Bots.TryGetValue(botName, out Bot? bot)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botName))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botName))); } bool result = await bot.Rename(request.NewName).ConfigureAwait(false); @@ -368,7 +401,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.Actions.Resume))).ConfigureAwait(false); @@ -390,7 +423,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.Actions.Start))).ConfigureAwait(false); @@ -412,7 +445,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.Actions.Stop))).ConfigureAwait(false); @@ -427,18 +460,22 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(GenericResponse>), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] public async Task> TwoFactorAuthenticationConfirmationsPost(string botNames, [FromBody] TwoFactorAuthenticationConfirmationsRequest request) { - if (string.IsNullOrEmpty(botNames) || (request == null)) { + if (string.IsNullOrEmpty(botNames)) { throw new ArgumentNullException(nameof(botNames)); } + if (request == null) { + throw new ArgumentNullException(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)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(request.AcceptedType)))); } HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse>(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse>(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => bot.Actions.HandleTwoFactorAuthenticationConfirmations(request.Accept, request.AcceptedType, request.AcceptedCreatorIDs?.Count > 0 ? request.AcceptedCreatorIDs : null, request.WaitIfNeeded))).ConfigureAwait(false); @@ -467,7 +504,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { HashSet? bots = Bot.GetBots(botNames); if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse>>(false, string.Format(Strings.BotNotFound, botNames))); + return BadRequest(new GenericResponse>>(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames))); } IList<(bool Success, string? Token, string Message)> results = await Utilities.InParallel(bots.Select(bot => bot.Actions.GenerateTwoFactorAuthenticationToken())).ConfigureAwait(false); diff --git a/ArchiSteamFarm/IPC/Controllers/Api/CommandController.cs b/ArchiSteamFarm/IPC/Controllers/Api/CommandController.cs index b6eb69b0e..9020eb6eb 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/CommandController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/CommandController.cs @@ -20,6 +20,7 @@ // limitations under the License. using System; +using System.Globalization; using System.Linq; using System.Net; using System.Threading.Tasks; @@ -48,13 +49,13 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { } if (string.IsNullOrEmpty(request.Command)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(request.Command)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(request.Command)))); } ulong steamOwnerID = ASF.GlobalConfig?.SteamOwnerID ?? GlobalConfig.DefaultSteamOwnerID; if (steamOwnerID == 0) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, nameof(ASF.GlobalConfig.SteamOwnerID)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(ASF.GlobalConfig.SteamOwnerID)))); } Bot? targetBot = Bot.Bots?.OrderBy(bot => bot.Key, Bot.BotsComparer).Select(bot => bot.Value).FirstOrDefault(); @@ -69,7 +70,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { if (!string.IsNullOrEmpty(commandPrefix) && command.StartsWith(commandPrefix!, StringComparison.Ordinal)) { if (command.Length == commandPrefix!.Length) { // If the message starts with command prefix and is of the same length as command prefix, then it's just empty command trigger, useless - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(command)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(command)))); } command = command.Substring(commandPrefix!.Length); diff --git a/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs b/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs index c7d885538..d9dfcd462 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Net.WebSockets; @@ -49,8 +50,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(IEnumerable>), (int) HttpStatusCode.OK)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] public async Task NLogGet() { + if (HttpContext == null) { + throw new InvalidOperationException(nameof(HttpContext)); + } + if (!HttpContext.WebSockets.IsWebSocketRequest) { - return BadRequest(new GenericResponse(false, string.Format(Strings.WarningFailedWithError, nameof(HttpContext.WebSockets.IsWebSocketRequest) + ": " + HttpContext.WebSockets.IsWebSocketRequest))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError!, nameof(HttpContext.WebSockets.IsWebSocketRequest) + ": " + HttpContext.WebSockets.IsWebSocketRequest))); } // From now on we can return only EmptyResult as the response stream is already being used by existing websocket connection @@ -74,7 +79,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { } while (webSocket.State == WebSocketState.Open) { - WebSocketReceiveResult result = await webSocket.ReceiveAsync(new byte[0], CancellationToken.None).ConfigureAwait(false); + WebSocketReceiveResult result = await webSocket.ReceiveAsync(Array.Empty(), CancellationToken.None).ConfigureAwait(false); if (result.MessageType != WebSocketMessageType.Close) { await webSocket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "You're not supposed to be sending any message but Close!", CancellationToken.None).ConfigureAwait(false); @@ -104,7 +109,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { throw new ArgumentNullException(nameof(newHistoryEntryArgs)); } - if (ActiveLogWebSockets.Count == 0) { + if (ActiveLogWebSockets.IsEmpty) { return; } @@ -114,8 +119,16 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { } private static async Task PostLoggedJsonUpdate(WebSocket webSocket, SemaphoreSlim sendSemaphore, string json) { - if ((webSocket == null) || (sendSemaphore == null) || string.IsNullOrEmpty(json)) { - throw new ArgumentNullException(nameof(webSocket) + " || " + nameof(sendSemaphore) + " || " + nameof(json)); + if (webSocket == null) { + throw new ArgumentNullException(nameof(webSocket)); + } + + if (sendSemaphore == null) { + throw new ArgumentNullException(nameof(sendSemaphore)); + } + + if (string.IsNullOrEmpty(json)) { + throw new ArgumentNullException(nameof(json)); } if (webSocket.State != WebSocketState.Open) { @@ -138,8 +151,16 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { } private static async Task PostLoggedMessageUpdate(WebSocket webSocket, SemaphoreSlim sendSemaphore, string loggedMessage) { - if ((webSocket == null) || (sendSemaphore == null) || string.IsNullOrEmpty(loggedMessage)) { - throw new ArgumentNullException(nameof(webSocket) + " || " + nameof(sendSemaphore) + " || " + nameof(loggedMessage)); + if (webSocket == null) { + throw new ArgumentNullException(nameof(webSocket)); + } + + if (sendSemaphore == null) { + throw new ArgumentNullException(nameof(sendSemaphore)); + } + + if (string.IsNullOrEmpty(loggedMessage)) { + throw new ArgumentNullException(nameof(loggedMessage)); } if (webSocket.State != WebSocketState.Open) { diff --git a/ArchiSteamFarm/IPC/Controllers/Api/PluginsController.cs b/ArchiSteamFarm/IPC/Controllers/Api/PluginsController.cs index 6504fb834..333b48ed5 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/PluginsController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/PluginsController.cs @@ -19,6 +19,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Collections.Generic; using System.Net; using ArchiSteamFarm.IPC.Responses; @@ -31,7 +32,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [HttpGet] [ProducesResponseType(typeof(GenericResponse>), (int) HttpStatusCode.OK)] public ActionResult>> PluginsGet() { - IReadOnlyCollection activePlugins = PluginsCore.ActivePlugins ?? (IReadOnlyCollection) new IPlugin[0]; + IReadOnlyCollection activePlugins = PluginsCore.ActivePlugins ?? (IReadOnlyCollection) Array.Empty(); return Ok(new GenericResponse>(activePlugins)); } diff --git a/ArchiSteamFarm/IPC/Controllers/Api/StructureController.cs b/ArchiSteamFarm/IPC/Controllers/Api/StructureController.cs index b06c121b4..070c02b20 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/StructureController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/StructureController.cs @@ -20,6 +20,7 @@ // limitations under the License. using System; +using System.Globalization; using System.Net; using ArchiSteamFarm.IPC.Responses; using ArchiSteamFarm.Localization; @@ -45,7 +46,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { Type? targetType = WebUtilities.ParseType(structure); if (targetType == null) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, structure))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, structure))); } object? obj; @@ -53,7 +54,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { try { obj = Activator.CreateInstance(targetType, true); } catch (Exception e) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorParsingObject, nameof(targetType)) + Environment.NewLine + e)); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorParsingObject, nameof(targetType)) + Environment.NewLine + e)); } return Ok(new GenericResponse(obj)); diff --git a/ArchiSteamFarm/IPC/Controllers/Api/TypeController.cs b/ArchiSteamFarm/IPC/Controllers/Api/TypeController.cs index 938f343e3..4f4e9b1a6 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/TypeController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/TypeController.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Reflection; @@ -49,7 +50,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { Type? targetType = WebUtilities.ParseType(type); if (targetType == null) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, type))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, type))); } string? baseType = targetType.BaseType?.GetUnifiedName(); @@ -92,10 +93,10 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { if (string.IsNullOrEmpty(valueText)) { ASF.ArchiLogger.LogNullError(nameof(valueText)); - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorObjectIsNull, nameof(valueText)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(valueText)))); } - string? valueObjText = Convert.ChangeType(value, enumType)?.ToString(); + string? valueObjText = Convert.ChangeType(value, enumType, CultureInfo.InvariantCulture)?.ToString(); if (string.IsNullOrEmpty(valueObjText)) { continue; diff --git a/ArchiSteamFarm/IPC/Controllers/Api/WWWController.cs b/ArchiSteamFarm/IPC/Controllers/Api/WWWController.cs index abcdcd8ff..1a0913205 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/WWWController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/WWWController.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net; @@ -51,7 +52,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { string directoryPath = Path.Combine(ArchiKestrel.WebsiteDirectory, directory); if (!Directory.Exists(directoryPath)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, directory))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, directory))); } string[] files; @@ -59,7 +60,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { try { files = Directory.GetFiles(directoryPath); } catch (Exception e) { - return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, string.Format(Strings.ErrorParsingObject, nameof(files)) + Environment.NewLine + e)); + return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorParsingObject, nameof(files)) + Environment.NewLine + e)); } HashSet result = files.Select(Path.GetFileName).Where(fileName => !string.IsNullOrEmpty(fileName)).ToHashSet()!; @@ -79,7 +80,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { public async Task> GitHubReleaseGet() { GitHub.ReleaseResponse? releaseResponse = await GitHub.GetLatestRelease(false).ConfigureAwait(false); - return releaseResponse != null ? Ok(new GenericResponse(new GitHubReleaseResponse(releaseResponse))) : StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries))); + return releaseResponse != null ? Ok(new GenericResponse(new GitHubReleaseResponse(releaseResponse))) : StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries))); } /// @@ -106,7 +107,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { break; default: if (!Version.TryParse(version, out Version? parsedVersion)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, nameof(version)))); + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(version)))); } releaseResponse = await GitHub.GetRelease(parsedVersion.ToString(4)).ConfigureAwait(false); @@ -114,7 +115,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { break; } - return releaseResponse != null ? Ok(new GenericResponse(new GitHubReleaseResponse(releaseResponse))) : StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries))); + return releaseResponse != null ? Ok(new GenericResponse(new GitHubReleaseResponse(releaseResponse))) : StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries))); } /// @@ -129,17 +130,21 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.BadRequest)] [ProducesResponseType(typeof(GenericResponse), (int) HttpStatusCode.ServiceUnavailable)] public async Task> SendPost([FromBody] WWWSendRequest request) { - if ((request == null) || (ASF.WebBrowser == null)) { - throw new ArgumentNullException(nameof(request) + " || " + nameof(ASF.WebBrowser)); + if ((request == null)) { + throw new ArgumentNullException(nameof(request)); } - if (string.IsNullOrEmpty(request.URL) || !Uri.TryCreate(request.URL, UriKind.Absolute, out Uri? uri) || !uri.Scheme.Equals(Uri.UriSchemeHttps)) { - return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsInvalid, nameof(request.URL)))); + if (ASF.WebBrowser == null) { + throw new InvalidOperationException(nameof(ASF.WebBrowser)); + } + + if (string.IsNullOrEmpty(request.URL) || !Uri.TryCreate(request.URL, UriKind.Absolute, out Uri? uri) || !uri.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)) { + return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(request.URL)))); } WebBrowser.StringResponse? urlResponse = await ASF.WebBrowser.UrlGetToString(request.URL!).ConfigureAwait(false); - return urlResponse?.Content != null ? Ok(new GenericResponse(urlResponse.Content)) : StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries))); + return urlResponse?.Content != null ? Ok(new GenericResponse(urlResponse.Content)) : StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries))); } } } diff --git a/ArchiSteamFarm/IPC/Integration/ApiAuthenticationMiddleware.cs b/ArchiSteamFarm/IPC/Integration/ApiAuthenticationMiddleware.cs index 9b38a3130..76d5fc0e0 100644 --- a/ArchiSteamFarm/IPC/Integration/ApiAuthenticationMiddleware.cs +++ b/ArchiSteamFarm/IPC/Integration/ApiAuthenticationMiddleware.cs @@ -76,8 +76,12 @@ namespace ArchiSteamFarm.IPC.Integration { } private static async Task GetAuthenticationStatus(HttpContext context) { - if ((context == null) || (ClearFailedAuthorizationsTimer == null)) { - throw new ArgumentNullException(nameof(context) + " || " + nameof(ClearFailedAuthorizationsTimer)); + if ((context == null)) { + throw new ArgumentNullException(nameof(context)); + } + + if (ClearFailedAuthorizationsTimer == null) { + throw new InvalidOperationException(nameof(ClearFailedAuthorizationsTimer)); } string? ipcPassword = ASF.GlobalConfig != null ? ASF.GlobalConfig.IPCPassword : GlobalConfig.DefaultIPCPassword; @@ -89,7 +93,7 @@ namespace ArchiSteamFarm.IPC.Integration { IPAddress? clientIP = context.Connection.RemoteIpAddress; if (clientIP == null) { - throw new ArgumentNullException(nameof(context.Connection.RemoteIpAddress)); + throw new InvalidOperationException(nameof(clientIP)); } if (FailedAuthorizations.TryGetValue(clientIP, out byte attempts)) { diff --git a/ArchiSteamFarm/IPC/Integration/EnumSchemaFilter.cs b/ArchiSteamFarm/IPC/Integration/EnumSchemaFilter.cs index 44dbeabe6..a869ab082 100644 --- a/ArchiSteamFarm/IPC/Integration/EnumSchemaFilter.cs +++ b/ArchiSteamFarm/IPC/Integration/EnumSchemaFilter.cs @@ -20,6 +20,7 @@ // limitations under the License. using System; +using System.Globalization; using JetBrains.Annotations; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; @@ -30,11 +31,15 @@ namespace ArchiSteamFarm.IPC.Integration { [UsedImplicitly] internal sealed class EnumSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { - if ((schema == null) || (context == null)) { - throw new ArgumentNullException(nameof(schema) + " || " + nameof(context)); + if (schema == null) { + throw new ArgumentNullException(nameof(schema)); } - if (!context.Type.IsEnum) { + if (context == null) { + throw new ArgumentNullException(nameof(context)); + } + + if ((context.Type == null) || !context.Type.IsEnum) { return; } @@ -67,9 +72,9 @@ namespace ArchiSteamFarm.IPC.Integration { enumObject = new OpenApiLong(longValue); } else if (TryCast(enumValue, out ulong ulongValue)) { // OpenApi spec doesn't support ulongs as of now - enumObject = new OpenApiString(ulongValue.ToString()); + enumObject = new OpenApiString(ulongValue.ToString(CultureInfo.InvariantCulture)); } else { - throw new ArgumentOutOfRangeException(nameof(enumValue)); + throw new InvalidOperationException(nameof(enumValue)); } definition.Add(enumName!, enumObject); @@ -84,7 +89,7 @@ namespace ArchiSteamFarm.IPC.Integration { } try { - typedValue = (T) Convert.ChangeType(value, typeof(T)); + typedValue = (T) Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture); return true; } catch (InvalidCastException) { diff --git a/ArchiSteamFarm/IPC/Requests/ASFEncryptRequest.cs b/ArchiSteamFarm/IPC/Requests/ASFEncryptRequest.cs index 36a069c95..d18f48aed 100644 --- a/ArchiSteamFarm/IPC/Requests/ASFEncryptRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/ASFEncryptRequest.cs @@ -31,14 +31,14 @@ namespace ArchiSteamFarm.IPC.Requests { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly ArchiCryptoHelper.ECryptoMethod CryptoMethod; + public ArchiCryptoHelper.ECryptoMethod CryptoMethod { get; private set; } /// /// String to encrypt with provided . /// [JsonProperty(Required = Required.Always)] [Required] - public readonly string? StringToEncrypt; + public string? StringToEncrypt { get; private set; } [JsonConstructor] private ASFEncryptRequest() { } diff --git a/ArchiSteamFarm/IPC/Requests/ASFHashRequest.cs b/ArchiSteamFarm/IPC/Requests/ASFHashRequest.cs index 348f277e4..4db98705f 100644 --- a/ArchiSteamFarm/IPC/Requests/ASFHashRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/ASFHashRequest.cs @@ -31,14 +31,14 @@ namespace ArchiSteamFarm.IPC.Requests { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly ArchiCryptoHelper.EHashingMethod HashingMethod; + public ArchiCryptoHelper.EHashingMethod HashingMethod { get; private set; } /// /// String to hash with provided . /// [JsonProperty(Required = Required.Always)] [Required] - public readonly string? StringToHash; + public string? StringToHash { get; private set; } [JsonConstructor] private ASFHashRequest() { } diff --git a/ArchiSteamFarm/IPC/Requests/ASFRequest.cs b/ArchiSteamFarm/IPC/Requests/ASFRequest.cs index abcb45254..9f742997b 100644 --- a/ArchiSteamFarm/IPC/Requests/ASFRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/ASFRequest.cs @@ -31,7 +31,7 @@ namespace ArchiSteamFarm.IPC.Requests { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly GlobalConfig? GlobalConfig; + public GlobalConfig? GlobalConfig { get; private set; } [JsonConstructor] private ASFRequest() { } diff --git a/ArchiSteamFarm/IPC/Requests/BotGamesToRedeemInBackgroundRequest.cs b/ArchiSteamFarm/IPC/Requests/BotGamesToRedeemInBackgroundRequest.cs index 2e322e045..3f79f6237 100644 --- a/ArchiSteamFarm/IPC/Requests/BotGamesToRedeemInBackgroundRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/BotGamesToRedeemInBackgroundRequest.cs @@ -36,7 +36,7 @@ namespace ArchiSteamFarm.IPC.Requests { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly OrderedDictionary? GamesToRedeemInBackground; + public OrderedDictionary? GamesToRedeemInBackground { get; private set; } [JsonConstructor] private BotGamesToRedeemInBackgroundRequest() { } diff --git a/ArchiSteamFarm/IPC/Requests/BotInputRequest.cs b/ArchiSteamFarm/IPC/Requests/BotInputRequest.cs index 158798698..49393664f 100644 --- a/ArchiSteamFarm/IPC/Requests/BotInputRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/BotInputRequest.cs @@ -29,13 +29,13 @@ namespace ArchiSteamFarm.IPC.Requests { /// Specifies the type of the input. /// [JsonProperty(Required = Required.Always)] - public readonly ASF.EUserInputType Type; + public ASF.EUserInputType Type { get; private set; } /// /// Specifies the value for given input type (declared in ) /// [JsonProperty(Required = Required.Always)] - public readonly string? Value; + public string? Value { get; private set; } [JsonConstructor] private BotInputRequest() { } diff --git a/ArchiSteamFarm/IPC/Requests/BotPauseRequest.cs b/ArchiSteamFarm/IPC/Requests/BotPauseRequest.cs index 27e2a53d5..35ef5b8e2 100644 --- a/ArchiSteamFarm/IPC/Requests/BotPauseRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/BotPauseRequest.cs @@ -29,13 +29,13 @@ namespace ArchiSteamFarm.IPC.Requests { /// Specifies if pause is permanent or temporary (default). /// [JsonProperty(Required = Required.DisallowNull)] - public readonly bool Permanent; + public bool Permanent { get; private set; } /// /// Specifies automatic resume action in given seconds. Default value of 0 disables automatic resume. /// [JsonProperty(Required = Required.DisallowNull)] - public readonly ushort ResumeInSeconds; + public ushort ResumeInSeconds { get; private set; } [JsonConstructor] private BotPauseRequest() { } diff --git a/ArchiSteamFarm/IPC/Requests/BotRedeemRequest.cs b/ArchiSteamFarm/IPC/Requests/BotRedeemRequest.cs index ca0ef8d85..7e39c5f98 100644 --- a/ArchiSteamFarm/IPC/Requests/BotRedeemRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/BotRedeemRequest.cs @@ -32,7 +32,7 @@ namespace ArchiSteamFarm.IPC.Requests { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly ImmutableHashSet? KeysToRedeem; + public ImmutableHashSet? KeysToRedeem { get; private set; } [JsonConstructor] private BotRedeemRequest() { } diff --git a/ArchiSteamFarm/IPC/Requests/BotRenameRequest.cs b/ArchiSteamFarm/IPC/Requests/BotRenameRequest.cs index 3a105eb19..a789dc351 100644 --- a/ArchiSteamFarm/IPC/Requests/BotRenameRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/BotRenameRequest.cs @@ -31,7 +31,7 @@ namespace ArchiSteamFarm.IPC.Requests { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly string? NewName; + public string? NewName { get; private set; } [JsonConstructor] private BotRenameRequest() { } diff --git a/ArchiSteamFarm/IPC/Requests/BotRequest.cs b/ArchiSteamFarm/IPC/Requests/BotRequest.cs index 3441d418c..8038f6cdd 100644 --- a/ArchiSteamFarm/IPC/Requests/BotRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/BotRequest.cs @@ -31,7 +31,7 @@ namespace ArchiSteamFarm.IPC.Requests { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly BotConfig? BotConfig; + public BotConfig? BotConfig { get; private set; } [JsonConstructor] private BotRequest() { } diff --git a/ArchiSteamFarm/IPC/Requests/CommandRequest.cs b/ArchiSteamFarm/IPC/Requests/CommandRequest.cs index 1e09d37a6..bfbeece99 100644 --- a/ArchiSteamFarm/IPC/Requests/CommandRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/CommandRequest.cs @@ -32,7 +32,7 @@ namespace ArchiSteamFarm.IPC.Requests { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly string? Command; + public string? Command { get; private set; } internal CommandRequest(string command) { if (string.IsNullOrEmpty(command)) { diff --git a/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs b/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs index ac38d5069..9f367e9d0 100644 --- a/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs @@ -23,6 +23,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using ArchiSteamFarm.Localization; using Newtonsoft.Json; @@ -33,19 +34,19 @@ namespace ArchiSteamFarm.IPC.Requests { /// Specifies the target action, whether we should accept the confirmations (true), or decline them (false). /// [JsonProperty(Required = Required.Always)] - public readonly bool Accept; + public bool Accept { get; private set; } /// /// Specifies the 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; + public MobileAuthenticator.Confirmation.EType? AcceptedType { get; private set; } /// /// 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; + public bool WaitIfNeeded { get; private set; } /// /// 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 the market listing. If not provided, or empty array, all confirmation IDs are considered for an action. @@ -67,7 +68,7 @@ namespace ArchiSteamFarm.IPC.Requests { foreach (string creatorIDText in value) { if (!ulong.TryParse(creatorIDText, out ulong creatorID) || (creatorID == 0)) { - ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, nameof(SAcceptedCreatorIDs))); + ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(SAcceptedCreatorIDs))); return; } diff --git a/ArchiSteamFarm/IPC/Requests/WWWSendRequest.cs b/ArchiSteamFarm/IPC/Requests/WWWSendRequest.cs index 20a14a488..85002de75 100644 --- a/ArchiSteamFarm/IPC/Requests/WWWSendRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/WWWSendRequest.cs @@ -34,7 +34,7 @@ namespace ArchiSteamFarm.IPC.Requests { /// [Required] [JsonProperty(Required = Required.Always)] - public readonly string? URL; + public string? URL { get; private set; } [JsonConstructor] private WWWSendRequest() { } diff --git a/ArchiSteamFarm/IPC/Responses/ASFResponse.cs b/ArchiSteamFarm/IPC/Responses/ASFResponse.cs index 6e4b7bf8a..50e3b0be2 100644 --- a/ArchiSteamFarm/IPC/Responses/ASFResponse.cs +++ b/ArchiSteamFarm/IPC/Responses/ASFResponse.cs @@ -30,54 +30,50 @@ namespace ArchiSteamFarm.IPC.Responses { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly string BuildVariant; + public string BuildVariant { get; private set; } /// /// A value specifying whether this variant of ASF is capable of auto-update. /// [JsonProperty(Required = Required.Always)] [Required] - public readonly bool CanUpdate; + public bool CanUpdate { get; private set; } /// /// Currently loaded ASF's global config. /// [JsonProperty(Required = Required.Always)] [Required] - public readonly GlobalConfig GlobalConfig; + public GlobalConfig GlobalConfig { get; private set; } /// /// Current amount of managed memory being used by the process, in kilobytes. /// [JsonProperty(Required = Required.Always)] [Required] - public readonly uint MemoryUsage; + public uint MemoryUsage { get; private set; } /// /// Start date of the process. /// [JsonProperty(Required = Required.Always)] [Required] - public readonly DateTime ProcessStartTime; + public DateTime ProcessStartTime { get; private set; } /// /// ASF version of currently running binary. /// [JsonProperty(Required = Required.Always)] [Required] - public readonly Version Version; + public Version Version { get; private set; } internal ASFResponse(string buildVariant, bool canUpdate, GlobalConfig globalConfig, uint memoryUsage, DateTime processStartTime, Version version) { - if (string.IsNullOrEmpty(buildVariant) || (globalConfig == null) || (memoryUsage == 0) || (processStartTime == DateTime.MinValue) || (version == null)) { - throw new ArgumentNullException(nameof(buildVariant) + " || " + nameof(globalConfig) + " || " + nameof(memoryUsage) + " || " + nameof(processStartTime) + " || " + nameof(version)); - } - - BuildVariant = buildVariant; + BuildVariant = !string.IsNullOrEmpty(buildVariant) ? buildVariant : throw new ArgumentNullException(nameof(buildVariant)); CanUpdate = canUpdate; - GlobalConfig = globalConfig; - MemoryUsage = memoryUsage; - ProcessStartTime = processStartTime; - Version = version; + GlobalConfig = globalConfig ?? throw new ArgumentNullException(nameof(globalConfig)); + MemoryUsage = memoryUsage > 0 ? memoryUsage : throw new ArgumentOutOfRangeException(nameof(memoryUsage)); + ProcessStartTime = processStartTime > DateTime.MinValue ? processStartTime : throw new ArgumentOutOfRangeException(nameof(processStartTime)); + Version = version ?? throw new ArgumentNullException(nameof(version)); } } } diff --git a/ArchiSteamFarm/IPC/Responses/GamesToRedeemInBackgroundResponse.cs b/ArchiSteamFarm/IPC/Responses/GamesToRedeemInBackgroundResponse.cs index 98dc7c3de..af929d699 100644 --- a/ArchiSteamFarm/IPC/Responses/GamesToRedeemInBackgroundResponse.cs +++ b/ArchiSteamFarm/IPC/Responses/GamesToRedeemInBackgroundResponse.cs @@ -28,13 +28,13 @@ namespace ArchiSteamFarm.IPC.Responses { /// Keys that were redeemed and not used during the process, if available. /// [JsonProperty] - public readonly Dictionary? UnusedKeys; + public Dictionary? UnusedKeys { get; private set; } /// /// Keys that were redeemed and used during the process, if available. /// [JsonProperty] - public readonly Dictionary? UsedKeys; + public Dictionary? UsedKeys { get; private set; } internal GamesToRedeemInBackgroundResponse(Dictionary? unusedKeys = null, Dictionary? usedKeys = null) { UnusedKeys = unusedKeys; diff --git a/ArchiSteamFarm/IPC/Responses/GenericResponse.cs b/ArchiSteamFarm/IPC/Responses/GenericResponse.cs index eaf740b95..88b610e6d 100644 --- a/ArchiSteamFarm/IPC/Responses/GenericResponse.cs +++ b/ArchiSteamFarm/IPC/Responses/GenericResponse.cs @@ -32,7 +32,7 @@ namespace ArchiSteamFarm.IPC.Responses { /// The type of the result depends on the API endpoint that you've called. /// [JsonProperty] - public readonly T? Result; + public T? Result { get; private set; } public GenericResponse(T? result) : base(result != null) => Result = result; public GenericResponse(bool success, string message) : base(success, message) { } @@ -48,14 +48,14 @@ namespace ArchiSteamFarm.IPC.Responses { /// This property will provide exact reason for majority of expected failures. /// [JsonProperty] - public readonly string Message; + public string Message { get; private set; } /// /// Boolean type that specifies if the request has succeeded. /// [JsonProperty(Required = Required.Always)] [Required] - public readonly bool Success; + public bool Success { get; private set; } public GenericResponse(bool success, string? message = null) { Success = success; diff --git a/ArchiSteamFarm/IPC/Responses/GitHubReleaseResponse.cs b/ArchiSteamFarm/IPC/Responses/GitHubReleaseResponse.cs index 2ef664da4..0a8add30b 100644 --- a/ArchiSteamFarm/IPC/Responses/GitHubReleaseResponse.cs +++ b/ArchiSteamFarm/IPC/Responses/GitHubReleaseResponse.cs @@ -30,28 +30,28 @@ namespace ArchiSteamFarm.IPC.Responses { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly string? ChangelogHTML; + public string? ChangelogHTML { get; private set; } /// /// Date of the release. /// [JsonProperty(Required = Required.Always)] [Required] - public readonly DateTime ReleasedAt; + public DateTime ReleasedAt { get; private set; } /// /// Boolean value that specifies whether the build is stable or not (pre-release). /// [JsonProperty(Required = Required.Always)] [Required] - public readonly bool Stable; + public bool Stable { get; private set; } /// /// Version of the release. /// [JsonProperty(Required = Required.Always)] [Required] - public readonly string? Version; + public string? Version { get; private set; } internal GitHubReleaseResponse(GitHub.ReleaseResponse releaseResponse) { if (releaseResponse == null) { diff --git a/ArchiSteamFarm/IPC/Responses/TypeResponse.cs b/ArchiSteamFarm/IPC/Responses/TypeResponse.cs index b3fb5578d..84a37343c 100644 --- a/ArchiSteamFarm/IPC/Responses/TypeResponse.cs +++ b/ArchiSteamFarm/IPC/Responses/TypeResponse.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; using Newtonsoft.Json; namespace ArchiSteamFarm.IPC.Responses { @@ -36,22 +37,18 @@ namespace ArchiSteamFarm.IPC.Responses { /// [JsonProperty(Required = Required.Always)] [Required] - public readonly Dictionary Body; + public Dictionary Body { get; private set; } /// /// Metadata of given type. /// [JsonProperty(Required = Required.Always)] [Required] - public readonly TypeProperties Properties; + public TypeProperties Properties { get; private set; } - internal TypeResponse(Dictionary body, TypeProperties properties) { - if ((body == null) || (properties == null)) { - throw new ArgumentNullException(nameof(body) + " || " + nameof(properties)); - } - - Body = body; - Properties = properties; + internal TypeResponse([NotNull] Dictionary body, [NotNull] TypeProperties properties) { + Body = body ?? throw new ArgumentNullException(nameof(body)); + Properties = properties ?? throw new ArgumentNullException(nameof(properties)); } public sealed class TypeProperties { @@ -62,7 +59,7 @@ namespace ArchiSteamFarm.IPC.Responses { /// This can be used for determining how should be interpreted. /// [JsonProperty] - public readonly string? BaseType; + public string? BaseType { get; private set; } /// /// Custom attributes of given type, if available. @@ -71,7 +68,7 @@ namespace ArchiSteamFarm.IPC.Responses { /// This can be used for determining main enum type if is . /// [JsonProperty] - public readonly HashSet? CustomAttributes; + public HashSet? CustomAttributes { get; private set; } /// /// Underlying type of given type, if available. @@ -80,7 +77,7 @@ namespace ArchiSteamFarm.IPC.Responses { /// This can be used for determining underlying enum type if is . /// [JsonProperty] - public readonly string? UnderlyingType; + public string? UnderlyingType { get; private set; } internal TypeProperties(string? baseType = null, HashSet? customAttributes = null, string? underlyingType = null) { BaseType = baseType; diff --git a/ArchiSteamFarm/IPC/Startup.cs b/ArchiSteamFarm/IPC/Startup.cs index 547107bbe..b3ff2cbf6 100644 --- a/ArchiSteamFarm/IPC/Startup.cs +++ b/ArchiSteamFarm/IPC/Startup.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Net; using System.Reflection; @@ -56,8 +57,12 @@ namespace ArchiSteamFarm.IPC { [UsedImplicitly] public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { #endif - if ((app == null) || (env == null)) { - throw new ArgumentNullException(nameof(app) + " || " + nameof(env)); + if (app == null) { + throw new ArgumentNullException(nameof(app)); + } + + if (env == null) { + throw new ArgumentNullException(nameof(env)); } if (Debugging.IsUserDebugging) { @@ -137,14 +142,14 @@ namespace ArchiSteamFarm.IPC { HashSet? knownNetworks = null; - if ((knownNetworksTexts != null) && (knownNetworksTexts.Count > 0)) { + if (knownNetworksTexts?.Count > 0) { knownNetworks = new HashSet(knownNetworksTexts.Count); foreach (string knownNetworkText in knownNetworksTexts) { string[] addressParts = knownNetworkText.Split('/', StringSplitOptions.RemoveEmptyEntries); if ((addressParts.Length != 2) || !IPAddress.TryParse(addressParts[0], out IPAddress? ipAddress) || !byte.TryParse(addressParts[1], out byte prefixLength)) { - ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, nameof(knownNetworkText))); + ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(knownNetworkText))); ASF.ArchiLogger.LogGenericDebug(nameof(knownNetworkText) + ": " + knownNetworkText); continue; @@ -199,7 +204,7 @@ namespace ArchiSteamFarm.IPC { } }, - new string[0] + Array.Empty() } } );