mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-16 06:20:34 +00:00
Use C# 10 string interpolation wherever possible
This commit is contained in:
@@ -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<bool>();
|
||||
ASF.ArchiLogger.LogGenericInfo($"{nameof(ExamplePlugin)}TestProperty boolean property has been found with a value of: {exampleBooleanValue}");
|
||||
|
||||
|
||||
@@ -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<string> 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<string> 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<string> 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<string> 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<string> 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]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Uri, (ICrossProcessSemaphore RateLimitingSemaphore, SemaphoreSlim OpenConnectionsSemaphore)>(4) {
|
||||
{ ArchiWebHandler.SteamCommunityURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}{networkGroupText}-{nameof(ArchiWebHandler.SteamCommunityURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) },
|
||||
|
||||
@@ -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<Asset.EType> AcceptedMatchableTypes = ImmutableHashSet.Create(
|
||||
Asset.EType.Emoticon,
|
||||
|
||||
@@ -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<StatusCodeResponse>))]
|
||||
[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<StatusCodeResponse>))]
|
||||
[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<StatusCodeResponse>))]
|
||||
[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<StatusCodeResponse>))]
|
||||
[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 { }
|
||||
|
||||
@@ -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<object>(obj));
|
||||
|
||||
@@ -55,7 +55,7 @@ public sealed class TwoFactorAuthenticationConfirmationsRequest {
|
||||
/// <summary>
|
||||
/// A helper property which works the same as <see cref="AcceptedCreatorIDs" /> but with values written as strings - for javascript compatibility purposes. Use either this one, or <see cref="AcceptedCreatorIDs" />, not both.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(AcceptedCreatorIDs), Required = Required.DisallowNull)]
|
||||
[JsonProperty(PropertyName = $"{SharedInfo.UlongCompatibilityStringPrefix}{nameof(AcceptedCreatorIDs)}", Required = Required.DisallowNull)]
|
||||
public ImmutableHashSet<string> SAcceptedCreatorIDs {
|
||||
get => AcceptedCreatorIDs.Select(static creatorID => creatorID.ToString(CultureInfo.InvariantCulture)).ToImmutableHashSet();
|
||||
set {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<LoggingRule> ConsoleLoggingRules = new();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -180,8 +180,7 @@ public sealed class Bot : IAsyncDisposable {
|
||||
/// </remarks>
|
||||
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));
|
||||
|
||||
@@ -2226,7 +2226,7 @@ public sealed class Commands {
|
||||
ownedGamesStats[gameID] = ownedGameStats;
|
||||
}
|
||||
|
||||
IEnumerable<string> 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<string> 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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace ArchiSteamFarm.Web;
|
||||
|
||||
internal static class GitHub {
|
||||
internal static async Task<ReleaseResponse?> 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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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<StringResponse?> UrlGetToString(Uri request, IReadOnlyCollection<KeyValuePair<string, string>>? 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<XmlDocumentResponse?> UrlGetToXmlDocument(Uri request, IReadOnlyCollection<KeyValuePair<string, string>>? headers = null, Uri? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) {
|
||||
if (request == null) {
|
||||
|
||||
Reference in New Issue
Block a user