From 61f876480a8f3d43a8c4e7be0dbb203a41bd5a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Domeradzki?= Date: Mon, 31 Mar 2025 00:06:05 +0200 Subject: [PATCH] General code cleanups --- .../RemoteCommunication.cs | 4 +- .../MonitoringPlugin.cs | 16 +++---- .../SteamTokenDumperPlugin.cs | 12 ++--- ArchiSteamFarm.Tests/Bot.cs | 3 +- ArchiSteamFarm/Core/ASF.cs | 10 +--- ArchiSteamFarm/Core/ArchiNet.cs | 2 +- ArchiSteamFarm/Core/Utilities.cs | 2 +- ArchiSteamFarm/IPC/ArchiKestrel.cs | 12 ++--- .../IPC/Controllers/Api/BotController.cs | 48 +++++++++---------- .../IPC/OpenApi/OperationTransformer.cs | 2 +- ArchiSteamFarm/Program.cs | 5 +- ArchiSteamFarm/Steam/Bot.cs | 15 ++---- ArchiSteamFarm/Steam/Cards/CardsFarmer.cs | 4 +- .../Steam/Data/InventoryContextData.cs | 10 ++-- .../Steam/Data/InventoryDescription.cs | 9 ++-- .../Steam/Integration/ArchiWebHandler.cs | 9 ++-- ArchiSteamFarm/Steam/Interaction/Actions.cs | 11 ++--- ArchiSteamFarm/Steam/Interaction/Commands.cs | 11 ++--- .../Steam/Security/MobileAuthenticator.cs | 7 ++- ArchiSteamFarm/Steam/Storage/BotConfig.cs | 6 +-- 20 files changed, 81 insertions(+), 117 deletions(-) diff --git a/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/RemoteCommunication.cs b/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/RemoteCommunication.cs index e0e66724b..efa27d510 100644 --- a/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/RemoteCommunication.cs +++ b/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/RemoteCommunication.cs @@ -62,12 +62,12 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable { private const byte MinimumSteamGuardEnabledDays = 15; // As imposed by Steam limits private const byte MinPersonaStateTTL = 5; // Minimum amount of minutes we must wait before requesting persona state update - private static readonly FrozenSet AcceptedMatchableTypes = new HashSet(4) { + private static readonly FrozenSet AcceptedMatchableTypes = [ EAssetType.Emoticon, EAssetType.FoilTradingCard, EAssetType.ProfileBackground, EAssetType.TradingCard - }.ToFrozenSet(); + ]; private readonly Bot Bot; private readonly Timer? HeartBeatTimer; diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs index 798357c18..d3e808598 100644 --- a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs @@ -133,8 +133,7 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IBot, IBotTradeOfferRes throw new InvalidOperationException(nameof(Meter)); } - services.AddOpenTelemetry().WithMetrics( - builder => { + services.AddOpenTelemetry().WithMetrics(builder => { builder.AddPrometheusExporter(static config => config.ScrapeEndpointPath = "/Api/metrics"); builder.AddRuntimeInstrumentation(); builder.AddAspNetCoreInstrumentation(); @@ -153,11 +152,11 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IBot, IBotTradeOfferRes int officialPluginCount = PluginsCore.ActivePlugins.Count(static plugin => plugin is OfficialPlugin); - PluginMeasurements = new HashSet>(3) { - new(PluginsCore.ActivePlugins.Count), - new(officialPluginCount, new KeyValuePair(TagNames.PluginType, "official")), - new(PluginsCore.ActivePlugins.Count - officialPluginCount, new KeyValuePair(TagNames.PluginType, "custom")) - }.ToFrozenSet(); + PluginMeasurements = [ + new Measurement(PluginsCore.ActivePlugins.Count), + new Measurement(officialPluginCount, new KeyValuePair(TagNames.PluginType, "official")), + new Measurement(PluginsCore.ActivePlugins.Count - officialPluginCount, new KeyValuePair(TagNames.PluginType, "custom")) + ]; Meter = new Meter(MeterName, Version.ToString()); @@ -272,8 +271,7 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IBot, IBotTradeOfferRes ); Meter.CreateObservableCounter( - $"{MetricNamePrefix}_bot_trades", () => TradeStatistics.SelectMany, Measurement>( - static kv => [ + $"{MetricNamePrefix}_bot_trades", () => TradeStatistics.SelectMany, Measurement>(static kv => [ new Measurement( kv.Value.AcceptedOffers, new KeyValuePair(TagNames.BotName, kv.Key.BotName), diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs index 167cace8e..58197aa18 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs @@ -478,8 +478,7 @@ internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotC // We can still try other depots bot.ArchiLogger.LogGenericWarningException(e); } finally { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Task.Delay(DepotsRateLimitingDelay).ConfigureAwait(false); // ReSharper disable once AccessToDisposedClosure - we're waiting for the semaphore to be free before disposing it @@ -505,8 +504,7 @@ internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotC // We can still try other depots bot.ArchiLogger.LogGenericWarningException(e); } finally { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Task.Delay(DepotsRateLimitingDelay).ConfigureAwait(false); // ReSharper disable once AccessToDisposedClosure - we're waiting for the semaphore to be free before disposing it @@ -561,8 +559,7 @@ internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotC return bot.Commands.FormatBotResponse(ArchiSteamFarm.Localization.Strings.FormatWarningFailedWithError(nameof(GlobalCache))); } - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Refresh(bot).ConfigureAwait(false); await SubmitData().ConfigureAwait(false); } @@ -598,8 +595,7 @@ internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotC return Commands.FormatStaticResponse(ArchiSteamFarm.Localization.Strings.FormatWarningFailedWithError(nameof(GlobalCache))); } - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Utilities.InParallel(bots.Select(static bot => Refresh(bot))).ConfigureAwait(false); await SubmitData().ConfigureAwait(false); diff --git a/ArchiSteamFarm.Tests/Bot.cs b/ArchiSteamFarm.Tests/Bot.cs index a69c41d26..e0902ae3b 100644 --- a/ArchiSteamFarm.Tests/Bot.cs +++ b/ArchiSteamFarm.Tests/Bot.cs @@ -511,8 +511,7 @@ internal sealed class Bot { CreateCard(4, realAppID: appID0) ]; - Assert.ThrowsExactly( - () => GetItemsForFullBadge( + Assert.ThrowsExactly(() => GetItemsForFullBadge( items, new Dictionary { { appID0, 3 }, { appID1, 3 }, diff --git a/ArchiSteamFarm/Core/ASF.cs b/ArchiSteamFarm/Core/ASF.cs index c59efe165..173b4973a 100644 --- a/ArchiSteamFarm/Core/ASF.cs +++ b/ArchiSteamFarm/Core/ASF.cs @@ -83,7 +83,7 @@ public static class ASF { internal static ICrossProcessSemaphore? RateLimitingSemaphore { get; private set; } internal static FrozenDictionary? WebLimitingSemaphores { get; private set; } - private static readonly FrozenSet AssembliesNeededBeforeUpdate = new HashSet(1, StringComparer.Ordinal) { "System.IO.Pipes" }.ToFrozenSet(StringComparer.Ordinal); + private static readonly FrozenSet AssembliesNeededBeforeUpdate = FrozenSet.Create(StringComparer.Ordinal, "System.IO.Pipes"); private static readonly SemaphoreSlim UpdateSemaphore = new(1, 1); private static Timer? AutoUpdatesTimer; @@ -773,13 +773,7 @@ public static class ASF { ReleaseResponse? releaseResponse = await GitHubService.GetLatestRelease(SharedInfo.GithubRepo, channel == GlobalConfig.EUpdateChannel.Stable).ConfigureAwait(false); - if (releaseResponse == null) { - ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed); - - return (false, null); - } - - if (string.IsNullOrEmpty(releaseResponse.Tag)) { + if ((releaseResponse == null) || string.IsNullOrEmpty(releaseResponse.Tag)) { ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed); return (false, null); diff --git a/ArchiSteamFarm/Core/ArchiNet.cs b/ArchiSteamFarm/Core/ArchiNet.cs index c25dd7aa2..e2b95f3dd 100644 --- a/ArchiSteamFarm/Core/ArchiNet.cs +++ b/ArchiSteamFarm/Core/ArchiNet.cs @@ -183,7 +183,7 @@ internal static class ArchiNet { private static async Task<(bool Success, IReadOnlyCollection? Result)> ResolveCachedBadBots(CancellationToken cancellationToken = default) { if (ASF.GlobalDatabase == null) { - throw new InvalidOperationException(nameof(ASF.WebBrowser)); + throw new InvalidOperationException(nameof(ASF.GlobalDatabase)); } if (ASF.WebBrowser == null) { diff --git a/ArchiSteamFarm/Core/Utilities.cs b/ArchiSteamFarm/Core/Utilities.cs index cc3eb23b4..8420924b8 100644 --- a/ArchiSteamFarm/Core/Utilities.cs +++ b/ArchiSteamFarm/Core/Utilities.cs @@ -51,7 +51,7 @@ public static class Utilities { private const byte TimeoutForLongRunningTasksInSeconds = 60; private const uint UnauthorizedAccessHResult = 0x80070005; - private static readonly FrozenSet DirectorySeparators = new HashSet(2) { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }.ToFrozenSet(); + private static readonly FrozenSet DirectorySeparators = [Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar]; [PublicAPI] public static IEnumerable AsLinqThreadSafeEnumerable(this ICollection collection) { diff --git a/ArchiSteamFarm/IPC/ArchiKestrel.cs b/ArchiSteamFarm/IPC/ArchiKestrel.cs index eeb2d235e..2b02299e5 100644 --- a/ArchiSteamFarm/IPC/ArchiKestrel.cs +++ b/ArchiSteamFarm/IPC/ArchiKestrel.cs @@ -301,8 +301,7 @@ internal static class ArchiKestrel { } // Add support for proxies - services.Configure( - options => { + services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.All; if (knownNetworks != null) { @@ -351,8 +350,7 @@ internal static class ArchiKestrel { } } - services.ConfigureHttpJsonOptions( - static options => { + services.ConfigureHttpJsonOptions(static options => { JsonSerializerOptions jsonSerializerOptions = Debugging.IsUserDebugging ? JsonUtilities.IndentedJsonSerialierOptions : JsonUtilities.DefaultJsonSerialierOptions; options.SerializerOptions.PropertyNamingPolicy = jsonSerializerOptions.PropertyNamingPolicy; @@ -377,8 +375,7 @@ internal static class ArchiKestrel { mvc.AddControllersAsServices(); // Modify default JSON options - mvc.AddJsonOptions( - static options => { + mvc.AddJsonOptions(static options => { JsonSerializerOptions jsonSerializerOptions = Debugging.IsUserDebugging ? JsonUtilities.IndentedJsonSerialierOptions : JsonUtilities.DefaultJsonSerialierOptions; options.JsonSerializerOptions.PropertyNamingPolicy = jsonSerializerOptions.PropertyNamingPolicy; @@ -439,8 +436,7 @@ internal static class ArchiKestrel { builder.WebHost.UseConfiguration(new ConfigurationBuilder().SetBasePath(absoluteConfigDirectory).AddJsonFile(SharedInfo.IPCConfigFile, false, true).Build()); } - builder.WebHost.ConfigureKestrel( - options => { + builder.WebHost.ConfigureKestrel(options => { options.AddServerHeader = false; if (customConfigExists) { diff --git a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs index 2297b1ec3..fc77b616b 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs @@ -279,30 +279,6 @@ public sealed class BotController : ArchiController { return Ok(results.All(static result => result) ? new GenericResponse(true) : new GenericResponse(false, Strings.WarningFailed)); } - [EndpointSummary("Fetches general inventory information of given bots")] - [HttpGet("{botNames:required}/Inventory")] - [ProducesResponseType>>>((int) HttpStatusCode.OK)] - [ProducesResponseType((int) HttpStatusCode.BadRequest)] - public async Task> InventoryInfoGet(string botNames) { - ArgumentException.ThrowIfNullOrEmpty(botNames); - - HashSet? bots = Bot.GetBots(botNames); - - if ((bots == null) || (bots.Count == 0)) { - return BadRequest(new GenericResponse(false, Strings.FormatBotNotFound(botNames))); - } - - IList?> results = await Utilities.InParallel(bots.Select(static bot => bot.ArchiWebHandler.GetInventoryContextData())).ConfigureAwait(false); - - Dictionary?> result = new(bots.Count, Bot.BotsComparer); - - foreach (Bot bot in bots) { - result[bot.BotName] = results[result.Count]; - } - - return Ok(new GenericResponse?>>(result)); - } - [EndpointSummary("Fetches specific inventory of given bots")] [HttpGet("{botNames:required}/Inventory/{appID}/{contextID}")] [ProducesResponseType>>((int) HttpStatusCode.OK)] @@ -354,6 +330,30 @@ public sealed class BotController : ArchiController { return Ok(new GenericResponse>(result)); } + [EndpointSummary("Fetches general inventory information of given bots")] + [HttpGet("{botNames:required}/Inventory")] + [ProducesResponseType>>>((int) HttpStatusCode.OK)] + [ProducesResponseType((int) HttpStatusCode.BadRequest)] + public async Task> InventoryInfoGet(string botNames) { + ArgumentException.ThrowIfNullOrEmpty(botNames); + + HashSet? bots = Bot.GetBots(botNames); + + if ((bots == null) || (bots.Count == 0)) { + return BadRequest(new GenericResponse(false, Strings.FormatBotNotFound(botNames))); + } + + IList?> results = await Utilities.InParallel(bots.Select(static bot => bot.ArchiWebHandler.GetInventoryContextData())).ConfigureAwait(false); + + Dictionary?> result = new(bots.Count, Bot.BotsComparer); + + foreach (Bot bot in bots) { + result[bot.BotName] = results[result.Count]; + } + + return Ok(new GenericResponse?>>(result)); + } + [EndpointSummary("Pauses given bots")] [HttpPost("{botNames:required}/Pause")] [ProducesResponseType((int) HttpStatusCode.OK)] diff --git a/ArchiSteamFarm/IPC/OpenApi/OperationTransformer.cs b/ArchiSteamFarm/IPC/OpenApi/OperationTransformer.cs index fb39d0626..61399b000 100644 --- a/ArchiSteamFarm/IPC/OpenApi/OperationTransformer.cs +++ b/ArchiSteamFarm/IPC/OpenApi/OperationTransformer.cs @@ -52,7 +52,7 @@ internal sealed class OperationTransformer : IOpenApiOperationTransformer { } }, - Array.Empty() + [] } } ); diff --git a/ArchiSteamFarm/Program.cs b/ArchiSteamFarm/Program.cs index 1538515dc..ecffca3fa 100644 --- a/ArchiSteamFarm/Program.cs +++ b/ArchiSteamFarm/Program.cs @@ -60,7 +60,7 @@ internal static class Program { private static readonly Dictionary RegisteredPosixSignals = new(); private static readonly TaskCompletionSource ShutdownResetEvent = new(); - private static readonly FrozenSet SupportedPosixSignals = new HashSet(2) { PosixSignal.SIGINT, PosixSignal.SIGTERM }.ToFrozenSet(); + private static readonly FrozenSet SupportedPosixSignals = [PosixSignal.SIGINT, PosixSignal.SIGTERM]; private static bool InputCryptkeyManually; private static bool Minimized; @@ -187,8 +187,7 @@ internal static class Program { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // Add support for custom logging targets - LogManager.Setup().SetupExtensions( - static extensions => { + LogManager.Setup().SetupExtensions(static extensions => { extensions.RegisterTarget(HistoryTarget.TargetName); extensions.RegisterTarget(SteamTarget.TargetName); } diff --git a/ArchiSteamFarm/Steam/Bot.cs b/ArchiSteamFarm/Steam/Bot.cs index ef55d75f2..db1079432 100644 --- a/ArchiSteamFarm/Steam/Bot.cs +++ b/ArchiSteamFarm/Steam/Bot.cs @@ -329,8 +329,7 @@ public sealed class Bot : IAsyncDisposable, IDisposable { ArchiWebHandler = new ArchiWebHandler(this); - SteamConfiguration = SteamConfiguration.Create( - builder => { + SteamConfiguration = SteamConfiguration.Create(builder => { builder.WithCellID(ASF.GlobalDatabase.CellID); builder.WithHttpClientFactory(ArchiWebHandler.GenerateDisposableHttpClient); builder.WithProtocolTypes(ASF.GlobalConfig?.SteamProtocols ?? GlobalConfig.DefaultSteamProtocols); @@ -2062,8 +2061,7 @@ public sealed class Bot : IAsyncDisposable, IDisposable { CancellationTokenSource? callbacksAborted = CallbacksAborted; if (callbacksAborted is { IsCancellationRequested: false }) { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Task.Delay(CallbackSleep * WebBrowser.MaxTries, CancellationToken.None).ConfigureAwait(false); try { @@ -2671,8 +2669,7 @@ public sealed class Bot : IAsyncDisposable, IDisposable { await ASF.LoginRateLimitingSemaphore.WaitAsync().ConfigureAwait(false); ASF.LoginRateLimitingSemaphore.Release(); } finally { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Task.Delay(loginLimiterDelay * 1000).ConfigureAwait(false); ASF.LoginSemaphore.Release(); } @@ -3137,8 +3134,7 @@ public sealed class Bot : IAsyncDisposable, IDisposable { // The following actions should be synchronized, as they modify the state of the inventory if (BotConfig.FarmingPreferences.HasFlag(BotConfig.EFarmingPreferences.AutoUnpackBoosterPacks)) { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { if (!await UnpackBoosterPacks().ConfigureAwait(false)) { // Another task is already in progress, so it'll handle the actions below as well return; @@ -3384,8 +3380,7 @@ public sealed class Bot : IAsyncDisposable, IDisposable { ResetPersonaState(); if (BotConfig.SteamMasterClanID != 0) { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { if (!await ArchiWebHandler.JoinGroup(BotConfig.SteamMasterClanID).ConfigureAwait(false)) { ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(nameof(ArchiWebHandler.JoinGroup))); } diff --git a/ArchiSteamFarm/Steam/Cards/CardsFarmer.cs b/ArchiSteamFarm/Steam/Cards/CardsFarmer.cs index b7c764cf0..d030c2a36 100644 --- a/ArchiSteamFarm/Steam/Cards/CardsFarmer.cs +++ b/ArchiSteamFarm/Steam/Cards/CardsFarmer.cs @@ -56,12 +56,12 @@ public sealed class CardsFarmer : IAsyncDisposable, IDisposable { private const byte HoursToIgnore = 1; // How many hours we ignore unreleased appIDs and don't bother checking them again [PublicAPI] - public static readonly FrozenSet SalesBlacklist = new HashSet(22) { 267420, 303700, 335590, 368020, 425280, 480730, 566020, 639900, 762800, 876740, 991980, 1195670, 1343890, 1465680, 1658760, 1797760, 2021850, 2243720, 2459330, 2640280, 2861690, 2861720 }.ToFrozenSet(); + public static readonly FrozenSet SalesBlacklist = [267420, 303700, 335590, 368020, 425280, 480730, 566020, 639900, 762800, 876740, 991980, 1195670, 1343890, 1465680, 1658760, 1797760, 2021850, 2243720, 2459330, 2640280, 2861690, 2861720]; private static readonly ConcurrentDictionary GloballyIgnoredAppIDs = new(); // Reserved for unreleased games // Games that were confirmed to show false status on general badges page - private static readonly FrozenSet UntrustedAppIDs = new HashSet(3) { 440, 570, 730 }.ToFrozenSet(); + private static readonly FrozenSet UntrustedAppIDs = [440, 570, 730]; [JsonInclude] [JsonPropertyName(nameof(CurrentGamesFarming))] diff --git a/ArchiSteamFarm/Steam/Data/InventoryContextData.cs b/ArchiSteamFarm/Steam/Data/InventoryContextData.cs index 53cd5e62e..2fbf022f6 100644 --- a/ArchiSteamFarm/Steam/Data/InventoryContextData.cs +++ b/ArchiSteamFarm/Steam/Data/InventoryContextData.cs @@ -26,6 +26,11 @@ using System.Text.Json.Serialization; namespace ArchiSteamFarm.Steam.Data; public sealed class InventoryContextData { + [JsonInclude] + [JsonPropertyName("asset_count")] + [JsonRequired] + public uint AssetsCount { get; private init; } + [JsonInclude] [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] [JsonPropertyName("id")] @@ -36,9 +41,4 @@ public sealed class InventoryContextData { [JsonPropertyName("name")] [JsonRequired] public string Name { get; private init; } = ""; - - [JsonInclude] - [JsonPropertyName("asset_count")] - [JsonRequired] - public uint AssetsCount { get; private init; } } diff --git a/ArchiSteamFarm/Steam/Data/InventoryDescription.cs b/ArchiSteamFarm/Steam/Data/InventoryDescription.cs index 3035646fe..1d05a75f2 100644 --- a/ArchiSteamFarm/Steam/Data/InventoryDescription.cs +++ b/ArchiSteamFarm/Steam/Data/InventoryDescription.cs @@ -89,8 +89,7 @@ public sealed class InventoryDescription { Body.descriptions.Clear(); Body.descriptions.AddRange( - value.Select( - static description => new CEconItem_DescriptionLine { + value.Select(static description => new CEconItem_DescriptionLine { color = description.Color, label = description.Label, type = description.Type, @@ -173,8 +172,7 @@ public sealed class InventoryDescription { Body.owner_actions.Clear(); Body.owner_actions.AddRange( - value.Select( - static action => new CEconItem_Action { + value.Select(static action => new CEconItem_Action { link = action.Link, name = action.Name } @@ -326,8 +324,7 @@ public sealed class InventoryDescription { Body.tags.Clear(); Body.tags.AddRange( - value.Select( - tag => new CEconItem_Tag { + value.Select(tag => new CEconItem_Tag { appid = AppID, category = tag.Identifier, color = tag.Color, diff --git a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs index c378f4f92..3dff2dba4 100644 --- a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs +++ b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs @@ -324,8 +324,7 @@ public sealed class ArchiWebHandler : IDisposable { if (rateLimitingDelay == 0) { ASF.InventorySemaphore.Release(); } else { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Task.Delay(rateLimitingDelay).ConfigureAwait(false); ASF.InventorySemaphore.Release(); } @@ -1400,8 +1399,7 @@ public sealed class ArchiWebHandler : IDisposable { await limiters.RateLimitingSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); // We release rate-limiter semaphore regardless of our task completion, since we use that one only to guarantee rate-limiting of their creation - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { // ReSharper disable once MethodSupportsCancellation - we must always wait given time before releasing semaphore await Task.Delay(WebLimiterDelay).ConfigureAwait(false); limiters.RateLimitingSemaphore.Release(); @@ -2090,8 +2088,7 @@ public sealed class ArchiWebHandler : IDisposable { if (rateLimitingDelay == 0) { ASF.InventorySemaphore.Release(); } else { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Task.Delay(rateLimitingDelay).ConfigureAwait(false); ASF.InventorySemaphore.Release(); } diff --git a/ArchiSteamFarm/Steam/Interaction/Actions.cs b/ArchiSteamFarm/Steam/Interaction/Actions.cs index cdb673c00..75aaf72c8 100644 --- a/ArchiSteamFarm/Steam/Interaction/Actions.cs +++ b/ArchiSteamFarm/Steam/Interaction/Actions.cs @@ -120,8 +120,7 @@ public sealed class Actions : IAsyncDisposable, IDisposable { [PublicAPI] public static (bool Success, string Message) Exit() { // Schedule the task after some time so user can receive response - Utilities.InBackground( - static async () => { + Utilities.InBackground(static async () => { await Task.Delay(1000).ConfigureAwait(false); await Program.Exit().ConfigureAwait(false); } @@ -264,7 +263,7 @@ public sealed class Actions : IAsyncDisposable, IDisposable { handledConfirmations ??= new Dictionary(); - foreach (Confirmation? confirmation in remainingConfirmations) { + foreach (Confirmation confirmation in remainingConfirmations) { handledConfirmations[confirmation.CreatorID] = confirmation; } @@ -381,8 +380,7 @@ public sealed class Actions : IAsyncDisposable, IDisposable { } // Schedule the task after some time so user can receive response - Utilities.InBackground( - static async () => { + Utilities.InBackground(static async () => { await Task.Delay(1000).ConfigureAwait(false); await Program.Restart().ConfigureAwait(false); } @@ -700,8 +698,7 @@ public sealed class Actions : IAsyncDisposable, IDisposable { await ASF.GiftsSemaphore.WaitAsync().ConfigureAwait(false); - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Task.Delay(giftsLimiterDelay * 1000).ConfigureAwait(false); ASF.GiftsSemaphore.Release(); } diff --git a/ArchiSteamFarm/Steam/Interaction/Commands.cs b/ArchiSteamFarm/Steam/Interaction/Commands.cs index cfbf5357a..b96363699 100644 --- a/ArchiSteamFarm/Steam/Interaction/Commands.cs +++ b/ArchiSteamFarm/Steam/Interaction/Commands.cs @@ -1337,8 +1337,7 @@ public sealed class Commands { } if (Bot.CardsFarmer.NowFarming && Bot.CardsFarmer.GamesToFarmReadOnly.Any(game => appIDs.Contains(game.AppID))) { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Bot.CardsFarmer.StopFarming().ConfigureAwait(false); await Bot.CardsFarmer.StartFarming().ConfigureAwait(false); } @@ -1493,8 +1492,7 @@ public sealed class Commands { break; case true when Bot.CardsFarmer.GamesToFarmReadOnly.Any(game => appIDs.Contains(game.AppID)): - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Bot.CardsFarmer.StopFarming().ConfigureAwait(false); await Bot.CardsFarmer.StartFarming().ConfigureAwait(false); } @@ -1559,8 +1557,7 @@ public sealed class Commands { } if (Bot.CardsFarmer.NowFarming && Bot.CardsFarmer.GamesToFarmReadOnly.Any(game => appIDs.Contains(game.AppID))) { - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Bot.CardsFarmer.StopFarming().ConfigureAwait(false); await Bot.CardsFarmer.StartFarming().ConfigureAwait(false); } @@ -1695,7 +1692,7 @@ public sealed class Commands { StringBuilder response = new(); foreach (InventoryAppData appData in inventory.Values) { - foreach (InventoryContextData? contextData in appData.Contexts.Values) { + foreach (InventoryContextData contextData in appData.Contexts.Values) { if (response.Length > 0) { response.AppendLine(); } diff --git a/ArchiSteamFarm/Steam/Security/MobileAuthenticator.cs b/ArchiSteamFarm/Steam/Security/MobileAuthenticator.cs index 13879c922..5df32ad75 100644 --- a/ArchiSteamFarm/Steam/Security/MobileAuthenticator.cs +++ b/ArchiSteamFarm/Steam/Security/MobileAuthenticator.cs @@ -50,7 +50,7 @@ public sealed class MobileAuthenticator : IDisposable { // For how many minutes we can assume that SteamTimeDifference is correct private const byte SteamTimeTTL = 15; - internal static readonly ImmutableSortedSet CodeCharacters = ImmutableSortedSet.Create('2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'T', 'V', 'W', 'X', 'Y'); + internal static readonly ImmutableSortedSet CodeCharacters = ['2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'T', 'V', 'W', 'X', 'Y']; private static readonly SemaphoreSlim TimeSemaphore = new(1, 1); @@ -194,7 +194,7 @@ public sealed class MobileAuthenticator : IDisposable { return null; } - foreach (Confirmation? confirmation in response.Confirmations.Where(static confirmation => (confirmation.ConfirmationType == Confirmation.EConfirmationType.Unknown) || !Enum.IsDefined(confirmation.ConfirmationType))) { + foreach (Confirmation confirmation in response.Confirmations.Where(static confirmation => (confirmation.ConfirmationType == Confirmation.EConfirmationType.Unknown) || !Enum.IsDefined(confirmation.ConfirmationType))) { Bot.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(confirmation.ConfirmationType), $"{confirmation.ConfirmationType} ({confirmation.ConfirmationTypeName ?? "null"})")); } @@ -394,8 +394,7 @@ public sealed class MobileAuthenticator : IDisposable { await ASF.ConfirmationsSemaphore.WaitAsync().ConfigureAwait(false); - Utilities.InBackground( - async () => { + Utilities.InBackground(async () => { await Task.Delay(confirmationsLimiterDelay * 1000).ConfigureAwait(false); ASF.ConfirmationsSemaphore.Release(); } diff --git a/ArchiSteamFarm/Steam/Storage/BotConfig.cs b/ArchiSteamFarm/Steam/Storage/BotConfig.cs index b87497067..5f63c7d66 100644 --- a/ArchiSteamFarm/Steam/Storage/BotConfig.cs +++ b/ArchiSteamFarm/Steam/Storage/BotConfig.cs @@ -129,16 +129,16 @@ public sealed class BotConfig { public static readonly ImmutableList DefaultGamesPlayedWhileIdle = []; [PublicAPI] - public static readonly ImmutableHashSet DefaultLootableTypes = ImmutableHashSet.Create(EAssetType.BoosterPack, EAssetType.FoilTradingCard, EAssetType.TradingCard); + public static readonly ImmutableHashSet DefaultLootableTypes = [EAssetType.BoosterPack, EAssetType.FoilTradingCard, EAssetType.TradingCard]; [PublicAPI] - public static readonly ImmutableHashSet DefaultMatchableTypes = ImmutableHashSet.Create(EAssetType.TradingCard); + public static readonly ImmutableHashSet DefaultMatchableTypes = [EAssetType.TradingCard]; [PublicAPI] public static readonly ImmutableDictionary DefaultSteamUserPermissions = ImmutableDictionary.Empty; [PublicAPI] - public static readonly ImmutableHashSet DefaultTransferableTypes = ImmutableHashSet.Create(EAssetType.BoosterPack, EAssetType.FoilTradingCard, EAssetType.TradingCard); + public static readonly ImmutableHashSet DefaultTransferableTypes = [EAssetType.BoosterPack, EAssetType.FoilTradingCard, EAssetType.TradingCard]; [JsonInclude] public bool AcceptGifts { get; private init; } = DefaultAcceptGifts;