diff --git a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/CatAPI.cs b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/CatAPI.cs index daf4444df..4746e4c5f 100644 --- a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/CatAPI.cs +++ b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/CatAPI.cs @@ -38,7 +38,7 @@ namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin { throw new ArgumentNullException(nameof(webBrowser)); } - Uri request = new(URL + "/meow"); + Uri request = new($"{URL}/meow"); ObjectResponse? response = await webBrowser.UrlGetToJsonObject(request).ConfigureAwait(false); diff --git a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs index a94a8e8a8..0d1dd7be9 100644 --- a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs +++ b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs @@ -70,7 +70,7 @@ namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin { switch (configProperty) { case nameof(ExamplePlugin) + "TestProperty" when configValue.Type == JTokenType.Boolean: bool exampleBooleanValue = configValue.Value(); - ASF.ArchiLogger.LogGenericInfo(nameof(ExamplePlugin) + "TestProperty boolean property has been found with a value of: " + exampleBooleanValue); + ASF.ArchiLogger.LogGenericInfo($"{nameof(ExamplePlugin)}TestProperty boolean property has been found with a value of: {exampleBooleanValue}"); break; } @@ -121,7 +121,7 @@ namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin { // In general you should do that only when you have a particular need of custom modules or alike, since ASF's plugin system will always provide bot to you as a function argument public void OnBotInit(Bot bot) { // Apart of those two that are already provided by ASF, you can also initialize your own logger with your plugin's name, if needed - bot.ArchiLogger.LogGenericInfo("Our bot named " + bot.BotName + " has been initialized, and we're letting you know about it from our " + nameof(ExamplePlugin) + "!"); + bot.ArchiLogger.LogGenericInfo($"Our bot named {bot.BotName} has been initialized, and we're letting you know about it from our {nameof(ExamplePlugin)}!"); ASF.ArchiLogger.LogGenericWarning("In case we won't have a bot reference or have something process-wide to log, we can also use ASF's logger!"); } @@ -177,7 +177,7 @@ namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin { // At this point you can access core ASF's functionality, such as logging, but more advanced structures (like ASF's WebBrowser) will be available in OnASFInit(), which itself takes place after every plugin gets OnLoaded() // Typically you should use this function only for preparing core structures of your plugin, and optionally also sending a message to the user (e.g. support link, welcome message or similar), ASF-specific things should usually happen in OnASFInit() public void OnLoaded() { - ASF.ArchiLogger.LogGenericInfo("Hey! Thanks for checking if our example plugin works fine, this is a confirmation that indeed " + nameof(OnLoaded) + "() method was called!"); + ASF.ArchiLogger.LogGenericInfo($"Hey! Thanks for checking if our example plugin works fine, this is a confirmation that indeed {nameof(OnLoaded)}() method was called!"); ASF.ArchiLogger.LogGenericInfo("Good luck in whatever you're doing!"); } } diff --git a/ArchiSteamFarm.CustomPlugins.PeriodicGC/PeriodicGCPlugin.cs b/ArchiSteamFarm.CustomPlugins.PeriodicGC/PeriodicGCPlugin.cs index e1ceab284..97ad05aaa 100644 --- a/ArchiSteamFarm.CustomPlugins.PeriodicGC/PeriodicGCPlugin.cs +++ b/ArchiSteamFarm.CustomPlugins.PeriodicGC/PeriodicGCPlugin.cs @@ -43,7 +43,7 @@ namespace ArchiSteamFarm.CustomPlugins.PeriodicGC { public void OnLoaded() { TimeSpan timeSpan = TimeSpan.FromSeconds(GCPeriod); - ASF.ArchiLogger.LogGenericWarning("Periodic GC will occur every " + timeSpan.ToHumanReadable() + ". Please keep in mind that this plugin should be used for debugging tests only."); + ASF.ArchiLogger.LogGenericWarning($"Periodic GC will occur every {timeSpan.ToHumanReadable()}. Please keep in mind that this plugin should be used for debugging tests only."); lock (LockObject) { PeriodicGCTimer.Change(timeSpan, timeSpan); @@ -51,14 +51,14 @@ namespace ArchiSteamFarm.CustomPlugins.PeriodicGC { } private static void PerformGC(object? state = null) { - ASF.ArchiLogger.LogGenericWarning("Performing GC, current memory: " + (GC.GetTotalMemory(false) / 1024) + " KB."); + ASF.ArchiLogger.LogGenericWarning($"Performing GC, current memory: {GC.GetTotalMemory(false) / 1024} KB."); lock (LockObject) { GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true); } - ASF.ArchiLogger.LogGenericWarning("GC finished, current memory: " + (GC.GetTotalMemory(false) / 1024) + " KB."); + ASF.ArchiLogger.LogGenericWarning($"GC finished, current memory: {GC.GetTotalMemory(false) / 1024} KB."); } } } diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs index 13d033892..4496f94ea 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs @@ -39,7 +39,7 @@ using SteamKit2; namespace ArchiSteamFarm.OfficialPlugins.SteamTokenDumper { internal sealed class GlobalCache : SerializableFile { - private static string SharedFilePath => Path.Combine(ArchiSteamFarm.SharedInfo.ConfigDirectory, nameof(SteamTokenDumper) + ".cache"); + private static string SharedFilePath => Path.Combine(ArchiSteamFarm.SharedInfo.ConfigDirectory, $"{nameof(SteamTokenDumper)}.cache"); [JsonProperty(Required = Required.DisallowNull)] private readonly ConcurrentDictionary AppChangeNumbers = new(); diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs index 88fdea875..b53dc9529 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs @@ -497,7 +497,7 @@ namespace ArchiSteamFarm.OfficialPlugins.SteamTokenDumper { return; } - Uri request = new(SharedInfo.ServerURL + "/submit"); + Uri request = new($"{SharedInfo.ServerURL}/submit"); RequestData requestData = new(contributorSteamID, appTokens, packageTokens, depotKeys); ASF.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.SubmissionInProgress, appTokens.Count, packageTokens.Count, depotKeys.Count)); diff --git a/ArchiSteamFarm.Tests/SteamChatMessage.cs b/ArchiSteamFarm.Tests/SteamChatMessage.cs index f82774c9b..a69562f60 100644 --- a/ArchiSteamFarm.Tests/SteamChatMessage.cs +++ b/ArchiSteamFarm.Tests/SteamChatMessage.cs @@ -52,7 +52,7 @@ namespace ArchiSteamFarm.Tests { [TestMethod] public async Task DoesntSkipEmptyNewlines() { - string message = "asdf" + Environment.NewLine + Environment.NewLine + "asdf"; + string message = $"asdf{Environment.NewLine}{Environment.NewLine}asdf"; List output = await GetMessageParts(message).ToListAsync().ConfigureAwait(false); @@ -99,12 +99,12 @@ namespace ArchiSteamFarm.Tests { int longLineLength = maxMessageBytes - ReservedContinuationMessageBytes; string longLine = new('a', longLineLength - 2); - string message = longLine + @"\"; + string message = $@"{longLine}\"; List output = await GetMessageParts(message, isAccountLimited: isAccountLimited).ToListAsync().ConfigureAwait(false); Assert.AreEqual(1, output.Count); - Assert.AreEqual(message + @"\", output.First()); + Assert.AreEqual($@"{message}\", output.First()); } [DataRow(false)] @@ -115,19 +115,19 @@ namespace ArchiSteamFarm.Tests { int longLineLength = maxMessageBytes - ReservedContinuationMessageBytes; string longLine = new('a', longLineLength - 1); - string message = longLine + "["; + string message = $"{longLine}["; List output = await GetMessageParts(message, isAccountLimited: isAccountLimited).ToListAsync().ConfigureAwait(false); Assert.AreEqual(2, output.Count); Assert.AreEqual(longLine + ContinuationCharacter, output[0]); - Assert.AreEqual(ContinuationCharacter + @"\[", output[1]); + Assert.AreEqual($@"{ContinuationCharacter}\[", output[1]); } [TestMethod] public async Task NoNeedForAnySplittingWithNewlines() { - string message = "abcdef" + Environment.NewLine + "ghijkl" + Environment.NewLine + "mnopqr"; + string message = $"abcdef{Environment.NewLine}ghijkl{Environment.NewLine}mnopqr"; List output = await GetMessageParts(message).ToListAsync().ConfigureAwait(false); diff --git a/ArchiSteamFarm/Core/ASF.cs b/ArchiSteamFarm/Core/ASF.cs index efdadc2c0..ff56a0ad1 100644 --- a/ArchiSteamFarm/Core/ASF.cs +++ b/ArchiSteamFarm/Core/ASF.cs @@ -253,7 +253,7 @@ namespace ArchiSteamFarm.Core { return null; } - string targetFile = SharedInfo.ASF + "-" + SharedInfo.BuildInfo.Variant + ".zip"; + string targetFile = $"{SharedInfo.ASF}-{SharedInfo.BuildInfo.Variant}.zip"; GitHub.ReleaseResponse.Asset? binaryAsset = releaseResponse.Assets.FirstOrDefault(asset => !string.IsNullOrEmpty(asset.Name) && asset.Name!.Equals(targetFile, StringComparison.OrdinalIgnoreCase)); if (binaryAsset == null) { @@ -397,11 +397,11 @@ namespace ArchiSteamFarm.Core { using SHA256 hashingAlgorithm = SHA256.Create(); // ReSharper disable once RedundantSuppressNullableWarningExpression - required for .NET Framework - networkGroupText = "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Program.NetworkGroup!))).Replace("-", "", StringComparison.Ordinal); + networkGroupText = $"-{BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Program.NetworkGroup!))).Replace("-", "", StringComparison.Ordinal)}"; } else if (!string.IsNullOrEmpty(GlobalConfig.WebProxyText)) { using SHA256 hashingAlgorithm = SHA256.Create(); - networkGroupText = "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(GlobalConfig.WebProxyText!))).Replace("-", "", StringComparison.Ordinal); + networkGroupText = $"-{BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(GlobalConfig.WebProxyText!))).Replace("-", "", StringComparison.Ordinal)}"; } ConfirmationsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(ConfirmationsSemaphore) + networkGroupText).ConfigureAwait(false); @@ -412,10 +412,10 @@ namespace ArchiSteamFarm.Core { RateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(RateLimitingSemaphore) + networkGroupText).ConfigureAwait(false); WebLimitingSemaphores ??= new Dictionary(4) { - { ArchiWebHandler.SteamCommunityURL, (await PluginsCore.GetCrossProcessSemaphore(nameof(ArchiWebHandler) + networkGroupText + "-" + nameof(ArchiWebHandler.SteamCommunityURL)).ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { ArchiWebHandler.SteamHelpURL, (await PluginsCore.GetCrossProcessSemaphore(nameof(ArchiWebHandler) + networkGroupText + "-" + nameof(ArchiWebHandler.SteamHelpURL)).ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { ArchiWebHandler.SteamStoreURL, (await PluginsCore.GetCrossProcessSemaphore(nameof(ArchiWebHandler) + networkGroupText + "-" + nameof(ArchiWebHandler.SteamStoreURL)).ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { WebAPI.DefaultBaseAddress, (await PluginsCore.GetCrossProcessSemaphore(nameof(ArchiWebHandler) + networkGroupText + "-" + nameof(WebAPI)).ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) } + { ArchiWebHandler.SteamCommunityURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}{networkGroupText}-{nameof(ArchiWebHandler.SteamCommunityURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { ArchiWebHandler.SteamHelpURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}{networkGroupText}-{nameof(ArchiWebHandler.SteamHelpURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { ArchiWebHandler.SteamStoreURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}{networkGroupText}-{nameof(ArchiWebHandler.SteamStoreURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { WebAPI.DefaultBaseAddress, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}{networkGroupText}-{nameof(WebAPI)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) } }.ToImmutableDictionary(); } @@ -823,7 +823,7 @@ namespace ArchiSteamFarm.Core { private static async Task RegisterBots() { if ((GlobalConfig == null) || (GlobalDatabase == null) || (WebBrowser == null)) { - throw new ArgumentNullException(nameof(GlobalConfig) + " || " + nameof(GlobalDatabase) + " || " + nameof(WebBrowser)); + throw new ArgumentNullException($"{nameof(GlobalConfig)} || {nameof(GlobalDatabase)} || {nameof(WebBrowser)}"); } // Ensure that we ask for a list of servers if we don't have any saved servers available @@ -848,7 +848,7 @@ namespace ArchiSteamFarm.Core { HashSet botNames; try { - botNames = Directory.EnumerateFiles(SharedInfo.ConfigDirectory, "*" + SharedInfo.JsonConfigExtension).Select(Path.GetFileNameWithoutExtension).Where(botName => !string.IsNullOrEmpty(botName) && IsValidBotName(botName)).ToHashSet(Bot.BotsComparer)!; + botNames = Directory.EnumerateFiles(SharedInfo.ConfigDirectory, $"*{SharedInfo.JsonConfigExtension}").Select(Path.GetFileNameWithoutExtension).Where(botName => !string.IsNullOrEmpty(botName) && IsValidBotName(botName)).ToHashSet(Bot.BotsComparer)!; } catch (Exception e) { ArchiLogger.LogGenericException(e); @@ -1003,7 +1003,7 @@ namespace ArchiSteamFarm.Core { if (File.Exists(file)) { // This is possible only with files that we decided to leave in place during our backup function - string targetBackupFile = file + ".bak"; + string targetBackupFile = $"{file}.bak"; File.Move(file, targetBackupFile, true); } diff --git a/ArchiSteamFarm/Core/Debugging.cs b/ArchiSteamFarm/Core/Debugging.cs index 717ec54e2..a6bedfed3 100644 --- a/ArchiSteamFarm/Core/Debugging.cs +++ b/ArchiSteamFarm/Core/Debugging.cs @@ -37,10 +37,10 @@ namespace ArchiSteamFarm.Core { internal sealed class DebugListener : IDebugListener { public void WriteLine(string category, string msg) { if (string.IsNullOrEmpty(category) && string.IsNullOrEmpty(msg)) { - throw new InvalidOperationException(nameof(category) + " && " + nameof(msg)); + throw new InvalidOperationException($"{nameof(category)} && {nameof(msg)}"); } - ASF.ArchiLogger.LogGenericDebug(category + " | " + msg); + ASF.ArchiLogger.LogGenericDebug($"{category} | {msg}"); } } } diff --git a/ArchiSteamFarm/Core/OS.cs b/ArchiSteamFarm/Core/OS.cs index 3026f08c0..cac76995c 100644 --- a/ArchiSteamFarm/Core/OS.cs +++ b/ArchiSteamFarm/Core/OS.cs @@ -85,7 +85,7 @@ namespace ArchiSteamFarm.Core { description = "Unknown OS"; } - BackingVersion = framework + "; " + runtime + "; " + description; + BackingVersion = $"{framework}; {runtime}; {description}"; return BackingVersion; } @@ -120,7 +120,7 @@ namespace ArchiSteamFarm.Core { throw new ArgumentNullException(nameof(objectName)); } - return SharedInfo.AssemblyName + "-" + objectName; + return $"{SharedInfo.AssemblyName}-{objectName}"; } internal static void Init(GlobalConfig.EOptimizationMode optimizationMode) { @@ -153,7 +153,7 @@ namespace ArchiSteamFarm.Core { // At the same time it'd be the best if we avoided all special characters, such as '/' found e.g. in base64, as we can't be sure that it's not a prohibited character in regards to native OS implementation // Because of that, SHA256 is sufficient for our case, as it generates alphanumeric characters only, and is barely 256-bit long. We don't need any kind of complex cryptography or collision detection here, any hashing algorithm will do, and the shorter the better using (SHA256 hashingAlgorithm = SHA256.Create()) { - uniqueName = "Global\\" + GetOsResourceName(nameof(SingleInstance)) + "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Directory.GetCurrentDirectory()))).Replace("-", "", StringComparison.Ordinal); + uniqueName = $"Global\\{GetOsResourceName(nameof(SingleInstance))}-{BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Directory.GetCurrentDirectory()))).Replace("-", "", StringComparison.Ordinal)}"; } Mutex? singleInstance = null; @@ -195,7 +195,7 @@ namespace ArchiSteamFarm.Core { } if (!File.Exists(path) && !Directory.Exists(path)) { - ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, "!" + nameof(path))); + ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"!{nameof(path)}")); return; } diff --git a/ArchiSteamFarm/Core/Statistics.cs b/ArchiSteamFarm/Core/Statistics.cs index 75b123c13..9acec4289 100644 --- a/ArchiSteamFarm/Core/Statistics.cs +++ b/ArchiSteamFarm/Core/Statistics.cs @@ -112,7 +112,7 @@ namespace ArchiSteamFarm.Core { return; } - Uri request = new(URL + "/Api/HeartBeat"); + Uri request = new($"{URL}/Api/HeartBeat"); Dictionary data = new(2, StringComparer.Ordinal) { { "Guid", (ASF.GlobalDatabase?.Identifier ?? Guid.NewGuid()).ToString("N") }, @@ -221,7 +221,7 @@ namespace ArchiSteamFarm.Core { return; } - Uri request = new(URL + "/Api/Announce"); + Uri request = new($"{URL}/Api/Announce"); Dictionary data = new(9, StringComparer.Ordinal) { { "AvatarHash", avatarHash ?? "" }, @@ -258,7 +258,7 @@ namespace ArchiSteamFarm.Core { } private async Task?> GetListedUsers() { - Uri request = new(URL + "/Api/Bots"); + Uri request = new($"{URL}/Api/Bots"); ObjectResponse>? response = await Bot.ArchiWebHandler.WebBrowser.UrlGetToJsonObject>(request).ConfigureAwait(false); @@ -276,7 +276,7 @@ namespace ArchiSteamFarm.Core { bool? hasPublicInventory = await Bot.HasPublicInventory().ConfigureAwait(false); if (hasPublicInventory != true) { - Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(Bot.HasPublicInventory) + ": " + (hasPublicInventory?.ToString() ?? "null"))); + Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.HasPublicInventory)}: {hasPublicInventory?.ToString() ?? "null"}")); return hasPublicInventory; } @@ -287,21 +287,21 @@ namespace ArchiSteamFarm.Core { private async Task IsEligibleForMatching() { // Bot must have ASF 2FA if (!Bot.HasMobileAuthenticator) { - Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(Bot.HasMobileAuthenticator) + ": " + Bot.HasMobileAuthenticator)); + Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.HasMobileAuthenticator)}: {Bot.HasMobileAuthenticator}")); return false; } // Bot must have STM enable in TradingPreferences if (!Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher)) { - Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(Bot.BotConfig.TradingPreferences) + ": " + Bot.BotConfig.TradingPreferences)); + Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.BotConfig.TradingPreferences)}: {Bot.BotConfig.TradingPreferences}")); return false; } // Bot must have at least one accepted matchable type set if ((Bot.BotConfig.MatchableTypes.Count == 0) || Bot.BotConfig.MatchableTypes.All(type => !AcceptedMatchableTypes.Contains(type))) { - Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(Bot.BotConfig.MatchableTypes) + ": " + string.Join(", ", Bot.BotConfig.MatchableTypes))); + Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.BotConfig.MatchableTypes)}: {string.Join(", ", Bot.BotConfig.MatchableTypes)}")); return false; } @@ -310,7 +310,7 @@ namespace ArchiSteamFarm.Core { bool? hasValidApiKey = await Bot.ArchiWebHandler.HasValidApiKey().ConfigureAwait(false); if (hasValidApiKey != true) { - Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(Bot.ArchiWebHandler.HasValidApiKey) + ": " + (hasValidApiKey?.ToString() ?? "null"))); + Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.ArchiWebHandler.HasValidApiKey)}: {hasValidApiKey?.ToString() ?? "null"}")); return hasValidApiKey; } @@ -407,7 +407,7 @@ namespace ArchiSteamFarm.Core { if (Trading.IsEmptyForMatching(ourFullState, ourTradableState)) { // User doesn't have any more dupes in the inventory - Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(ourFullState) + " || " + nameof(ourTradableState))); + Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, $"{nameof(ourFullState)} || {nameof(ourTradableState)}")); return (false, false); } @@ -436,7 +436,7 @@ namespace ArchiSteamFarm.Core { break; } - Bot.ArchiLogger.LogGenericTrace(listedUser.SteamID + "..."); + Bot.ArchiLogger.LogGenericTrace($"{listedUser.SteamID}..."); byte? holdDuration = await Bot.ArchiWebHandler.GetTradeHoldDurationForUser(listedUser.SteamID, listedUser.TradeToken).ConfigureAwait(false); @@ -446,7 +446,7 @@ namespace ArchiSteamFarm.Core { continue; case > 0 when holdDuration.Value > maxTradeHoldDuration: - Bot.ArchiLogger.LogGenericTrace(holdDuration.Value + " > " + maxTradeHoldDuration); + Bot.ArchiLogger.LogGenericTrace($"{holdDuration.Value} > {maxTradeHoldDuration}"); continue; } @@ -662,7 +662,7 @@ namespace ArchiSteamFarm.Core { triedSteamIDs[listedUser.SteamID] = (++previousAttempt.Tries, previousAttempt.GivenAssetIDs, previousAttempt.ReceivedAssetIDs); - Bot.ArchiLogger.LogGenericTrace(Bot.SteamID + " <- " + string.Join(", ", itemsToReceive.Select(item => item.RealAppID + "/" + item.Type + "-" + item.ClassID + " #" + item.Amount)) + " | " + string.Join(", ", itemsToGive.Select(item => item.RealAppID + "/" + item.Type + "-" + item.ClassID + " #" + item.Amount)) + " -> " + listedUser.SteamID); + Bot.ArchiLogger.LogGenericTrace($"{Bot.SteamID} <- {string.Join(", ", itemsToReceive.Select(item => $"{item.RealAppID}/{item.Type}-{item.ClassID} #{item.Amount}"))} | {string.Join(", ", itemsToGive.Select(item => $"{item.RealAppID}/{item.Type}-{item.ClassID} #{item.Amount}"))} -> {listedUser.SteamID}"); (bool success, HashSet? mobileTradeOfferIDs) = await Bot.ArchiWebHandler.SendTradeOffer(listedUser.SteamID, itemsToGive, itemsToReceive, listedUser.TradeToken, true).ConfigureAwait(false); diff --git a/ArchiSteamFarm/Core/Utilities.cs b/ArchiSteamFarm/Core/Utilities.cs index 369543f18..8929e4e59 100644 --- a/ArchiSteamFarm/Core/Utilities.cs +++ b/ArchiSteamFarm/Core/Utilities.cs @@ -49,7 +49,7 @@ namespace ArchiSteamFarm.Core { } if (args.Length <= argsToSkip) { - throw new InvalidOperationException(nameof(args.Length) + " && " + nameof(argsToSkip)); + throw new InvalidOperationException($"{nameof(args.Length)} && {nameof(argsToSkip)}"); } if (string.IsNullOrEmpty(delimiter)) { @@ -228,7 +228,7 @@ namespace ArchiSteamFarm.Core { [PublicAPI] public static int RandomNext(int minValue, int maxValue) { if (minValue > maxValue) { - throw new InvalidOperationException(nameof(minValue) + " && " + nameof(maxValue)); + throw new InvalidOperationException($"{nameof(minValue)} && {nameof(maxValue)}"); } if (minValue >= maxValue - 1) { diff --git a/ArchiSteamFarm/Helpers/SerializableFile.cs b/ArchiSteamFarm/Helpers/SerializableFile.cs index 12b4d02f6..2e41f6bcb 100644 --- a/ArchiSteamFarm/Helpers/SerializableFile.cs +++ b/ArchiSteamFarm/Helpers/SerializableFile.cs @@ -87,7 +87,7 @@ namespace ArchiSteamFarm.Helpers { } // We always want to write entire content to temporary file first, in order to never load corrupted data, also when target file doesn't exist - string newFilePath = FilePath + ".new"; + string newFilePath = $"{FilePath}.new"; if (File.Exists(FilePath)) { string currentJson = await File.ReadAllTextAsync(FilePath!).ConfigureAwait(false); @@ -138,7 +138,7 @@ namespace ArchiSteamFarm.Helpers { throw new ArgumentNullException(nameof(json)); } - string newFilePath = filePath + ".new"; + string newFilePath = $"{filePath}.new"; await GlobalFileSemaphore.WaitAsync().ConfigureAwait(false); diff --git a/ArchiSteamFarm/IPC/ArchiKestrel.cs b/ArchiSteamFarm/IPC/ArchiKestrel.cs index e04f5cfc3..9ae2b9999 100644 --- a/ArchiSteamFarm/IPC/ArchiKestrel.cs +++ b/ArchiSteamFarm/IPC/ArchiKestrel.cs @@ -104,7 +104,7 @@ namespace ArchiSteamFarm.IPC { if (!string.IsNullOrEmpty(json)) { JObject jObject = JObject.Parse(json); - ASF.ArchiLogger.LogGenericDebug(SharedInfo.IPCConfigFile + ": " + jObject.ToString(Formatting.Indented)); + ASF.ArchiLogger.LogGenericDebug($"{SharedInfo.IPCConfigFile}: {jObject.ToString(Formatting.Indented)}"); } } catch (Exception e) { ASF.ArchiLogger.LogGenericException(e); diff --git a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs index 6f5f55b0c..267125d2e 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs @@ -271,7 +271,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { } if ((request.Type == ASF.EUserInputType.None) || !Enum.IsDefined(typeof(ASF.EUserInputType), request.Type) || string.IsNullOrEmpty(request.Value)) { - return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, 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); diff --git a/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs b/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs index 7aa6fd3ef..ff98bb949 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs @@ -60,7 +60,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { } if (!HttpContext.WebSockets.IsWebSocketRequest) { - return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, 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 diff --git a/ArchiSteamFarm/IPC/Startup.cs b/ArchiSteamFarm/IPC/Startup.cs index 2d310f99d..4a9bd347b 100644 --- a/ArchiSteamFarm/IPC/Startup.cs +++ b/ArchiSteamFarm/IPC/Startup.cs @@ -175,7 +175,7 @@ namespace ArchiSteamFarm.IPC { options.DisplayRequestDuration(); options.EnableDeepLinking(); options.ShowExtensions(); - options.SwaggerEndpoint(SharedInfo.ASF + "/swagger.json", SharedInfo.ASF + " API"); + options.SwaggerEndpoint($"{SharedInfo.ASF}/swagger.json", $"{SharedInfo.ASF} API"); } ); } @@ -202,7 +202,7 @@ namespace ArchiSteamFarm.IPC { if ((addressParts.Length != 2) || !IPAddress.TryParse(addressParts[0], out IPAddress? ipAddress) || !byte.TryParse(addressParts[1], out byte prefixLength)) { ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(knownNetworkText))); - ASF.ArchiLogger.LogGenericDebug(nameof(knownNetworkText) + ": " + knownNetworkText); + ASF.ArchiLogger.LogGenericDebug($"{nameof(knownNetworkText)}: {knownNetworkText}"); continue; } @@ -245,7 +245,7 @@ namespace ArchiSteamFarm.IPC { options => { options.AddSecurityDefinition( nameof(GlobalConfig.IPCPassword), new OpenApiSecurityScheme { - Description = nameof(GlobalConfig.IPCPassword) + " authentication using request headers. Check " + SharedInfo.ProjectURL + "/wiki/IPC#authentication for more info.", + Description = $"{nameof(GlobalConfig.IPCPassword)} authentication using request headers. Check {SharedInfo.ProjectURL}/wiki/IPC#authentication for more info.", In = ParameterLocation.Header, Name = ApiAuthenticationMiddleware.HeadersField, Type = SecuritySchemeType.ApiKey @@ -285,7 +285,7 @@ namespace ArchiSteamFarm.IPC { Url = new Uri(SharedInfo.LicenseURL) }, - Title = SharedInfo.ASF + " API" + Title = $"{SharedInfo.ASF} API" } ); diff --git a/ArchiSteamFarm/IPC/WebUtilities.cs b/ArchiSteamFarm/IPC/WebUtilities.cs index ca0080e0a..b5f84a1be 100644 --- a/ArchiSteamFarm/IPC/WebUtilities.cs +++ b/ArchiSteamFarm/IPC/WebUtilities.cs @@ -37,7 +37,7 @@ namespace ArchiSteamFarm.IPC { throw new ArgumentNullException(nameof(type)); } - return type.GenericTypeArguments.Length == 0 ? type.FullName : type.Namespace + "." + type.Name + string.Join("", type.GenericTypeArguments.Select(innerType => '[' + innerType.GetUnifiedName() + ']')); + return type.GenericTypeArguments.Length == 0 ? type.FullName : $"{type.Namespace}.{type.Name}{string.Join("", type.GenericTypeArguments.Select(innerType => $"[{innerType.GetUnifiedName()}]"))}"; } internal static Type? ParseType(string typeText) { @@ -58,7 +58,7 @@ namespace ArchiSteamFarm.IPC { return null; } - return Type.GetType(typeText + "," + typeText[..index]); + return Type.GetType($"{typeText},{typeText[..index]}"); } internal static async Task WriteJsonAsync(this HttpResponse response, TValue? value, JsonSerializerSettings? jsonSerializerSettings = null) { diff --git a/ArchiSteamFarm/NLog/ArchiLogger.cs b/ArchiSteamFarm/NLog/ArchiLogger.cs index d07f5939a..0558b90ac 100644 --- a/ArchiSteamFarm/NLog/ArchiLogger.cs +++ b/ArchiSteamFarm/NLog/ArchiLogger.cs @@ -138,16 +138,16 @@ namespace ArchiSteamFarm.NLog { } if (((chatGroupID == 0) || (chatID == 0)) && (steamID == 0)) { - throw new InvalidOperationException("((" + nameof(chatGroupID) + " || " + nameof(chatID) + ") && " + nameof(steamID) + ")"); + throw new InvalidOperationException($"(({nameof(chatGroupID)} || {nameof(chatID)}) && {nameof(steamID)})"); } - StringBuilder loggedMessage = new(previousMethodName + "() " + message + " " + (echo ? "->" : "<-") + " "); + StringBuilder loggedMessage = new($"{previousMethodName}() {message} {(echo ? "->" : "<-")} "); if ((chatGroupID != 0) && (chatID != 0)) { - loggedMessage.Append(chatGroupID + "-" + chatID); + loggedMessage.Append($"{chatGroupID}-{chatID}"); if (steamID != 0) { - loggedMessage.Append("/" + steamID); + loggedMessage.Append($"/{steamID}"); } } else if (steamID != 0) { loggedMessage.Append(steamID); @@ -225,7 +225,7 @@ namespace ArchiSteamFarm.NLog { ulong steamID64 = steamID; - string loggedMessage = previousMethodName + "() " + steamID.AccountType + " " + steamID64 + (handled.HasValue ? " = " + handled.Value : ""); + string loggedMessage = $"{previousMethodName}() {steamID.AccountType} {steamID64}{(handled.HasValue ? $" = {handled.Value}" : "")}"; LogEventInfo logEventInfo = new(LogLevel.Trace, Logger.Name, loggedMessage) { Properties = { diff --git a/ArchiSteamFarm/NLog/Logging.cs b/ArchiSteamFarm/NLog/Logging.cs index e0ee638aa..9e688ee34 100644 --- a/ArchiSteamFarm/NLog/Logging.cs +++ b/ArchiSteamFarm/NLog/Logging.cs @@ -322,7 +322,7 @@ namespace ArchiSteamFarm.NLog { OnUserInputStart(); try { - Console.Write(@">> " + Strings.EnterCommand); + Console.Write($@">> {Strings.EnterCommand}"); string? command = ConsoleReadLine(); if (string.IsNullOrEmpty(command)) { @@ -347,12 +347,12 @@ namespace ArchiSteamFarm.NLog { Bot? targetBot = Bot.Bots?.OrderBy(bot => bot.Key, Bot.BotsComparer).Select(bot => bot.Value).FirstOrDefault(); if (targetBot == null) { - Console.WriteLine(@"<< " + Strings.ErrorNoBotsDefined); + Console.WriteLine($@"<< {Strings.ErrorNoBotsDefined}"); continue; } - Console.WriteLine(@"<> " + Strings.Executing); + Console.WriteLine($@"<> {Strings.Executing}"); ulong steamOwnerID = ASF.GlobalConfig?.SteamOwnerID ?? GlobalConfig.DefaultSteamOwnerID; @@ -365,7 +365,7 @@ namespace ArchiSteamFarm.NLog { continue; } - Console.WriteLine(@"<< " + response); + Console.WriteLine($@"<< {response}"); } finally { OnUserInputEnd(); } diff --git a/ArchiSteamFarm/Program.cs b/ArchiSteamFarm/Program.cs index 6beea4a8b..ed75f90c4 100644 --- a/ArchiSteamFarm/Program.cs +++ b/ArchiSteamFarm/Program.cs @@ -254,7 +254,7 @@ namespace ArchiSteamFarm { } if (globalConfig.Debug) { - ASF.ArchiLogger.LogGenericDebug(globalConfigFile + ": " + JsonConvert.SerializeObject(globalConfig, Formatting.Indented)); + ASF.ArchiLogger.LogGenericDebug($"{globalConfigFile}: {JsonConvert.SerializeObject(globalConfig, Formatting.Indented)}"); } if (!string.IsNullOrEmpty(globalConfig.CurrentCulture)) { @@ -333,7 +333,7 @@ namespace ArchiSteamFarm { if (currentStringObjects.Count < defaultStringObjects.Count) { float translationCompleteness = currentStringObjects.Count / (float) defaultStringObjects.Count; - ASF.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.TranslationIncomplete, CultureInfo.CurrentUICulture.Name + " (" + CultureInfo.CurrentUICulture.EnglishName + ")", translationCompleteness.ToString("P1", CultureInfo.CurrentCulture))); + ASF.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.TranslationIncomplete, $"{CultureInfo.CurrentUICulture.Name} ({CultureInfo.CurrentUICulture.EnglishName})", translationCompleteness.ToString("P1", CultureInfo.CurrentCulture))); } return true; @@ -367,7 +367,7 @@ namespace ArchiSteamFarm { // If debugging is on, we prepare debug directory prior to running if (Debugging.IsUserDebugging) { if (Debugging.IsDebugConfigured) { - ASF.ArchiLogger.LogGenericDebug(globalDatabaseFile + ": " + JsonConvert.SerializeObject(ASF.GlobalDatabase, Formatting.Indented)); + ASF.ArchiLogger.LogGenericDebug($"{globalDatabaseFile}: {JsonConvert.SerializeObject(ASF.GlobalDatabase, Formatting.Indented)}"); } Logging.EnableTraceLogging(); diff --git a/ArchiSteamFarm/SharedInfo.cs b/ArchiSteamFarm/SharedInfo.cs index 3a23d5837..a0edb660e 100644 --- a/ArchiSteamFarm/SharedInfo.cs +++ b/ArchiSteamFarm/SharedInfo.cs @@ -83,7 +83,7 @@ namespace ArchiSteamFarm { } } - internal static string ProgramIdentifier => PublicIdentifier + " V" + Version + " (" + BuildInfo.Variant + "/" + ModuleVersion + " | " + OS.Version + ")"; + internal static string ProgramIdentifier => $"{PublicIdentifier} V{Version} ({BuildInfo.Variant}/{ModuleVersion} | {OS.Version})"; internal static string PublicIdentifier => AssemblyName + (BuildInfo.IsCustomBuild ? "-custom" : PluginsCore.HasCustomPluginsLoaded ? "-modded" : ""); internal static Version Version => Assembly.GetExecutingAssembly().GetName().Version ?? throw new InvalidOperationException(nameof(Version)); diff --git a/ArchiSteamFarm/Steam/Bot.cs b/ArchiSteamFarm/Steam/Bot.cs index f94d72a62..28d16c329 100644 --- a/ArchiSteamFarm/Steam/Bot.cs +++ b/ArchiSteamFarm/Steam/Bot.cs @@ -568,7 +568,7 @@ namespace ArchiSteamFarm.Steam { } if (itemsPerSet < itemsPerClassID.Count) { - throw new InvalidOperationException(nameof(inventory) + " && " + nameof(amountsToExtract)); + throw new InvalidOperationException($"{nameof(inventory)} && {nameof(amountsToExtract)}"); } if (itemsPerSet > itemsPerClassID.Count) { @@ -985,7 +985,7 @@ namespace ArchiSteamFarm.Steam { throw new ArgumentNullException(nameof(botName)); } - return Environment.NewLine + "<" + botName + "> " + response; + return $"{Environment.NewLine}<{botName}> {response}"; } internal async Task<(uint PlayableAppID, DateTime IgnoredUntil, bool IgnoredGlobally)> GetAppDataForIdling(uint appID, float hoursPlayed, bool allowRecursiveDiscovery = true, bool optimisticDiscovery = true) { @@ -1495,7 +1495,7 @@ namespace ArchiSteamFarm.Steam { } if (Debugging.IsDebugConfigured) { - ASF.ArchiLogger.LogGenericDebug(configFilePath + ": " + JsonConvert.SerializeObject(botConfig, Formatting.Indented)); + ASF.ArchiLogger.LogGenericDebug($"{configFilePath}: {JsonConvert.SerializeObject(botConfig, Formatting.Indented)}"); } if (!string.IsNullOrEmpty(latestJson)) { @@ -1524,7 +1524,7 @@ namespace ArchiSteamFarm.Steam { } if (Debugging.IsDebugConfigured) { - ASF.ArchiLogger.LogGenericDebug(databaseFilePath + ": " + JsonConvert.SerializeObject(botDatabase, Formatting.Indented)); + ASF.ArchiLogger.LogGenericDebug($"{databaseFilePath}: {JsonConvert.SerializeObject(botDatabase, Formatting.Indented)}"); } Bot bot; @@ -2138,7 +2138,7 @@ namespace ArchiSteamFarm.Steam { private static async Task LimitLoginRequestsAsync() { if ((ASF.LoginSemaphore == null) || (ASF.LoginRateLimitingSemaphore == null)) { - ASF.ArchiLogger.LogNullError(nameof(ASF.LoginSemaphore) + " || " + nameof(ASF.LoginRateLimitingSemaphore)); + ASF.ArchiLogger.LogNullError($"{nameof(ASF.LoginSemaphore)} || {nameof(ASF.LoginRateLimitingSemaphore)}"); return; } @@ -2476,7 +2476,7 @@ namespace ArchiSteamFarm.Steam { } if ((notification.chat_group_id == 0) || (notification.chat_id == 0) || (notification.steamid_sender == 0)) { - ArchiLogger.LogNullError(nameof(notification.chat_group_id) + " || " + nameof(notification.chat_id) + " || " + nameof(notification.steamid_sender)); + ArchiLogger.LogNullError($"{nameof(notification.chat_group_id)} || {nameof(notification.chat_id)} || {nameof(notification.steamid_sender)}"); return; } @@ -2716,7 +2716,7 @@ namespace ArchiSteamFarm.Steam { AccountFlags = callback.AccountFlags; SteamID = callback.ClientSteamID ?? throw new InvalidOperationException(nameof(callback.ClientSteamID)); - ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.BotLoggedOn, SteamID + (!string.IsNullOrEmpty(callback.VanityURL) ? "/" + callback.VanityURL : ""))); + ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.BotLoggedOn, SteamID + (!string.IsNullOrEmpty(callback.VanityURL) ? $"/{callback.VanityURL}" : ""))); // Old status for these doesn't matter, we'll update them if needed InvalidPasswordFailures = TwoFactorCodeFailures = 0; @@ -3091,7 +3091,7 @@ namespace ArchiSteamFarm.Steam { PastNotifications.TryRemove(notification, out _); } - ArchiLogger.LogGenericTrace(notification + " = " + count); + ArchiLogger.LogGenericTrace($"{notification} = {count}"); switch (notification) { case UserNotificationsCallback.EUserNotification.Gifts when newNotification && BotConfig.AcceptGifts: @@ -3151,7 +3151,7 @@ namespace ArchiSteamFarm.Steam { (string? key, string? name) = BotDatabase.GetGameToRedeemInBackground(); if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(name)) { - ArchiLogger.LogNullError(nameof(key) + " || " + nameof(name)); + ArchiLogger.LogNullError($"{nameof(key)} || {nameof(name)}"); break; } @@ -3177,7 +3177,7 @@ namespace ArchiSteamFarm.Steam { } } - ArchiLogger.LogGenericDebug(result.Items?.Count > 0 ? string.Format(CultureInfo.CurrentCulture, Strings.BotRedeemWithItems, key, result.Result + "/" + result.PurchaseResultDetail, string.Join(", ", result.Items)) : string.Format(CultureInfo.CurrentCulture, Strings.BotRedeem, key, result.Result + "/" + result.PurchaseResultDetail)); + ArchiLogger.LogGenericDebug(result.Items?.Count > 0 ? string.Format(CultureInfo.CurrentCulture, Strings.BotRedeemWithItems, key, $"{result.Result}/{result.PurchaseResultDetail}", string.Join(", ", result.Items)) : string.Format(CultureInfo.CurrentCulture, Strings.BotRedeem, key, $"{result.Result}/{result.PurchaseResultDetail}")); bool rateLimited = false; bool redeemed = false; @@ -3219,7 +3219,7 @@ namespace ArchiSteamFarm.Steam { name = string.Join(", ", result.Items.Values); } - string logEntry = name + DefaultBackgroundKeysRedeemerSeparator + "[" + result.PurchaseResultDetail + "]" + (result.Items?.Count > 0 ? DefaultBackgroundKeysRedeemerSeparator + string.Join(", ", result.Items) : "") + DefaultBackgroundKeysRedeemerSeparator + key; + string logEntry = $"{name}{DefaultBackgroundKeysRedeemerSeparator}[{result.PurchaseResultDetail}]{(result.Items?.Count > 0 ? DefaultBackgroundKeysRedeemerSeparator + string.Join(", ", result.Items) : "")}{DefaultBackgroundKeysRedeemerSeparator}{key}"; string filePath = GetFilePath(redeemed ? EFileType.KeysToRedeemUsed : EFileType.KeysToRedeemUnused); diff --git a/ArchiSteamFarm/Steam/Exchange/Trading.cs b/ArchiSteamFarm/Steam/Exchange/Trading.cs index 23bf2e350..8f7e4bf03 100644 --- a/ArchiSteamFarm/Steam/Exchange/Trading.cs +++ b/ArchiSteamFarm/Steam/Exchange/Trading.cs @@ -541,14 +541,14 @@ namespace ArchiSteamFarm.Steam.Exchange { if (tradeOffer.OtherSteamID64 != 0) { // Always accept trades from SteamMasterID if (Bot.HasAccess(tradeOffer.OtherSteamID64, BotConfig.EAccess.Master)) { - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Accepted, nameof(tradeOffer.OtherSteamID64) + " " + tradeOffer.OtherSteamID64 + ": " + BotConfig.EAccess.Master)); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Accepted, $"{nameof(tradeOffer.OtherSteamID64)} {tradeOffer.OtherSteamID64}: {BotConfig.EAccess.Master}")); return ParseTradeResult.EResult.Accepted; } // Always deny trades from blacklisted steamIDs if (Bot.IsBlacklistedFromTrades(tradeOffer.OtherSteamID64)) { - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Blacklisted, nameof(tradeOffer.OtherSteamID64) + " " + tradeOffer.OtherSteamID64)); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Blacklisted, $"{nameof(tradeOffer.OtherSteamID64)} {tradeOffer.OtherSteamID64}")); return ParseTradeResult.EResult.Blacklisted; } @@ -558,7 +558,7 @@ namespace ArchiSteamFarm.Steam.Exchange { switch (tradeOffer.ItemsToGive.Count) { case 0 when tradeOffer.ItemsToReceive.Count == 0: // If it's steam issue, try again later - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.TryAgain, nameof(tradeOffer.ItemsToReceive.Count) + " = 0")); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.TryAgain, $"{nameof(tradeOffer.ItemsToReceive.Count)} = 0")); return ParseTradeResult.EResult.TryAgain; case 0: @@ -569,13 +569,13 @@ namespace ArchiSteamFarm.Steam.Exchange { switch (acceptDonations) { case true when acceptBotTrades: // If we accept donations and bot trades, accept it right away - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Accepted, nameof(acceptDonations) + " = " + true + " && " + nameof(acceptBotTrades) + " = " + true)); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Accepted, $"{nameof(acceptDonations)} = {true} && {nameof(acceptBotTrades)} = {true}")); return ParseTradeResult.EResult.Accepted; case false when !acceptBotTrades: // If we don't accept donations, neither bot trades, deny it right away - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(acceptDonations) + " = " + false + " && " + nameof(acceptBotTrades) + " = " + false)); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, $"{nameof(acceptDonations)} = {false} && {nameof(acceptBotTrades)} = {false}")); return ParseTradeResult.EResult.Rejected; } @@ -585,28 +585,28 @@ namespace ArchiSteamFarm.Steam.Exchange { ParseTradeResult.EResult result = (acceptDonations && !isBotTrade) || (acceptBotTrades && isBotTrade) ? ParseTradeResult.EResult.Accepted : ParseTradeResult.EResult.Rejected; - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, result, nameof(acceptDonations) + " = " + acceptDonations + " && " + nameof(acceptBotTrades) + " = " + acceptBotTrades + " && " + nameof(isBotTrade) + " = " + isBotTrade)); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, result, $"{nameof(acceptDonations)} = {acceptDonations} && {nameof(acceptBotTrades)} = {acceptBotTrades} && {nameof(isBotTrade)} = {isBotTrade}")); return result; } // If we don't have SteamTradeMatcher enabled, this is the end for us if (!Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher)) { - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(BotConfig.ETradingPreferences.SteamTradeMatcher) + " = " + false)); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, $"{nameof(BotConfig.ETradingPreferences.SteamTradeMatcher)} = {false}")); return ParseTradeResult.EResult.Rejected; } // Decline trade if we're giving more count-wise, this is a very naive pre-check, it'll be strengthened in more detailed fair types exchange next if (tradeOffer.ItemsToGive.Count > tradeOffer.ItemsToReceive.Count) { - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(tradeOffer.ItemsToGive.Count) + ": " + tradeOffer.ItemsToGive.Count + " > " + tradeOffer.ItemsToReceive.Count)); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, $"{nameof(tradeOffer.ItemsToGive.Count)}: {tradeOffer.ItemsToGive.Count} > {tradeOffer.ItemsToReceive.Count}")); return ParseTradeResult.EResult.Rejected; } // Decline trade if we're requested to handle any not-accepted item type or if it's not fair games/types exchange if (!tradeOffer.IsValidSteamItemsRequest(Bot.BotConfig.MatchableTypes) || !IsFairExchange(tradeOffer.ItemsToGive, tradeOffer.ItemsToReceive)) { - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(tradeOffer.IsValidSteamItemsRequest) + " || " + nameof(IsFairExchange))); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, $"{nameof(tradeOffer.IsValidSteamItemsRequest)} || {nameof(IsFairExchange)}")); return ParseTradeResult.EResult.Rejected; } @@ -626,7 +626,7 @@ namespace ArchiSteamFarm.Steam.Exchange { // If user has a trade hold, we add extra logic // If trade hold duration exceeds our max, or user asks for cards with short lifespan, reject the trade case > 0 when (holdDuration.Value > ASF.GlobalConfig.MaxTradeHoldDuration) || tradeOffer.ItemsToGive.Any(item => item.Type is Asset.EType.FoilTradingCard or Asset.EType.TradingCard && CardsFarmer.SalesBlacklist.Contains(item.RealAppID)): - Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(holdDuration) + " > 0: " + holdDuration.Value)); + Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, $"{nameof(holdDuration)} > 0: {holdDuration.Value}")); return ParseTradeResult.EResult.Rejected; } diff --git a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs index 7011f95d6..129c6519e 100644 --- a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs +++ b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs @@ -121,7 +121,7 @@ namespace ArchiSteamFarm.Steam.Integration { } } - return string.IsNullOrEmpty(VanityURL) ? "/profiles/" + Bot.SteamID : "/id/" + VanityURL; + return string.IsNullOrEmpty(VanityURL) ? $"/profiles/{Bot.SteamID}" : $"/id/{VanityURL}"; } [PublicAPI] @@ -165,7 +165,7 @@ namespace ArchiSteamFarm.Steam.Integration { await ASF.InventorySemaphore.WaitAsync().ConfigureAwait(false); try { - Uri request = new(SteamCommunityURL, "/inventory/" + steamID + "/" + appID + "/" + contextID + "?count=" + MaxItemsInSingleInventoryRequest + "&l=english" + (startAssetID > 0 ? "&start_assetid=" + startAssetID : "")); + Uri request = new(SteamCommunityURL, $"/inventory/{steamID}/{appID}/{contextID}?count={MaxItemsInSingleInventoryRequest}&l=english{(startAssetID > 0 ? $"&start_assetid={startAssetID}" : "")}"); ObjectResponse? response = await UrlGetToJsonObjectWithSession(request).ConfigureAwait(false); @@ -185,7 +185,7 @@ namespace ArchiSteamFarm.Steam.Integration { assetIDs ??= new HashSet((int) response.Content.TotalInventoryCount); if ((response.Content.Assets.Count == 0) || (response.Content.Descriptions.Count == 0)) { - throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(response.Content.Assets) + " || " + nameof(response.Content.Descriptions))); + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, $"{nameof(response.Content.Assets)} || {nameof(response.Content.Descriptions)}")); } Dictionary<(ulong ClassID, ulong InstanceID), InventoryResponse.Description> descriptions = new(); @@ -326,7 +326,7 @@ namespace ArchiSteamFarm.Steam.Integration { throw new ArgumentOutOfRangeException(nameof(groupID)); } - Uri request = new(SteamCommunityURL, "/gid/" + groupID); + Uri request = new(SteamCommunityURL, $"/gid/{groupID}"); // Extra entry for sessionID Dictionary data = new(2, StringComparer.Ordinal) { { "action", "join" } }; @@ -341,7 +341,7 @@ namespace ArchiSteamFarm.Steam.Integration { } if (((itemsToGive == null) || (itemsToGive.Count == 0)) && ((itemsToReceive == null) || (itemsToReceive.Count == 0))) { - throw new ArgumentException(nameof(itemsToGive) + " && " + nameof(itemsToReceive)); + throw new ArgumentException($"{nameof(itemsToGive)} && {nameof(itemsToReceive)}"); } if (itemsPerTrade <= 2) { @@ -389,7 +389,7 @@ namespace ArchiSteamFarm.Steam.Integration { { "partner", steamID.ToString(CultureInfo.InvariantCulture) }, { "serverid", "1" }, { "trade_offer_create_params", !string.IsNullOrEmpty(token) ? new JObject { { "trade_offer_access_token", token } }.ToString(Formatting.None) : "" }, - { "tradeoffermessage", "Sent by " + SharedInfo.PublicIdentifier + "/" + SharedInfo.Version } + { "tradeoffermessage", $"Sent by {SharedInfo.PublicIdentifier}/{SharedInfo.Version}" } }; HashSet mobileTradeOfferIDs = new(); @@ -1259,8 +1259,8 @@ namespace ArchiSteamFarm.Steam.Integration { throw new ArgumentOutOfRangeException(nameof(tradeID)); } - Uri request = new(SteamCommunityURL, "/tradeoffer/" + tradeID + "/accept"); - Uri referer = new(SteamCommunityURL, "/tradeoffer/" + tradeID); + Uri request = new(SteamCommunityURL, $"/tradeoffer/{tradeID}/accept"); + Uri referer = new(SteamCommunityURL, $"/tradeoffer/{tradeID}"); // Extra entry for sessionID Dictionary data = new(3, StringComparer.Ordinal) { @@ -1353,7 +1353,7 @@ namespace ArchiSteamFarm.Steam.Integration { return false; } - Uri request = new(SteamCommunityURL, profileURL + "/ajaxsetprivacy"); + Uri request = new(SteamCommunityURL, $"{profileURL}/ajaxsetprivacy"); // Extra entry for sessionID Dictionary data = new(3, StringComparer.Ordinal) { @@ -1381,7 +1381,7 @@ namespace ArchiSteamFarm.Steam.Integration { throw new ArgumentOutOfRangeException(nameof(appID)); } - Uri request = new(SteamStoreURL, "/app/" + appID); + Uri request = new(SteamStoreURL, $"/app/{appID}"); // Extra entry for sessionID Dictionary data = new(2, StringComparer.Ordinal) { { "appid_to_clear_from_queue", appID.ToString(CultureInfo.InvariantCulture) } }; @@ -1680,7 +1680,7 @@ namespace ArchiSteamFarm.Steam.Integration { throw new ArgumentOutOfRangeException(nameof(page)); } - Uri request = new(SteamCommunityURL, "/my/badges?l=english&p=" + page); + Uri request = new(SteamCommunityURL, $"/my/badges?l=english&p={page}"); HtmlDocumentResponse? response = await UrlGetToHtmlDocumentWithSession(request, checkSessionPreemptively: false).ConfigureAwait(false); @@ -1746,7 +1746,7 @@ namespace ArchiSteamFarm.Steam.Integration { } } - Uri request = new(SteamCommunityURL, "/mobileconf/conf?a=" + Bot.SteamID + "&k=" + WebUtility.UrlEncode(confirmationHash) + "&l=english&m=android&p=" + WebUtility.UrlEncode(deviceID) + "&t=" + time + "&tag=conf"); + Uri request = new(SteamCommunityURL, $"/mobileconf/conf?a={Bot.SteamID}&k={WebUtility.UrlEncode(confirmationHash)}&l=english&m=android&p={WebUtility.UrlEncode(deviceID)}&t={time}&tag=conf"); HtmlDocumentResponse? response = await UrlGetToHtmlDocumentWithSession(request).ConfigureAwait(false); @@ -1837,7 +1837,7 @@ namespace ArchiSteamFarm.Steam.Integration { throw new ArgumentOutOfRangeException(nameof(appID)); } - Uri request = new(SteamCommunityURL, "/my/gamecards/" + appID + "?l=english"); + Uri request = new(SteamCommunityURL, $"/my/gamecards/{appID}?l=english"); HtmlDocumentResponse? response = await UrlGetToHtmlDocumentWithSession(request, checkSessionPreemptively: false).ConfigureAwait(false); @@ -1888,7 +1888,7 @@ namespace ArchiSteamFarm.Steam.Integration { throw new ArgumentOutOfRangeException(nameof(tradeID)); } - Uri request = new(SteamCommunityURL, "/tradeoffer/" + tradeID + "?l=english"); + Uri request = new(SteamCommunityURL, $"/tradeoffer/{tradeID}?l=english"); using HtmlDocumentResponse? response = await UrlGetToHtmlDocumentWithSession(request).ConfigureAwait(false); @@ -2035,7 +2035,7 @@ namespace ArchiSteamFarm.Steam.Integration { } } - Uri request = new(SteamCommunityURL, "/mobileconf/ajaxop?a=" + Bot.SteamID + "&cid=" + confirmationID + "&ck=" + confirmationKey + "&k=" + WebUtility.UrlEncode(confirmationHash) + "&l=english&m=android&op=" + (accept ? "allow" : "cancel") + "&p=" + WebUtility.UrlEncode(deviceID) + "&t=" + time + "&tag=conf"); + Uri request = new(SteamCommunityURL, $"/mobileconf/ajaxop?a={Bot.SteamID}&cid={confirmationID}&ck={confirmationKey}&k={WebUtility.UrlEncode(confirmationHash)}&l=english&m=android&op={(accept ? "allow" : "cancel")}&p={WebUtility.UrlEncode(deviceID)}&t={time}&tag=conf"); ObjectResponse? response = await UrlGetToJsonObjectWithSession(request).ConfigureAwait(false); @@ -2187,24 +2187,24 @@ namespace ArchiSteamFarm.Steam.Integration { string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(steamID.ToString(CultureInfo.InvariantCulture))); - WebBrowser.CookieContainer.Add(new Cookie("sessionid", sessionID, "/", "." + SteamCommunityURL.Host)); - WebBrowser.CookieContainer.Add(new Cookie("sessionid", sessionID, "/", "." + SteamHelpURL.Host)); - WebBrowser.CookieContainer.Add(new Cookie("sessionid", sessionID, "/", "." + SteamStoreURL.Host)); + WebBrowser.CookieContainer.Add(new Cookie("sessionid", sessionID, "/", $".{SteamCommunityURL.Host}")); + WebBrowser.CookieContainer.Add(new Cookie("sessionid", sessionID, "/", $".{SteamHelpURL.Host}")); + WebBrowser.CookieContainer.Add(new Cookie("sessionid", sessionID, "/", $".{SteamStoreURL.Host}")); - WebBrowser.CookieContainer.Add(new Cookie("steamLogin", steamLogin, "/", "." + SteamCommunityURL.Host)); - WebBrowser.CookieContainer.Add(new Cookie("steamLogin", steamLogin, "/", "." + SteamHelpURL.Host)); - WebBrowser.CookieContainer.Add(new Cookie("steamLogin", steamLogin, "/", "." + SteamStoreURL.Host)); + WebBrowser.CookieContainer.Add(new Cookie("steamLogin", steamLogin, "/", $".{SteamCommunityURL.Host}")); + WebBrowser.CookieContainer.Add(new Cookie("steamLogin", steamLogin, "/", $".{SteamHelpURL.Host}")); + WebBrowser.CookieContainer.Add(new Cookie("steamLogin", steamLogin, "/", $".{SteamStoreURL.Host}")); - WebBrowser.CookieContainer.Add(new Cookie("steamLoginSecure", steamLoginSecure, "/", "." + SteamCommunityURL.Host)); - WebBrowser.CookieContainer.Add(new Cookie("steamLoginSecure", steamLoginSecure, "/", "." + SteamHelpURL.Host)); - WebBrowser.CookieContainer.Add(new Cookie("steamLoginSecure", steamLoginSecure, "/", "." + SteamStoreURL.Host)); + WebBrowser.CookieContainer.Add(new Cookie("steamLoginSecure", steamLoginSecure, "/", $".{SteamCommunityURL.Host}")); + WebBrowser.CookieContainer.Add(new Cookie("steamLoginSecure", steamLoginSecure, "/", $".{SteamHelpURL.Host}")); + WebBrowser.CookieContainer.Add(new Cookie("steamLoginSecure", steamLoginSecure, "/", $".{SteamStoreURL.Host}")); // Report proper time when doing timezone-based calculations, see setTimezoneCookies() from https://steamcommunity-a.akamaihd.net/public/shared/javascript/shared_global.js - string timeZoneOffset = DateTimeOffset.Now.Offset.TotalSeconds + WebUtility.UrlEncode(",") + "0"; + string timeZoneOffset = $"{DateTimeOffset.Now.Offset.TotalSeconds}{WebUtility.UrlEncode(",")}0"; - WebBrowser.CookieContainer.Add(new Cookie("timezoneOffset", timeZoneOffset, "/", "." + SteamCommunityURL.Host)); - WebBrowser.CookieContainer.Add(new Cookie("timezoneOffset", timeZoneOffset, "/", "." + SteamHelpURL.Host)); - WebBrowser.CookieContainer.Add(new Cookie("timezoneOffset", timeZoneOffset, "/", "." + SteamStoreURL.Host)); + WebBrowser.CookieContainer.Add(new Cookie("timezoneOffset", timeZoneOffset, "/", $".{SteamCommunityURL.Host}")); + WebBrowser.CookieContainer.Add(new Cookie("timezoneOffset", timeZoneOffset, "/", $".{SteamHelpURL.Host}")); + WebBrowser.CookieContainer.Add(new Cookie("timezoneOffset", timeZoneOffset, "/", $".{SteamStoreURL.Host}")); Bot.ArchiLogger.LogGenericInfo(Strings.Success); @@ -2323,7 +2323,7 @@ namespace ArchiSteamFarm.Steam.Integration { return false; } - Uri request = new(SteamCommunityURL, profileURL + "/ajaxunpackbooster"); + Uri request = new(SteamCommunityURL, $"{profileURL}/ajaxunpackbooster"); // Extra entry for sessionID Dictionary data = new(3, StringComparer.Ordinal) { @@ -2605,7 +2605,7 @@ namespace ArchiSteamFarm.Steam.Integration { Dictionary data = new(4, StringComparer.Ordinal) { { "agreeToTerms", "agreed" }, #pragma warning disable CA1308 // False positive, we're intentionally converting this part to lowercase and it's not used for any security decisions based on the result of the normalization - { "domain", "generated.by." + SharedInfo.AssemblyName.ToLowerInvariant() + ".localhost" }, + { "domain", $"generated.by.{SharedInfo.AssemblyName.ToLowerInvariant()}.localhost" }, #pragma warning restore CA1308 // False positive, we're intentionally converting this part to lowercase and it's not used for any security decisions based on the result of the normalization { "Submit", "Register" } }; diff --git a/ArchiSteamFarm/Steam/Interaction/Actions.cs b/ArchiSteamFarm/Steam/Interaction/Actions.cs index 091d25d99..1a75042f9 100644 --- a/ArchiSteamFarm/Steam/Interaction/Actions.cs +++ b/ArchiSteamFarm/Steam/Interaction/Actions.cs @@ -252,7 +252,7 @@ namespace ArchiSteamFarm.Steam.Interaction { [PublicAPI] public static (bool Success, string Message) Restart() { if (!Program.RestartAllowed) { - return (false, "!" + nameof(Program.RestartAllowed)); + return (false, $"!{nameof(Program.RestartAllowed)}"); } // Schedule the task after some time so user can receive response @@ -418,7 +418,7 @@ namespace ArchiSteamFarm.Steam.Interaction { } if (SharedInfo.Version >= version) { - return (false, "V" + SharedInfo.Version + " ≥ V" + version, version); + return (false, $"V{SharedInfo.Version} ≥ V{version}", version); } Utilities.InBackground(ASF.RestartOrExit); diff --git a/ArchiSteamFarm/Steam/Interaction/Commands.cs b/ArchiSteamFarm/Steam/Interaction/Commands.cs index b4b2e31f4..d3dc9f7ef 100644 --- a/ArchiSteamFarm/Steam/Interaction/Commands.cs +++ b/ArchiSteamFarm/Steam/Interaction/Commands.cs @@ -62,7 +62,7 @@ namespace ArchiSteamFarm.Steam.Interaction { throw new ArgumentNullException(nameof(botName)); } - return Environment.NewLine + "<" + botName + "> " + response; + return $"{Environment.NewLine}<{botName}> {response}"; } [PublicAPI] @@ -71,7 +71,7 @@ namespace ArchiSteamFarm.Steam.Interaction { throw new ArgumentNullException(nameof(response)); } - return "<" + Bot.BotName + "> " + response; + return $"<{Bot.BotName}> {response}"; } [PublicAPI] @@ -80,7 +80,7 @@ namespace ArchiSteamFarm.Steam.Interaction { throw new ArgumentNullException(nameof(response)); } - return "<" + SharedInfo.ASF + "> " + response; + return $"<{SharedInfo.ASF}> {response}"; } [PublicAPI] @@ -638,18 +638,18 @@ namespace ArchiSteamFarm.Steam.Interaction { callback = await Bot.SteamApps.RequestFreeLicense(gameID).ToLongRunningTask().ConfigureAwait(false); } catch (Exception e) { Bot.ArchiLogger.LogGenericWarningException(e); - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotAddLicense, "app/" + gameID, EResult.Timeout))); + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotAddLicense, $"app/{gameID}", EResult.Timeout))); break; } - response.AppendLine(FormatBotResponse((callback.GrantedApps.Count > 0) || (callback.GrantedPackages.Count > 0) ? string.Format(CultureInfo.CurrentCulture, Strings.BotAddLicenseWithItems, "app/" + gameID, callback.Result, string.Join(", ", callback.GrantedApps.Select(appID => "app/" + appID).Union(callback.GrantedPackages.Select(subID => "sub/" + subID)))) : string.Format(CultureInfo.CurrentCulture, Strings.BotAddLicense, "app/" + gameID, callback.Result))); + response.AppendLine(FormatBotResponse((callback.GrantedApps.Count > 0) || (callback.GrantedPackages.Count > 0) ? string.Format(CultureInfo.CurrentCulture, Strings.BotAddLicenseWithItems, $"app/{gameID}", callback.Result, string.Join(", ", callback.GrantedApps.Select(appID => $"app/{appID}").Union(callback.GrantedPackages.Select(subID => $"sub/{subID}")))) : string.Format(CultureInfo.CurrentCulture, Strings.BotAddLicense, $"app/{gameID}", callback.Result))); break; default: (EResult result, EPurchaseResultDetail purchaseResult) = await Bot.ArchiWebHandler.AddFreeLicense(gameID).ConfigureAwait(false); - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotAddLicense, "sub/" + gameID, result + "/" + purchaseResult))); + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotAddLicense, $"sub/{gameID}", $"{result}/{purchaseResult}"))); break; } @@ -1276,7 +1276,7 @@ namespace ArchiSteamFarm.Steam.Interaction { throw new ArgumentOutOfRangeException(nameof(steamID)); } - return Bot.HasAccess(steamID, BotConfig.EAccess.FamilySharing) ? FormatBotResponse(SharedInfo.ProjectURL + "/wiki/Commands") : null; + return Bot.HasAccess(steamID, BotConfig.EAccess.FamilySharing) ? FormatBotResponse($"{SharedInfo.ProjectURL}/wiki/Commands") : null; } private string? ResponseIdleBlacklist(ulong steamID) { @@ -2081,11 +2081,11 @@ namespace ArchiSteamFarm.Steam.Interaction { if (packageIDs?.Count > 0) { if ((gamesOwned != null) && gamesOwned.TryGetValue(appID, out string? cachedGameName)) { - result["app/" + appID] = cachedGameName; - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlreadyWithName, "app/" + appID, cachedGameName))); + result[$"app/{appID}"] = cachedGameName; + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlreadyWithName, $"app/{appID}", cachedGameName))); } else { - result["app/" + appID] = appID.ToString(CultureInfo.InvariantCulture); - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlready, "app/" + appID))); + result[$"app/{appID}"] = appID.ToString(CultureInfo.InvariantCulture); + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlready, $"app/{appID}"))); } } else { if (gamesOwned == null) { @@ -2099,10 +2099,10 @@ namespace ArchiSteamFarm.Steam.Interaction { } if (gamesOwned.TryGetValue(appID, out string? gameName)) { - result["app/" + appID] = gameName; - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlreadyWithName, "app/" + appID, gameName))); + result[$"app/{appID}"] = gameName; + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlreadyWithName, $"app/{appID}", gameName))); } else { - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotOwnedYet, "app/" + appID))); + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotOwnedYet, $"app/{appID}"))); } } @@ -2135,8 +2135,8 @@ namespace ArchiSteamFarm.Steam.Interaction { foreach ((uint appID, string gameName) in gamesOwned.Where(gameOwned => regex.IsMatch(gameOwned.Value))) { foundWithRegex = true; - result["app/" + appID] = gameName; - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlreadyWithName, "app/" + appID, gameName))); + result[$"app/{appID}"] = gameName; + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlreadyWithName, $"app/{appID}", gameName))); } if (!foundWithRegex) { @@ -2147,10 +2147,10 @@ namespace ArchiSteamFarm.Steam.Interaction { case "S" when uint.TryParse(game, out uint packageID) && (packageID > 0): case "SUB" when uint.TryParse(game, out packageID) && (packageID > 0): if (Bot.OwnedPackageIDs.ContainsKey(packageID)) { - result["sub/" + packageID] = packageID.ToString(CultureInfo.InvariantCulture); - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlready, "sub/" + packageID))); + result[$"sub/{packageID}"] = packageID.ToString(CultureInfo.InvariantCulture); + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlready, $"sub/{packageID}"))); } else { - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotOwnedYet, "sub/" + packageID))); + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotOwnedYet, $"sub/{packageID}"))); } break; @@ -2170,8 +2170,8 @@ namespace ArchiSteamFarm.Steam.Interaction { foreach ((uint appID, string gameName) in gamesOwned.Where(gameOwned => gameOwned.Value.Contains(game, StringComparison.OrdinalIgnoreCase))) { foundWithName = true; - result["app/" + appID] = gameName; - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlreadyWithName, "app/" + appID, gameName))); + result[$"app/{appID}"] = gameName; + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnedAlreadyWithName, $"app/{appID}", gameName))); } if (!foundWithName) { @@ -2228,7 +2228,7 @@ namespace ArchiSteamFarm.Steam.Interaction { ownedGamesStats[gameID] = ownedGameStats; } - IEnumerable extraResponses = ownedGamesStats.Select(kv => FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnsOverviewPerGame, kv.Value.Count, validResults.Count, kv.Key + (!string.IsNullOrEmpty(kv.Value.GameName) ? " | " + kv.Value.GameName : "")))); + IEnumerable extraResponses = ownedGamesStats.Select(kv => FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotOwnsOverviewPerGame, kv.Value.Count, validResults.Count, kv.Key + (!string.IsNullOrEmpty(kv.Value.GameName) ? $" | {kv.Value.GameName}" : "")))); return string.Join(Environment.NewLine, validResults.Select(result => result.Response).Concat(extraResponses)); } @@ -2382,7 +2382,7 @@ namespace ArchiSteamFarm.Steam.Interaction { } if (gamesToPlay.Count >= ArchiHandler.MaxGamesPlayedConcurrently) { - return FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(gamesToPlay) + " > " + ArchiHandler.MaxGamesPlayedConcurrently)); + return FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(gamesToPlay)} > {ArchiHandler.MaxGamesPlayedConcurrently}")); } gamesToPlay.Add(gameID); @@ -2721,9 +2721,9 @@ namespace ArchiSteamFarm.Steam.Interaction { } if (result.Items?.Count > 0) { - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotRedeemWithItems, key, result.Result + "/" + result.PurchaseResultDetail, string.Join(", ", result.Items)), currentBot.BotName)); + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotRedeemWithItems, key, $"{result.Result}/{result.PurchaseResultDetail}", string.Join(", ", result.Items)), currentBot.BotName)); } else if (!skipRequest) { - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotRedeem, key, result.Result + "/" + result.PurchaseResultDetail), currentBot.BotName)); + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotRedeem, key, $"{result.Result}/{result.PurchaseResultDetail}"), currentBot.BotName)); } switch (result.PurchaseResultDetail) { @@ -2774,7 +2774,7 @@ namespace ArchiSteamFarm.Steam.Interaction { PurchaseResponseCallback? otherResult = await innerBot.Actions.RedeemKey(key!).ConfigureAwait(false); if (otherResult == null) { - response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotRedeem, key, EResult.Timeout + "/" + EPurchaseResultDetail.Timeout), innerBot.BotName)); + response.AppendLine(FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotRedeem, key, $"{EResult.Timeout}/{EPurchaseResultDetail.Timeout}"), innerBot.BotName)); continue; } @@ -2798,7 +2798,7 @@ namespace ArchiSteamFarm.Steam.Interaction { break; } - response.AppendLine(FormatBotResponse(otherResult.Items?.Count > 0 ? string.Format(CultureInfo.CurrentCulture, Strings.BotRedeemWithItems, key, otherResult.Result + "/" + otherResult.PurchaseResultDetail, string.Join(", ", otherResult.Items)) : string.Format(CultureInfo.CurrentCulture, Strings.BotRedeem, key, otherResult.Result + "/" + otherResult.PurchaseResultDetail), innerBot.BotName)); + response.AppendLine(FormatBotResponse(otherResult.Items?.Count > 0 ? string.Format(CultureInfo.CurrentCulture, Strings.BotRedeemWithItems, key, $"{otherResult.Result}/{otherResult.PurchaseResultDetail}", string.Join(", ", otherResult.Items)) : string.Format(CultureInfo.CurrentCulture, Strings.BotRedeem, key, $"{otherResult.Result}/{otherResult.PurchaseResultDetail}"), innerBot.BotName)); if (alreadyHandled) { break; @@ -3061,7 +3061,7 @@ namespace ArchiSteamFarm.Steam.Interaction { } if (Bot.CardsFarmer.CurrentGamesFarmingReadOnly.Count > 1) { - return (FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotStatusIdlingList, string.Join(", ", Bot.CardsFarmer.CurrentGamesFarmingReadOnly.Select(game => game.AppID + " (" + game.GameName + ")")), Bot.CardsFarmer.GamesToFarmReadOnly.Count, Bot.CardsFarmer.GamesToFarmReadOnly.Sum(game => game.CardsRemaining), Bot.CardsFarmer.TimeRemaining.ToHumanReadable())), Bot); + return (FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotStatusIdlingList, string.Join(", ", Bot.CardsFarmer.CurrentGamesFarmingReadOnly.Select(game => $"{game.AppID} ({game.GameName})")), Bot.CardsFarmer.GamesToFarmReadOnly.Count, Bot.CardsFarmer.GamesToFarmReadOnly.Sum(game => game.CardsRemaining), Bot.CardsFarmer.TimeRemaining.ToHumanReadable())), Bot); } Game soloGame = Bot.CardsFarmer.CurrentGamesFarmingReadOnly.First(); @@ -3410,7 +3410,7 @@ namespace ArchiSteamFarm.Steam.Interaction { (bool success, string? message, Version? version) = await Actions.Update().ConfigureAwait(false); - return FormatStaticResponse((success ? Strings.Success : Strings.WarningFailed) + (!string.IsNullOrEmpty(message) ? " " + message : version != null ? " " + version : "")); + return FormatStaticResponse((success ? Strings.Success : Strings.WarningFailed) + (!string.IsNullOrEmpty(message) ? $" {message}" : version != null ? $" {version}" : "")); } private string? ResponseVersion(ulong steamID) { diff --git a/ArchiSteamFarm/Steam/Storage/BotConfig.cs b/ArchiSteamFarm/Steam/Storage/BotConfig.cs index 260dfc85f..4c987ca79 100644 --- a/ArchiSteamFarm/Steam/Storage/BotConfig.cs +++ b/ArchiSteamFarm/Steam/Storage/BotConfig.cs @@ -461,7 +461,7 @@ namespace ArchiSteamFarm.Steam.Storage { } if (GamesPlayedWhileIdle.Count > ArchiHandler.MaxGamesPlayedConcurrently) { - return (false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorConfigPropertyInvalid, nameof(GamesPlayedWhileIdle), nameof(GamesPlayedWhileIdle.Count) + " " + GamesPlayedWhileIdle.Count + " > " + ArchiHandler.MaxGamesPlayedConcurrently)); + return (false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorConfigPropertyInvalid, nameof(GamesPlayedWhileIdle), $"{nameof(GamesPlayedWhileIdle.Count)} {GamesPlayedWhileIdle.Count} > {ArchiHandler.MaxGamesPlayedConcurrently}")); } foreach (Asset.EType lootableType in LootableTypes.Where(lootableType => !Enum.IsDefined(typeof(Asset.EType), lootableType))) { diff --git a/ArchiSteamFarm/Web/GitHub.cs b/ArchiSteamFarm/Web/GitHub.cs index 47ae3831f..cf40b191c 100644 --- a/ArchiSteamFarm/Web/GitHub.cs +++ b/ArchiSteamFarm/Web/GitHub.cs @@ -56,7 +56,7 @@ namespace ArchiSteamFarm.Web { throw new ArgumentNullException(nameof(version)); } - Uri request = new(SharedInfo.GithubReleaseURL + "/tags/" + version); + Uri request = new($"{SharedInfo.GithubReleaseURL}/tags/{version}"); return await GetReleaseFromURL(request).ConfigureAwait(false); } @@ -70,7 +70,7 @@ namespace ArchiSteamFarm.Web { throw new InvalidOperationException(nameof(ASF.WebBrowser)); } - Uri request = new(SharedInfo.ProjectURL + "/wiki/" + page + "/_history"); + Uri request = new($"{SharedInfo.ProjectURL}/wiki/{page}/_history"); using HtmlDocumentResponse? response = await ASF.WebBrowser.UrlGetToHtmlDocument(request, requestOptions: WebBrowser.ERequestOptions.ReturnClientErrors).ConfigureAwait(false); @@ -143,7 +143,7 @@ namespace ArchiSteamFarm.Web { throw new InvalidOperationException(nameof(ASF.WebBrowser)); } - Uri request = new(SharedInfo.ProjectURL + "/wiki/" + page + (!string.IsNullOrEmpty(revision) ? "/" + revision : "")); + Uri request = new($"{SharedInfo.ProjectURL}/wiki/{page}{(!string.IsNullOrEmpty(revision) ? $"/{revision}" : "")}"); using HtmlDocumentResponse? response = await ASF.WebBrowser.UrlGetToHtmlDocument(request).ConfigureAwait(false); diff --git a/ArchiSteamFarm/Web/WebBrowser.cs b/ArchiSteamFarm/Web/WebBrowser.cs index b1a6b1e49..11ed581fb 100644 --- a/ArchiSteamFarm/Web/WebBrowser.cs +++ b/ArchiSteamFarm/Web/WebBrowser.cs @@ -113,7 +113,7 @@ namespace ArchiSteamFarm.Web { // Most web services expect that UserAgent is set, so we declare it globally // If you by any chance came here with a very "clever" idea of hiding your ass by changing default ASF user-agent then here is a very good advice from me: don't, for your own safety - you've been warned result.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(SharedInfo.PublicIdentifier, SharedInfo.Version.ToString())); - result.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("(" + SharedInfo.BuildInfo.Variant + "; " + OS.Version.Replace("(", "", StringComparison.Ordinal).Replace(")", "", StringComparison.Ordinal) + "; +" + SharedInfo.ProjectURL + ")")); + result.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue($"({SharedInfo.BuildInfo.Variant}; {OS.Version.Replace("(", "", StringComparison.Ordinal).Replace(")", "", StringComparison.Ordinal)}; +{SharedInfo.ProjectURL})")); return result; } @@ -785,7 +785,7 @@ namespace ArchiSteamFarm.Web { try { requestMessage.Content = new FormUrlEncodedContent(nameValueCollection); } catch (UriFormatException) { - requestMessage.Content = new StringContent(string.Join("&", nameValueCollection.Select(kv => WebUtility.UrlEncode(kv.Key) + "=" + WebUtility.UrlEncode(kv.Value))), null, "application/x-www-form-urlencoded"); + requestMessage.Content = new StringContent(string.Join("&", nameValueCollection.Select(kv => $"{WebUtility.UrlEncode(kv.Key)}={WebUtility.UrlEncode(kv.Value)}")), null, "application/x-www-form-urlencoded"); } break; @@ -805,7 +805,7 @@ namespace ArchiSteamFarm.Web { } if (Debugging.IsUserDebugging) { - ArchiLogger.LogGenericDebug(httpMethod + " " + request); + ArchiLogger.LogGenericDebug($"{httpMethod} {request}"); } try { @@ -823,7 +823,7 @@ namespace ArchiSteamFarm.Web { } if (Debugging.IsUserDebugging) { - ArchiLogger.LogGenericDebug(response.StatusCode + " <- " + httpMethod + " " + request); + ArchiLogger.LogGenericDebug($"{response.StatusCode} <- {httpMethod} {request}"); } if (response.IsSuccessStatusCode) { @@ -883,7 +883,7 @@ namespace ArchiSteamFarm.Web { } if (!Debugging.IsUserDebugging) { - ArchiLogger.LogGenericDebug(response.StatusCode + " <- " + httpMethod + " " + request); + ArchiLogger.LogGenericDebug($"{response.StatusCode} <- {httpMethod} {request}"); } if (response.StatusCode.IsClientErrorCode()) {