diff --git a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs index 2a94a8959..eace5fa05 100644 --- a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs +++ b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs @@ -66,7 +66,7 @@ internal sealed class ExamplePlugin : IASF, IBot, IBotCommand, IBotConnection, I foreach ((string configProperty, JToken configValue) in additionalConfigProperties) { // It's a good idea to prefix your custom properties with the name of your plugin, so there will be no possible conflict of ASF or other plugins using the same name, neither now or in the future switch (configProperty) { - case nameof(ExamplePlugin) + "TestProperty" when configValue.Type == JTokenType.Boolean: + 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}"); diff --git a/ArchiSteamFarm.Tests/SteamChatMessage.cs b/ArchiSteamFarm.Tests/SteamChatMessage.cs index c00d5ee54..fc95acc58 100644 --- a/ArchiSteamFarm.Tests/SteamChatMessage.cs +++ b/ArchiSteamFarm.Tests/SteamChatMessage.cs @@ -36,16 +36,16 @@ public sealed class SteamChatMessage { string prefix = new('x', MaxMessagePrefixBytes); const string emoji = "😎"; - const string message = emoji + emoji + emoji + emoji; + const string message = $"{emoji}{emoji}{emoji}{emoji}"; List output = await GetMessageParts(message, prefix, true).ToListAsync().ConfigureAwait(false); Assert.AreEqual(4, output.Count); - Assert.AreEqual(prefix + emoji + ContinuationCharacter, output[0]); - Assert.AreEqual(prefix + ContinuationCharacter + emoji + ContinuationCharacter, output[1]); - Assert.AreEqual(prefix + ContinuationCharacter + emoji + ContinuationCharacter, output[2]); - Assert.AreEqual(prefix + ContinuationCharacter + emoji, output[3]); + Assert.AreEqual($"{prefix}{emoji}{ContinuationCharacter}", output[0]); + Assert.AreEqual($"{prefix}{ContinuationCharacter}{emoji}{ContinuationCharacter}", output[1]); + Assert.AreEqual($"{prefix}{ContinuationCharacter}{emoji}{ContinuationCharacter}", output[2]); + Assert.AreEqual($"{prefix}{ContinuationCharacter}{emoji}", output[3]); } [TestMethod] @@ -71,14 +71,14 @@ public sealed class SteamChatMessage { const string emoji = "😎"; string longSequence = new('a', longLineLength - 1); - string message = longSequence + emoji; + string message = $"{longSequence}{emoji}"; List output = await GetMessageParts(message, isAccountLimited: isAccountLimited).ToListAsync().ConfigureAwait(false); Assert.AreEqual(2, output.Count); - Assert.AreEqual(longSequence + ContinuationCharacter, output[0]); - Assert.AreEqual(ContinuationCharacter + emoji, output[1]); + Assert.AreEqual($"{longSequence}{ContinuationCharacter}", output[0]); + Assert.AreEqual($"{ContinuationCharacter}{emoji}", output[1]); } [TestMethod] @@ -122,7 +122,7 @@ public sealed class SteamChatMessage { Assert.AreEqual(2, output.Count); - Assert.AreEqual(longLine + ContinuationCharacter, output[0]); + Assert.AreEqual($"{longLine}{ContinuationCharacter}", output[0]); Assert.AreEqual($@"{ContinuationCharacter}\[", output[1]); } @@ -170,7 +170,7 @@ public sealed class SteamChatMessage { List output = await GetMessageParts(message, prefix).ToListAsync().ConfigureAwait(false); Assert.AreEqual(1, output.Count); - Assert.AreEqual(escapedPrefix + message, output.First()); + Assert.AreEqual($"{escapedPrefix}{message}", output.First()); } [DataRow(false)] @@ -181,16 +181,16 @@ public sealed class SteamChatMessage { int longLineLength = maxMessageBytes - ReservedContinuationMessageBytes; string longLine = new('a', longLineLength); - string message = longLine + longLine + longLine + longLine; + string message = $"{longLine}{longLine}{longLine}{longLine}"; List output = await GetMessageParts(message, isAccountLimited: isAccountLimited).ToListAsync().ConfigureAwait(false); Assert.AreEqual(4, output.Count); - Assert.AreEqual(longLine + ContinuationCharacter, output[0]); - Assert.AreEqual(ContinuationCharacter + longLine + ContinuationCharacter, output[1]); - Assert.AreEqual(ContinuationCharacter + longLine + ContinuationCharacter, output[2]); - Assert.AreEqual(ContinuationCharacter + longLine, output[3]); + Assert.AreEqual($"{longLine}{ContinuationCharacter}", output[0]); + Assert.AreEqual($"{ContinuationCharacter}{longLine}{ContinuationCharacter}", output[1]); + Assert.AreEqual($"{ContinuationCharacter}{longLine}{ContinuationCharacter}", output[2]); + Assert.AreEqual($"{ContinuationCharacter}{longLine}", output[3]); } [TestMethod] @@ -297,15 +297,15 @@ public sealed class SteamChatMessage { } string newlinePart = newlinePartBuilder.ToString(); - string message = newlinePart + Environment.NewLine + newlinePart + Environment.NewLine + newlinePart + Environment.NewLine + newlinePart; + string message = $"{newlinePart}{Environment.NewLine}{newlinePart}{Environment.NewLine}{newlinePart}{Environment.NewLine}{newlinePart}"; List output = await GetMessageParts(message, isAccountLimited: isAccountLimited).ToListAsync().ConfigureAwait(false); Assert.AreEqual(4, output.Count); - Assert.AreEqual(newlinePart + ParagraphCharacter, output[0]); - Assert.AreEqual(newlinePart + ParagraphCharacter, output[1]); - Assert.AreEqual(newlinePart + ParagraphCharacter, output[2]); + Assert.AreEqual($"{newlinePart}{ParagraphCharacter}", output[0]); + Assert.AreEqual($"{newlinePart}{ParagraphCharacter}", output[1]); + Assert.AreEqual($"{newlinePart}{ParagraphCharacter}", output[2]); Assert.AreEqual(newlinePart, output[3]); } diff --git a/ArchiSteamFarm/Core/ASF.cs b/ArchiSteamFarm/Core/ASF.cs index f225ee24b..83c220173 100644 --- a/ArchiSteamFarm/Core/ASF.cs +++ b/ArchiSteamFarm/Core/ASF.cs @@ -395,12 +395,12 @@ public static class ASF { networkGroupText = $"-{BitConverter.ToString(SHA256.HashData(Encoding.UTF8.GetBytes(GlobalConfig.WebProxyText!))).Replace("-", "", StringComparison.Ordinal)}"; } - ConfirmationsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(ConfirmationsSemaphore) + networkGroupText).ConfigureAwait(false); - GiftsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(GiftsSemaphore) + networkGroupText).ConfigureAwait(false); - InventorySemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(InventorySemaphore) + networkGroupText).ConfigureAwait(false); - LoginRateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(LoginRateLimitingSemaphore) + networkGroupText).ConfigureAwait(false); - LoginSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(LoginSemaphore) + networkGroupText).ConfigureAwait(false); - RateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(RateLimitingSemaphore) + networkGroupText).ConfigureAwait(false); + ConfirmationsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(ConfirmationsSemaphore)}{networkGroupText}").ConfigureAwait(false); + GiftsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(GiftsSemaphore)}{networkGroupText}").ConfigureAwait(false); + InventorySemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(InventorySemaphore)}{networkGroupText}").ConfigureAwait(false); + LoginRateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(LoginRateLimitingSemaphore)}{networkGroupText}").ConfigureAwait(false); + LoginSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(LoginSemaphore)}{networkGroupText}").ConfigureAwait(false); + 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)) }, diff --git a/ArchiSteamFarm/Core/Statistics.cs b/ArchiSteamFarm/Core/Statistics.cs index b105a4c0e..e031a21bd 100644 --- a/ArchiSteamFarm/Core/Statistics.cs +++ b/ArchiSteamFarm/Core/Statistics.cs @@ -51,7 +51,7 @@ internal sealed class Statistics : IAsyncDisposable { private const byte MinHeartBeatTTL = 10; // Minimum amount of minutes we must wait before sending next HeartBeat private const byte MinItemsCount = 100; // Minimum amount of items to be eligible for public listing private const byte MinPersonaStateTTL = 8; // Minimum amount of hours we must wait before requesting persona state update - private const string URL = "https://" + SharedInfo.StatisticsServer; + private const string URL = $"https://{SharedInfo.StatisticsServer}"; private static readonly ImmutableHashSet AcceptedMatchableTypes = ImmutableHashSet.Create( Asset.EType.Emoticon, diff --git a/ArchiSteamFarm/IPC/Controllers/Api/ArchiController.cs b/ArchiSteamFarm/IPC/Controllers/Api/ArchiController.cs index cb25dad83..c9b31b48d 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/ArchiController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/ArchiController.cs @@ -30,9 +30,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api; [ApiController] [Produces("application/json")] [Route("Api")] -[SwaggerResponse((int) HttpStatusCode.BadRequest, "The request has failed, check " + nameof(GenericResponse.Message) + " from response body for actual reason. Most of the time this is ASF, understanding the request, but refusing to execute it due to provided reason.", typeof(GenericResponse))] -[SwaggerResponse((int) HttpStatusCode.Unauthorized, "ASF has " + nameof(GlobalConfig.IPCPassword) + " set, but you've failed to authenticate. See " + SharedInfo.ProjectURL + "/wiki/IPC#authentication.", typeof(GenericResponse))] -[SwaggerResponse((int) HttpStatusCode.Forbidden, "ASF lacks " + nameof(GlobalConfig.IPCPassword) + " and you're not permitted to access the API, or " + nameof(GlobalConfig.IPCPassword) + " is set and you've failed to authenticate too many times (try again in an hour). See " + SharedInfo.ProjectURL + "/wiki/IPC#authentication.", typeof(GenericResponse))] +[SwaggerResponse((int) HttpStatusCode.BadRequest, $"The request has failed, check {nameof(GenericResponse.Message)} from response body for actual reason. Most of the time this is ASF, understanding the request, but refusing to execute it due to provided reason.", typeof(GenericResponse))] +[SwaggerResponse((int) HttpStatusCode.Unauthorized, $"ASF has {nameof(GlobalConfig.IPCPassword)} set, but you've failed to authenticate. See {SharedInfo.ProjectURL}/wiki/IPC#authentication.", typeof(GenericResponse))] +[SwaggerResponse((int) HttpStatusCode.Forbidden, $"ASF lacks {nameof(GlobalConfig.IPCPassword)} and you're not permitted to access the API, or {nameof(GlobalConfig.IPCPassword)} is set and you've failed to authenticate too many times (try again in an hour). See {SharedInfo.ProjectURL}/wiki/IPC#authentication.", typeof(GenericResponse))] [SwaggerResponse((int) HttpStatusCode.InternalServerError, "ASF has encountered an unexpected error while serving the request. The log may include extra info related to this issue.")] [SwaggerResponse((int) HttpStatusCode.ServiceUnavailable, "ASF has encountered an error while requesting a third-party resource. Try again later.")] public abstract class ArchiController : ControllerBase { } diff --git a/ArchiSteamFarm/IPC/Controllers/Api/StructureController.cs b/ArchiSteamFarm/IPC/Controllers/Api/StructureController.cs index 784bf69f5..fa2fc28b1 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/StructureController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/StructureController.cs @@ -55,7 +55,7 @@ public sealed class StructureController : ArchiController { try { obj = Activator.CreateInstance(targetType, true); } catch (Exception e) { - return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorParsingObject, nameof(targetType)) + Environment.NewLine + e)); + return BadRequest(new GenericResponse(false, $"{string.Format(CultureInfo.CurrentCulture, Strings.ErrorParsingObject, nameof(targetType))}{Environment.NewLine}{e}")); } return Ok(new GenericResponse(obj)); diff --git a/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs b/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs index 956c2150e..244e66c53 100644 --- a/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs +++ b/ArchiSteamFarm/IPC/Requests/TwoFactorAuthenticationConfirmationsRequest.cs @@ -55,7 +55,7 @@ public sealed class TwoFactorAuthenticationConfirmationsRequest { /// /// A helper property which works the same as but with values written as strings - for javascript compatibility purposes. Use either this one, or , not both. /// - [JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(AcceptedCreatorIDs), Required = Required.DisallowNull)] + [JsonProperty(PropertyName = $"{SharedInfo.UlongCompatibilityStringPrefix}{nameof(AcceptedCreatorIDs)}", Required = Required.DisallowNull)] public ImmutableHashSet SAcceptedCreatorIDs { get => AcceptedCreatorIDs.Select(static creatorID => creatorID.ToString(CultureInfo.InvariantCulture)).ToImmutableHashSet(); set { diff --git a/ArchiSteamFarm/NLog/ArchiLogger.cs b/ArchiSteamFarm/NLog/ArchiLogger.cs index d7b500739..c5593f196 100644 --- a/ArchiSteamFarm/NLog/ArchiLogger.cs +++ b/ArchiSteamFarm/NLog/ArchiLogger.cs @@ -176,7 +176,7 @@ public sealed class ArchiLogger { } // Otherwise, we ran into fatal exception before logging module could even get initialized, so activate fallback logging that involves file and console - string message = string.Format(CultureInfo.CurrentCulture, DateTime.Now + " " + Strings.ErrorEarlyFatalExceptionInfo, SharedInfo.Version) + Environment.NewLine; + string message = $"{DateTime.Now} {string.Format(CultureInfo.CurrentCulture, Strings.ErrorEarlyFatalExceptionInfo, SharedInfo.Version)}{Environment.NewLine}"; try { await File.WriteAllTextAsync(SharedInfo.LogFile, message).ConfigureAwait(false); @@ -191,7 +191,7 @@ public sealed class ArchiLogger { } while (true) { - message = string.Format(CultureInfo.CurrentCulture, Strings.ErrorEarlyFatalExceptionPrint, previousMethodName, exception.Message, exception.StackTrace) + Environment.NewLine; + message = $"{string.Format(CultureInfo.CurrentCulture, Strings.ErrorEarlyFatalExceptionPrint, previousMethodName, exception.Message, exception.StackTrace)}{Environment.NewLine}"; try { await File.AppendAllTextAsync(SharedInfo.LogFile, message).ConfigureAwait(false); diff --git a/ArchiSteamFarm/NLog/Logging.cs b/ArchiSteamFarm/NLog/Logging.cs index 962601457..74ea2d052 100644 --- a/ArchiSteamFarm/NLog/Logging.cs +++ b/ArchiSteamFarm/NLog/Logging.cs @@ -44,7 +44,7 @@ internal static class Logging { internal const string NLogConfigurationFile = "NLog.config"; private const byte ConsoleResponsivenessDelay = 250; // In milliseconds - private const string GeneralLayout = @"${date:format=yyyy-MM-dd HH\:mm\:ss}|${processname}-${processid}|${level:uppercase=true}|" + LayoutMessage; + private const string GeneralLayout = $@"${{date:format=yyyy-MM-dd HH\:mm\:ss}}|${{processname}}-${{processid}}|${{level:uppercase=true}}|{LayoutMessage}"; private const string LayoutMessage = @"${logger}|${message}${onexception:inner= ${exception:format=toString,Data}}"; private static readonly ConcurrentHashSet ConsoleLoggingRules = new(); diff --git a/ArchiSteamFarm/SharedInfo.cs b/ArchiSteamFarm/SharedInfo.cs index 3f035def6..4c0c486f1 100644 --- a/ArchiSteamFarm/SharedInfo.cs +++ b/ArchiSteamFarm/SharedInfo.cs @@ -37,20 +37,20 @@ public static class SharedInfo { internal const string ArchivalLogsDirectory = "logs"; internal const string ASF = nameof(ASF); internal const ulong ASFGroupSteamID = 103582791440160998; - internal const string AssemblyDocumentation = AssemblyName + ".xml"; + internal const string AssemblyDocumentation = $"{AssemblyName}.xml"; internal const string AssemblyName = nameof(ArchiSteamFarm); internal const string DatabaseExtension = ".db"; internal const string DebugDirectory = "debug"; - internal const string EnvironmentVariableCryptKey = ASF + "_CRYPTKEY"; - internal const string EnvironmentVariableNetworkGroup = ASF + "_NETWORK_GROUP"; - internal const string EnvironmentVariablePath = ASF + "_PATH"; - internal const string GithubReleaseURL = "https://api.github.com/repos/" + GithubRepo + "/releases"; - internal const string GithubRepo = "JustArchiNET/" + AssemblyName; - internal const string GlobalConfigFileName = ASF + JsonConfigExtension; - internal const string GlobalDatabaseFileName = ASF + DatabaseExtension; + internal const string EnvironmentVariableCryptKey = $"{ASF}_CRYPTKEY"; + internal const string EnvironmentVariableNetworkGroup = $"{ASF}_NETWORK_GROUP"; + internal const string EnvironmentVariablePath = $"{ASF}_PATH"; + internal const string GithubReleaseURL = $"https://api.github.com/repos/{GithubRepo}/releases"; + internal const string GithubRepo = $"JustArchiNET/{AssemblyName}"; + internal const string GlobalConfigFileName = $"{ASF}{JsonConfigExtension}"; + internal const string GlobalDatabaseFileName = $"{ASF}{DatabaseExtension}"; internal const ushort InformationDelay = 10000; internal const string IPCConfigExtension = ".config"; - internal const string IPCConfigFile = nameof(IPC) + IPCConfigExtension; + internal const string IPCConfigFile = $"{nameof(IPC)}{IPCConfigExtension}"; internal const string JsonConfigExtension = ".json"; internal const string KeysExtension = ".keys"; internal const string KeysUnusedExtension = ".unused"; @@ -61,7 +61,7 @@ public static class SharedInfo { internal const string LolcatCultureName = "qps-Ploc"; internal const string MobileAuthenticatorExtension = ".maFile"; internal const string PluginsDirectory = "plugins"; - internal const string ProjectURL = "https://github.com/" + GithubRepo; + internal const string ProjectURL = $"https://github.com/{GithubRepo}"; internal const string SentryHashExtension = ".bin"; internal const ushort ShortInformationDelay = InformationDelay / 2; internal const string StatisticsServer = "asf.justarchi.net"; @@ -88,7 +88,7 @@ public static class SharedInfo { } 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 string PublicIdentifier => $"{AssemblyName}{(BuildInfo.IsCustomBuild ? "-custom" : PluginsCore.HasCustomPluginsLoaded ? "-modded" : "")}"; internal static Version Version => Assembly.GetExecutingAssembly().GetName().Version ?? throw new InvalidOperationException(nameof(Version)); private static Guid ModuleVersion => Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId; diff --git a/ArchiSteamFarm/Steam/Bot.cs b/ArchiSteamFarm/Steam/Bot.cs index 4f9f24e62..36d62cd11 100644 --- a/ArchiSteamFarm/Steam/Bot.cs +++ b/ArchiSteamFarm/Steam/Bot.cs @@ -180,8 +180,7 @@ public sealed class Bot : IAsyncDisposable { /// private bool ShouldUseLoginKeys => BotConfig.UseLoginKeys && (!BotConfig.IsSteamPasswordSet || string.IsNullOrEmpty(BotConfig.DecryptedSteamPassword) || !HasMobileAuthenticator); - [JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(SteamID))] - + [JsonProperty(PropertyName = $"{SharedInfo.UlongCompatibilityStringPrefix}{nameof(SteamID)}")] private string SSteamID => SteamID.ToString(CultureInfo.InvariantCulture); [JsonProperty] @@ -523,13 +522,13 @@ public sealed class Bot : IAsyncDisposable { string botPath = Path.Combine(SharedInfo.ConfigDirectory, botName); return fileType switch { - EFileType.Config => botPath + SharedInfo.JsonConfigExtension, - EFileType.Database => botPath + SharedInfo.DatabaseExtension, - EFileType.KeysToRedeem => botPath + SharedInfo.KeysExtension, - EFileType.KeysToRedeemUnused => botPath + SharedInfo.KeysExtension + SharedInfo.KeysUnusedExtension, - EFileType.KeysToRedeemUsed => botPath + SharedInfo.KeysExtension + SharedInfo.KeysUsedExtension, - EFileType.MobileAuthenticator => botPath + SharedInfo.MobileAuthenticatorExtension, - EFileType.SentryFile => botPath + SharedInfo.SentryHashExtension, + EFileType.Config => $"{botPath}{SharedInfo.JsonConfigExtension}", + EFileType.Database => $"{botPath}{SharedInfo.DatabaseExtension}", + EFileType.KeysToRedeem => $"{botPath}{SharedInfo.KeysExtension}", + EFileType.KeysToRedeemUnused => $"{botPath}{SharedInfo.KeysExtension}{SharedInfo.KeysUnusedExtension}", + EFileType.KeysToRedeemUsed => $"{botPath}{SharedInfo.KeysExtension}{SharedInfo.KeysUsedExtension}", + EFileType.MobileAuthenticator => $"{botPath}{SharedInfo.MobileAuthenticatorExtension}", + EFileType.SentryFile => $"{botPath}{SharedInfo.SentryHashExtension}", _ => throw new ArgumentOutOfRangeException(nameof(fileType)) }; } @@ -2741,7 +2740,7 @@ public sealed class Bot : IAsyncDisposable { 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; @@ -2765,7 +2764,7 @@ public sealed class Bot : IAsyncDisposable { // Handle steamID-based maFile if (!HasMobileAuthenticator) { - string maFilePath = Path.Combine(SharedInfo.ConfigDirectory, SteamID + SharedInfo.MobileAuthenticatorExtension); + string maFilePath = Path.Combine(SharedInfo.ConfigDirectory, $"{SteamID}{SharedInfo.MobileAuthenticatorExtension}"); if (File.Exists(maFilePath)) { await ImportAuthenticatorFromFile(maFilePath).ConfigureAwait(false); @@ -3244,7 +3243,7 @@ public sealed class Bot : IAsyncDisposable { 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); @@ -3255,7 +3254,7 @@ public sealed class Bot : IAsyncDisposable { } try { - await File.AppendAllTextAsync(filePath, logEntry + Environment.NewLine).ConfigureAwait(false); + await File.AppendAllTextAsync(filePath, $"{logEntry}{Environment.NewLine}").ConfigureAwait(false); } catch (Exception e) { ArchiLogger.LogGenericException(e); ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.Content, logEntry)); diff --git a/ArchiSteamFarm/Steam/Interaction/Commands.cs b/ArchiSteamFarm/Steam/Interaction/Commands.cs index f0e40785d..55ab50884 100644 --- a/ArchiSteamFarm/Steam/Interaction/Commands.cs +++ b/ArchiSteamFarm/Steam/Interaction/Commands.cs @@ -2226,7 +2226,7 @@ public sealed class Commands { 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(static result => result.Response).Concat(extraResponses)); } @@ -2374,7 +2374,11 @@ public sealed class Commands { foreach (string game in games) { if (!uint.TryParse(game, out uint gameID) || (gameID == 0)) { - gameName.Append((gameName.Length > 0 ? " " : "") + game); + if (gameName.Length > 0) { + gameName.Append(' '); + } + + gameName.Append(game); continue; } @@ -3408,7 +3412,7 @@ public sealed class Commands { (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 8f882649c..0223b82df 100644 --- a/ArchiSteamFarm/Steam/Storage/BotConfig.cs +++ b/ArchiSteamFarm/Steam/Storage/BotConfig.cs @@ -314,7 +314,7 @@ public sealed class BotConfig { private string? BackingSteamParentalCode = DefaultSteamParentalCode; private string? BackingSteamPassword = DefaultSteamPassword; - [JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(SteamMasterClanID), Required = Required.DisallowNull)] + [JsonProperty(PropertyName = $"{SharedInfo.UlongCompatibilityStringPrefix}{nameof(SteamMasterClanID)}", Required = Required.DisallowNull)] private string SSteamMasterClanID { get => SteamMasterClanID.ToString(CultureInfo.InvariantCulture); diff --git a/ArchiSteamFarm/Steam/Storage/BotDatabase.cs b/ArchiSteamFarm/Steam/Storage/BotDatabase.cs index 50232cef5..2f781e83a 100644 --- a/ArchiSteamFarm/Steam/Storage/BotDatabase.cs +++ b/ArchiSteamFarm/Steam/Storage/BotDatabase.cs @@ -88,10 +88,10 @@ internal sealed class BotDatabase : SerializableFile { } } - [JsonProperty(PropertyName = "_" + nameof(LoginKey))] + [JsonProperty(PropertyName = $"_{nameof(LoginKey)}")] private string? BackingLoginKey; - [JsonProperty(PropertyName = "_" + nameof(MobileAuthenticator))] + [JsonProperty(PropertyName = $"_{nameof(MobileAuthenticator)}")] private MobileAuthenticator? BackingMobileAuthenticator; private BotDatabase(string filePath) { diff --git a/ArchiSteamFarm/Storage/GlobalConfig.cs b/ArchiSteamFarm/Storage/GlobalConfig.cs index c3c6d9afd..cb6803d1d 100644 --- a/ArchiSteamFarm/Storage/GlobalConfig.cs +++ b/ArchiSteamFarm/Storage/GlobalConfig.cs @@ -310,7 +310,7 @@ public sealed class GlobalConfig { private WebProxy? BackingWebProxy; private string? BackingWebProxyPassword = DefaultWebProxyPassword; - [JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(SteamOwnerID), Required = Required.DisallowNull)] + [JsonProperty(PropertyName = $"{SharedInfo.UlongCompatibilityStringPrefix}{nameof(SteamOwnerID)}", Required = Required.DisallowNull)] private string SSteamOwnerID { get => SteamOwnerID.ToString(CultureInfo.InvariantCulture); diff --git a/ArchiSteamFarm/Storage/GlobalDatabase.cs b/ArchiSteamFarm/Storage/GlobalDatabase.cs index ae8f40c0a..d7d255960 100644 --- a/ArchiSteamFarm/Storage/GlobalDatabase.cs +++ b/ArchiSteamFarm/Storage/GlobalDatabase.cs @@ -92,10 +92,10 @@ public sealed class GlobalDatabase : SerializableFile { } } - [JsonProperty(PropertyName = "_" + nameof(CellID), Required = Required.DisallowNull)] + [JsonProperty(PropertyName = $"_{nameof(CellID)}", Required = Required.DisallowNull)] private uint BackingCellID; - [JsonProperty(PropertyName = "_" + nameof(LastChangeNumber), Required = Required.DisallowNull)] + [JsonProperty(PropertyName = $"_{nameof(LastChangeNumber)}", Required = Required.DisallowNull)] private uint BackingLastChangeNumber; private GlobalDatabase(string filePath) : this() { diff --git a/ArchiSteamFarm/Web/GitHub.cs b/ArchiSteamFarm/Web/GitHub.cs index 95942a715..114bf59e0 100644 --- a/ArchiSteamFarm/Web/GitHub.cs +++ b/ArchiSteamFarm/Web/GitHub.cs @@ -41,7 +41,7 @@ namespace ArchiSteamFarm.Web; internal static class GitHub { internal static async Task GetLatestRelease(bool stable = true) { - Uri request = new(SharedInfo.GithubReleaseURL + (stable ? "/latest" : "?per_page=1")); + Uri request = new($"{SharedInfo.GithubReleaseURL}{(stable ? "/latest" : "?per_page=1")}"); if (stable) { return await GetReleaseFromURL(request).ConfigureAwait(false); diff --git a/ArchiSteamFarm/Web/Responses/StringResponse.cs b/ArchiSteamFarm/Web/Responses/StringResponse.cs index c1e21afc9..61f494409 100644 --- a/ArchiSteamFarm/Web/Responses/StringResponse.cs +++ b/ArchiSteamFarm/Web/Responses/StringResponse.cs @@ -25,7 +25,7 @@ using JetBrains.Annotations; namespace ArchiSteamFarm.Web.Responses; -[Obsolete("ASF no longer uses this class, re-implement it yourself using " + nameof(BasicResponse) + " if needed.")] +[Obsolete($"ASF no longer uses this class, re-implement it yourself using {nameof(BasicResponse)} if needed.")] public sealed class StringResponse : BasicResponse { [PublicAPI] public string Content { get; } diff --git a/ArchiSteamFarm/Web/Responses/XmlDocumentResponse.cs b/ArchiSteamFarm/Web/Responses/XmlDocumentResponse.cs index 95c677451..9ba9a44ea 100644 --- a/ArchiSteamFarm/Web/Responses/XmlDocumentResponse.cs +++ b/ArchiSteamFarm/Web/Responses/XmlDocumentResponse.cs @@ -25,7 +25,7 @@ using JetBrains.Annotations; namespace ArchiSteamFarm.Web.Responses; -[Obsolete("ASF no longer uses any XML-related functions, re-implement it yourself using " + nameof(BasicResponse) + " if needed.")] +[Obsolete($"ASF no longer uses any XML-related functions, re-implement it yourself using {nameof(BasicResponse)} if needed.")] public sealed class XmlDocumentResponse : BasicResponse { [PublicAPI] public XmlDocument Content { get; } diff --git a/ArchiSteamFarm/Web/WebBrowser.cs b/ArchiSteamFarm/Web/WebBrowser.cs index 3355769f2..157c49acb 100644 --- a/ArchiSteamFarm/Web/WebBrowser.cs +++ b/ArchiSteamFarm/Web/WebBrowser.cs @@ -362,7 +362,7 @@ public sealed class WebBrowser : IDisposable { return null; } - [Obsolete("ASF no longer uses this function, re-implement it yourself using " + nameof(UrlGetToStream) + " if needed.")] + [Obsolete($"ASF no longer uses this function, re-implement it yourself using {nameof(UrlGetToStream)} if needed.")] [PublicAPI] public async Task UrlGetToString(Uri request, IReadOnlyCollection>? headers = null, Uri? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { if (request == null) { @@ -404,7 +404,7 @@ public sealed class WebBrowser : IDisposable { return null; } - [Obsolete("ASF no longer uses any XML-related functions, re-implement it yourself using " + nameof(UrlGetToStream) + " if needed.")] + [Obsolete($"ASF no longer uses any XML-related functions, re-implement it yourself using {nameof(UrlGetToStream)} if needed.")] [PublicAPI] public async Task UrlGetToXmlDocument(Uri request, IReadOnlyCollection>? headers = null, Uri? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { if (request == null) {