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) {
|
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
|
// 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) {
|
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>();
|
bool exampleBooleanValue = configValue.Value<bool>();
|
||||||
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}");
|
||||||
|
|
||||||
|
|||||||
@@ -36,16 +36,16 @@ public sealed class SteamChatMessage {
|
|||||||
string prefix = new('x', MaxMessagePrefixBytes);
|
string prefix = new('x', MaxMessagePrefixBytes);
|
||||||
|
|
||||||
const string emoji = "😎";
|
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);
|
List<string> output = await GetMessageParts(message, prefix, true).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
Assert.AreEqual(4, output.Count);
|
Assert.AreEqual(4, output.Count);
|
||||||
|
|
||||||
Assert.AreEqual(prefix + emoji + ContinuationCharacter, output[0]);
|
Assert.AreEqual($"{prefix}{emoji}{ContinuationCharacter}", output[0]);
|
||||||
Assert.AreEqual(prefix + ContinuationCharacter + emoji + ContinuationCharacter, output[1]);
|
Assert.AreEqual($"{prefix}{ContinuationCharacter}{emoji}{ContinuationCharacter}", output[1]);
|
||||||
Assert.AreEqual(prefix + ContinuationCharacter + emoji + ContinuationCharacter, output[2]);
|
Assert.AreEqual($"{prefix}{ContinuationCharacter}{emoji}{ContinuationCharacter}", output[2]);
|
||||||
Assert.AreEqual(prefix + ContinuationCharacter + emoji, output[3]);
|
Assert.AreEqual($"{prefix}{ContinuationCharacter}{emoji}", output[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -71,14 +71,14 @@ public sealed class SteamChatMessage {
|
|||||||
const string emoji = "😎";
|
const string emoji = "😎";
|
||||||
|
|
||||||
string longSequence = new('a', longLineLength - 1);
|
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);
|
List<string> output = await GetMessageParts(message, isAccountLimited: isAccountLimited).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
Assert.AreEqual(2, output.Count);
|
Assert.AreEqual(2, output.Count);
|
||||||
|
|
||||||
Assert.AreEqual(longSequence + ContinuationCharacter, output[0]);
|
Assert.AreEqual($"{longSequence}{ContinuationCharacter}", output[0]);
|
||||||
Assert.AreEqual(ContinuationCharacter + emoji, output[1]);
|
Assert.AreEqual($"{ContinuationCharacter}{emoji}", output[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -122,7 +122,7 @@ public sealed class SteamChatMessage {
|
|||||||
|
|
||||||
Assert.AreEqual(2, output.Count);
|
Assert.AreEqual(2, output.Count);
|
||||||
|
|
||||||
Assert.AreEqual(longLine + ContinuationCharacter, output[0]);
|
Assert.AreEqual($"{longLine}{ContinuationCharacter}", output[0]);
|
||||||
Assert.AreEqual($@"{ContinuationCharacter}\[", output[1]);
|
Assert.AreEqual($@"{ContinuationCharacter}\[", output[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ public sealed class SteamChatMessage {
|
|||||||
List<string> output = await GetMessageParts(message, prefix).ToListAsync().ConfigureAwait(false);
|
List<string> output = await GetMessageParts(message, prefix).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
Assert.AreEqual(1, output.Count);
|
Assert.AreEqual(1, output.Count);
|
||||||
Assert.AreEqual(escapedPrefix + message, output.First());
|
Assert.AreEqual($"{escapedPrefix}{message}", output.First());
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataRow(false)]
|
[DataRow(false)]
|
||||||
@@ -181,16 +181,16 @@ public sealed class SteamChatMessage {
|
|||||||
int longLineLength = maxMessageBytes - ReservedContinuationMessageBytes;
|
int longLineLength = maxMessageBytes - ReservedContinuationMessageBytes;
|
||||||
|
|
||||||
string longLine = new('a', longLineLength);
|
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);
|
List<string> output = await GetMessageParts(message, isAccountLimited: isAccountLimited).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
Assert.AreEqual(4, output.Count);
|
Assert.AreEqual(4, output.Count);
|
||||||
|
|
||||||
Assert.AreEqual(longLine + ContinuationCharacter, output[0]);
|
Assert.AreEqual($"{longLine}{ContinuationCharacter}", output[0]);
|
||||||
Assert.AreEqual(ContinuationCharacter + longLine + ContinuationCharacter, output[1]);
|
Assert.AreEqual($"{ContinuationCharacter}{longLine}{ContinuationCharacter}", output[1]);
|
||||||
Assert.AreEqual(ContinuationCharacter + longLine + ContinuationCharacter, output[2]);
|
Assert.AreEqual($"{ContinuationCharacter}{longLine}{ContinuationCharacter}", output[2]);
|
||||||
Assert.AreEqual(ContinuationCharacter + longLine, output[3]);
|
Assert.AreEqual($"{ContinuationCharacter}{longLine}", output[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -297,15 +297,15 @@ public sealed class SteamChatMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string newlinePart = newlinePartBuilder.ToString();
|
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);
|
List<string> output = await GetMessageParts(message, isAccountLimited: isAccountLimited).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
Assert.AreEqual(4, output.Count);
|
Assert.AreEqual(4, output.Count);
|
||||||
|
|
||||||
Assert.AreEqual(newlinePart + ParagraphCharacter, output[0]);
|
Assert.AreEqual($"{newlinePart}{ParagraphCharacter}", output[0]);
|
||||||
Assert.AreEqual(newlinePart + ParagraphCharacter, output[1]);
|
Assert.AreEqual($"{newlinePart}{ParagraphCharacter}", output[1]);
|
||||||
Assert.AreEqual(newlinePart + ParagraphCharacter, output[2]);
|
Assert.AreEqual($"{newlinePart}{ParagraphCharacter}", output[2]);
|
||||||
Assert.AreEqual(newlinePart, output[3]);
|
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)}";
|
networkGroupText = $"-{BitConverter.ToString(SHA256.HashData(Encoding.UTF8.GetBytes(GlobalConfig.WebProxyText!))).Replace("-", "", StringComparison.Ordinal)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfirmationsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(ConfirmationsSemaphore) + networkGroupText).ConfigureAwait(false);
|
ConfirmationsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(ConfirmationsSemaphore)}{networkGroupText}").ConfigureAwait(false);
|
||||||
GiftsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(GiftsSemaphore) + networkGroupText).ConfigureAwait(false);
|
GiftsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(GiftsSemaphore)}{networkGroupText}").ConfigureAwait(false);
|
||||||
InventorySemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(InventorySemaphore) + networkGroupText).ConfigureAwait(false);
|
InventorySemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(InventorySemaphore)}{networkGroupText}").ConfigureAwait(false);
|
||||||
LoginRateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(LoginRateLimitingSemaphore) + networkGroupText).ConfigureAwait(false);
|
LoginRateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(LoginRateLimitingSemaphore)}{networkGroupText}").ConfigureAwait(false);
|
||||||
LoginSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(LoginSemaphore) + networkGroupText).ConfigureAwait(false);
|
LoginSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(LoginSemaphore)}{networkGroupText}").ConfigureAwait(false);
|
||||||
RateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(RateLimitingSemaphore) + networkGroupText).ConfigureAwait(false);
|
RateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(RateLimitingSemaphore)}{networkGroupText}").ConfigureAwait(false);
|
||||||
|
|
||||||
WebLimitingSemaphores ??= new Dictionary<Uri, (ICrossProcessSemaphore RateLimitingSemaphore, SemaphoreSlim OpenConnectionsSemaphore)>(4) {
|
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)) },
|
{ 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 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 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 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(
|
private static readonly ImmutableHashSet<Asset.EType> AcceptedMatchableTypes = ImmutableHashSet.Create(
|
||||||
Asset.EType.Emoticon,
|
Asset.EType.Emoticon,
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api;
|
|||||||
[ApiController]
|
[ApiController]
|
||||||
[Produces("application/json")]
|
[Produces("application/json")]
|
||||||
[Route("Api")]
|
[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.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.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.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.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.")]
|
[SwaggerResponse((int) HttpStatusCode.ServiceUnavailable, "ASF has encountered an error while requesting a third-party resource. Try again later.")]
|
||||||
public abstract class ArchiController : ControllerBase { }
|
public abstract class ArchiController : ControllerBase { }
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public sealed class StructureController : ArchiController {
|
|||||||
try {
|
try {
|
||||||
obj = Activator.CreateInstance(targetType, true);
|
obj = Activator.CreateInstance(targetType, true);
|
||||||
} catch (Exception e) {
|
} 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));
|
return Ok(new GenericResponse<object>(obj));
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public sealed class TwoFactorAuthenticationConfirmationsRequest {
|
|||||||
/// <summary>
|
/// <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.
|
/// 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>
|
/// </summary>
|
||||||
[JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(AcceptedCreatorIDs), Required = Required.DisallowNull)]
|
[JsonProperty(PropertyName = $"{SharedInfo.UlongCompatibilityStringPrefix}{nameof(AcceptedCreatorIDs)}", Required = Required.DisallowNull)]
|
||||||
public ImmutableHashSet<string> SAcceptedCreatorIDs {
|
public ImmutableHashSet<string> SAcceptedCreatorIDs {
|
||||||
get => AcceptedCreatorIDs.Select(static creatorID => creatorID.ToString(CultureInfo.InvariantCulture)).ToImmutableHashSet();
|
get => AcceptedCreatorIDs.Select(static creatorID => creatorID.ToString(CultureInfo.InvariantCulture)).ToImmutableHashSet();
|
||||||
set {
|
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
|
// 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 {
|
try {
|
||||||
await File.WriteAllTextAsync(SharedInfo.LogFile, message).ConfigureAwait(false);
|
await File.WriteAllTextAsync(SharedInfo.LogFile, message).ConfigureAwait(false);
|
||||||
@@ -191,7 +191,7 @@ public sealed class ArchiLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
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 {
|
try {
|
||||||
await File.AppendAllTextAsync(SharedInfo.LogFile, message).ConfigureAwait(false);
|
await File.AppendAllTextAsync(SharedInfo.LogFile, message).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ internal static class Logging {
|
|||||||
internal const string NLogConfigurationFile = "NLog.config";
|
internal const string NLogConfigurationFile = "NLog.config";
|
||||||
|
|
||||||
private const byte ConsoleResponsivenessDelay = 250; // In milliseconds
|
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 const string LayoutMessage = @"${logger}|${message}${onexception:inner= ${exception:format=toString,Data}}";
|
||||||
|
|
||||||
private static readonly ConcurrentHashSet<LoggingRule> ConsoleLoggingRules = new();
|
private static readonly ConcurrentHashSet<LoggingRule> ConsoleLoggingRules = new();
|
||||||
|
|||||||
@@ -37,20 +37,20 @@ public static class SharedInfo {
|
|||||||
internal const string ArchivalLogsDirectory = "logs";
|
internal const string ArchivalLogsDirectory = "logs";
|
||||||
internal const string ASF = nameof(ASF);
|
internal const string ASF = nameof(ASF);
|
||||||
internal const ulong ASFGroupSteamID = 103582791440160998;
|
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 AssemblyName = nameof(ArchiSteamFarm);
|
||||||
internal const string DatabaseExtension = ".db";
|
internal const string DatabaseExtension = ".db";
|
||||||
internal const string DebugDirectory = "debug";
|
internal const string DebugDirectory = "debug";
|
||||||
internal const string EnvironmentVariableCryptKey = ASF + "_CRYPTKEY";
|
internal const string EnvironmentVariableCryptKey = $"{ASF}_CRYPTKEY";
|
||||||
internal const string EnvironmentVariableNetworkGroup = ASF + "_NETWORK_GROUP";
|
internal const string EnvironmentVariableNetworkGroup = $"{ASF}_NETWORK_GROUP";
|
||||||
internal const string EnvironmentVariablePath = ASF + "_PATH";
|
internal const string EnvironmentVariablePath = $"{ASF}_PATH";
|
||||||
internal const string GithubReleaseURL = "https://api.github.com/repos/" + GithubRepo + "/releases";
|
internal const string GithubReleaseURL = $"https://api.github.com/repos/{GithubRepo}/releases";
|
||||||
internal const string GithubRepo = "JustArchiNET/" + AssemblyName;
|
internal const string GithubRepo = $"JustArchiNET/{AssemblyName}";
|
||||||
internal const string GlobalConfigFileName = ASF + JsonConfigExtension;
|
internal const string GlobalConfigFileName = $"{ASF}{JsonConfigExtension}";
|
||||||
internal const string GlobalDatabaseFileName = ASF + DatabaseExtension;
|
internal const string GlobalDatabaseFileName = $"{ASF}{DatabaseExtension}";
|
||||||
internal const ushort InformationDelay = 10000;
|
internal const ushort InformationDelay = 10000;
|
||||||
internal const string IPCConfigExtension = ".config";
|
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 JsonConfigExtension = ".json";
|
||||||
internal const string KeysExtension = ".keys";
|
internal const string KeysExtension = ".keys";
|
||||||
internal const string KeysUnusedExtension = ".unused";
|
internal const string KeysUnusedExtension = ".unused";
|
||||||
@@ -61,7 +61,7 @@ public static class SharedInfo {
|
|||||||
internal const string LolcatCultureName = "qps-Ploc";
|
internal const string LolcatCultureName = "qps-Ploc";
|
||||||
internal const string MobileAuthenticatorExtension = ".maFile";
|
internal const string MobileAuthenticatorExtension = ".maFile";
|
||||||
internal const string PluginsDirectory = "plugins";
|
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 string SentryHashExtension = ".bin";
|
||||||
internal const ushort ShortInformationDelay = InformationDelay / 2;
|
internal const ushort ShortInformationDelay = InformationDelay / 2;
|
||||||
internal const string StatisticsServer = "asf.justarchi.net";
|
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 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));
|
internal static Version Version => Assembly.GetExecutingAssembly().GetName().Version ?? throw new InvalidOperationException(nameof(Version));
|
||||||
|
|
||||||
private static Guid ModuleVersion => Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId;
|
private static Guid ModuleVersion => Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId;
|
||||||
|
|||||||
@@ -180,8 +180,7 @@ public sealed class Bot : IAsyncDisposable {
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
private bool ShouldUseLoginKeys => BotConfig.UseLoginKeys && (!BotConfig.IsSteamPasswordSet || string.IsNullOrEmpty(BotConfig.DecryptedSteamPassword) || !HasMobileAuthenticator);
|
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);
|
private string SSteamID => SteamID.ToString(CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
@@ -523,13 +522,13 @@ public sealed class Bot : IAsyncDisposable {
|
|||||||
string botPath = Path.Combine(SharedInfo.ConfigDirectory, botName);
|
string botPath = Path.Combine(SharedInfo.ConfigDirectory, botName);
|
||||||
|
|
||||||
return fileType switch {
|
return fileType switch {
|
||||||
EFileType.Config => botPath + SharedInfo.JsonConfigExtension,
|
EFileType.Config => $"{botPath}{SharedInfo.JsonConfigExtension}",
|
||||||
EFileType.Database => botPath + SharedInfo.DatabaseExtension,
|
EFileType.Database => $"{botPath}{SharedInfo.DatabaseExtension}",
|
||||||
EFileType.KeysToRedeem => botPath + SharedInfo.KeysExtension,
|
EFileType.KeysToRedeem => $"{botPath}{SharedInfo.KeysExtension}",
|
||||||
EFileType.KeysToRedeemUnused => botPath + SharedInfo.KeysExtension + SharedInfo.KeysUnusedExtension,
|
EFileType.KeysToRedeemUnused => $"{botPath}{SharedInfo.KeysExtension}{SharedInfo.KeysUnusedExtension}",
|
||||||
EFileType.KeysToRedeemUsed => botPath + SharedInfo.KeysExtension + SharedInfo.KeysUsedExtension,
|
EFileType.KeysToRedeemUsed => $"{botPath}{SharedInfo.KeysExtension}{SharedInfo.KeysUsedExtension}",
|
||||||
EFileType.MobileAuthenticator => botPath + SharedInfo.MobileAuthenticatorExtension,
|
EFileType.MobileAuthenticator => $"{botPath}{SharedInfo.MobileAuthenticatorExtension}",
|
||||||
EFileType.SentryFile => botPath + SharedInfo.SentryHashExtension,
|
EFileType.SentryFile => $"{botPath}{SharedInfo.SentryHashExtension}",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(fileType))
|
_ => throw new ArgumentOutOfRangeException(nameof(fileType))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -2741,7 +2740,7 @@ public sealed class Bot : IAsyncDisposable {
|
|||||||
AccountFlags = callback.AccountFlags;
|
AccountFlags = callback.AccountFlags;
|
||||||
SteamID = callback.ClientSteamID ?? throw new InvalidOperationException(nameof(callback.ClientSteamID));
|
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
|
// Old status for these doesn't matter, we'll update them if needed
|
||||||
InvalidPasswordFailures = TwoFactorCodeFailures = 0;
|
InvalidPasswordFailures = TwoFactorCodeFailures = 0;
|
||||||
@@ -2765,7 +2764,7 @@ public sealed class Bot : IAsyncDisposable {
|
|||||||
|
|
||||||
// Handle steamID-based maFile
|
// Handle steamID-based maFile
|
||||||
if (!HasMobileAuthenticator) {
|
if (!HasMobileAuthenticator) {
|
||||||
string maFilePath = Path.Combine(SharedInfo.ConfigDirectory, SteamID + SharedInfo.MobileAuthenticatorExtension);
|
string maFilePath = Path.Combine(SharedInfo.ConfigDirectory, $"{SteamID}{SharedInfo.MobileAuthenticatorExtension}");
|
||||||
|
|
||||||
if (File.Exists(maFilePath)) {
|
if (File.Exists(maFilePath)) {
|
||||||
await ImportAuthenticatorFromFile(maFilePath).ConfigureAwait(false);
|
await ImportAuthenticatorFromFile(maFilePath).ConfigureAwait(false);
|
||||||
@@ -3244,7 +3243,7 @@ public sealed class Bot : IAsyncDisposable {
|
|||||||
name = string.Join(", ", result.Items.Values);
|
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);
|
string filePath = GetFilePath(redeemed ? EFileType.KeysToRedeemUsed : EFileType.KeysToRedeemUnused);
|
||||||
|
|
||||||
@@ -3255,7 +3254,7 @@ public sealed class Bot : IAsyncDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await File.AppendAllTextAsync(filePath, logEntry + Environment.NewLine).ConfigureAwait(false);
|
await File.AppendAllTextAsync(filePath, $"{logEntry}{Environment.NewLine}").ConfigureAwait(false);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ArchiLogger.LogGenericException(e);
|
ArchiLogger.LogGenericException(e);
|
||||||
ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.Content, logEntry));
|
ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.Content, logEntry));
|
||||||
|
|||||||
@@ -2226,7 +2226,7 @@ public sealed class Commands {
|
|||||||
ownedGamesStats[gameID] = ownedGameStats;
|
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));
|
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) {
|
foreach (string game in games) {
|
||||||
if (!uint.TryParse(game, out uint gameID) || (gameID == 0)) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3408,7 +3412,7 @@ public sealed class Commands {
|
|||||||
|
|
||||||
(bool success, string? message, Version? version) = await Actions.Update().ConfigureAwait(false);
|
(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) {
|
private string? ResponseVersion(ulong steamID) {
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ public sealed class BotConfig {
|
|||||||
private string? BackingSteamParentalCode = DefaultSteamParentalCode;
|
private string? BackingSteamParentalCode = DefaultSteamParentalCode;
|
||||||
private string? BackingSteamPassword = DefaultSteamPassword;
|
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 {
|
private string SSteamMasterClanID {
|
||||||
get => SteamMasterClanID.ToString(CultureInfo.InvariantCulture);
|
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;
|
private string? BackingLoginKey;
|
||||||
|
|
||||||
[JsonProperty(PropertyName = "_" + nameof(MobileAuthenticator))]
|
[JsonProperty(PropertyName = $"_{nameof(MobileAuthenticator)}")]
|
||||||
private MobileAuthenticator? BackingMobileAuthenticator;
|
private MobileAuthenticator? BackingMobileAuthenticator;
|
||||||
|
|
||||||
private BotDatabase(string filePath) {
|
private BotDatabase(string filePath) {
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ public sealed class GlobalConfig {
|
|||||||
private WebProxy? BackingWebProxy;
|
private WebProxy? BackingWebProxy;
|
||||||
private string? BackingWebProxyPassword = DefaultWebProxyPassword;
|
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 {
|
private string SSteamOwnerID {
|
||||||
get => SteamOwnerID.ToString(CultureInfo.InvariantCulture);
|
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;
|
private uint BackingCellID;
|
||||||
|
|
||||||
[JsonProperty(PropertyName = "_" + nameof(LastChangeNumber), Required = Required.DisallowNull)]
|
[JsonProperty(PropertyName = $"_{nameof(LastChangeNumber)}", Required = Required.DisallowNull)]
|
||||||
private uint BackingLastChangeNumber;
|
private uint BackingLastChangeNumber;
|
||||||
|
|
||||||
private GlobalDatabase(string filePath) : this() {
|
private GlobalDatabase(string filePath) : this() {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace ArchiSteamFarm.Web;
|
|||||||
|
|
||||||
internal static class GitHub {
|
internal static class GitHub {
|
||||||
internal static async Task<ReleaseResponse?> GetLatestRelease(bool stable = true) {
|
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) {
|
if (stable) {
|
||||||
return await GetReleaseFromURL(request).ConfigureAwait(false);
|
return await GetReleaseFromURL(request).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ using JetBrains.Annotations;
|
|||||||
|
|
||||||
namespace ArchiSteamFarm.Web.Responses;
|
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 {
|
public sealed class StringResponse : BasicResponse {
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string Content { get; }
|
public string Content { get; }
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ using JetBrains.Annotations;
|
|||||||
|
|
||||||
namespace ArchiSteamFarm.Web.Responses;
|
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 {
|
public sealed class XmlDocumentResponse : BasicResponse {
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public XmlDocument Content { get; }
|
public XmlDocument Content { get; }
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ public sealed class WebBrowser : IDisposable {
|
|||||||
return null;
|
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]
|
[PublicAPI]
|
||||||
public async Task<StringResponse?> UrlGetToString(Uri request, IReadOnlyCollection<KeyValuePair<string, string>>? headers = null, Uri? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) {
|
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) {
|
if (request == null) {
|
||||||
@@ -404,7 +404,7 @@ public sealed class WebBrowser : IDisposable {
|
|||||||
return null;
|
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]
|
[PublicAPI]
|
||||||
public async Task<XmlDocumentResponse?> UrlGetToXmlDocument(Uri request, IReadOnlyCollection<KeyValuePair<string, string>>? headers = null, Uri? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) {
|
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) {
|
if (request == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user