Use static lambdas wherever possible

Thanks Rider
This commit is contained in:
Archi
2021-09-27 21:33:52 +02:00
parent f2d3a2a894
commit 7e9e90764b
39 changed files with 236 additions and 234 deletions

View File

@@ -84,7 +84,7 @@ namespace ArchiSteamFarm.IPC {
// Firstly initialize settings that user is free to override
builder.ConfigureLogging(
logging => {
static logging => {
logging.ClearProviders();
logging.SetMinimumLevel(Debugging.IsUserDebugging ? LogLevel.Trace : LogLevel.Warning);
}
@@ -112,7 +112,7 @@ namespace ArchiSteamFarm.IPC {
}
// Use custom config for logging configuration
builder.ConfigureLogging((hostingContext, logging) => logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")));
builder.ConfigureLogging(static (hostingContext, logging) => logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")));
}
// Enable NLog integration for logging
@@ -129,10 +129,10 @@ namespace ArchiSteamFarm.IPC {
webBuilder.UseConfiguration(new ConfigurationBuilder().SetBasePath(absoluteConfigDirectory).AddJsonFile(SharedInfo.IPCConfigFile, false, Program.ConfigWatch).Build());
// Use custom config for Kestrel configuration
webBuilder.UseKestrel((builderContext, options) => options.Configure(builderContext.Configuration.GetSection("Kestrel")));
webBuilder.UseKestrel(static (builderContext, options) => options.Configure(builderContext.Configuration.GetSection("Kestrel")));
} else {
// Use ASF defaults for Kestrel
webBuilder.UseKestrel(options => options.ListenLocalhost(1242));
webBuilder.UseKestrel(static options => options.ListenLocalhost(1242));
}
// Specify Startup class for IPC

View File

@@ -60,9 +60,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
}
IList<bool> results = await Utilities.InParallel(bots.Select(bot => bot.DeleteAllRelatedFiles())).ConfigureAwait(false);
IList<bool> results = await Utilities.InParallel(bots.Select(static bot => bot.DeleteAllRelatedFiles())).ConfigureAwait(false);
return Ok(new GenericResponse(results.All(result => result)));
return Ok(new GenericResponse(results.All(static result => result)));
}
/// <summary>
@@ -82,7 +82,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(bots))));
}
return Ok(new GenericResponse<IReadOnlyDictionary<string, Bot>>(bots.Where(bot => !string.IsNullOrEmpty(bot.BotName)).ToDictionary(bot => bot.BotName, bot => bot, Bot.BotsComparer)));
return Ok(new GenericResponse<IReadOnlyDictionary<string, Bot>>(bots.Where(static bot => !string.IsNullOrEmpty(bot.BotName)).ToDictionary(static bot => bot.BotName, static bot => bot, Bot.BotsComparer)));
}
/// <summary>
@@ -115,7 +115,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
HashSet<string> bots = botNames.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToHashSet(Bot.BotsComparer);
if (bots.Any(botName => !ASF.IsValidBotName(botName))) {
if (bots.Any(static botName => !ASF.IsValidBotName(botName))) {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(botNames))));
}
@@ -157,7 +157,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
result[botName] = await BotConfig.Write(filePath, request.BotConfig).ConfigureAwait(false);
}
return Ok(new GenericResponse<IReadOnlyDictionary<string, bool>>(result.Values.All(value => value), result));
return Ok(new GenericResponse<IReadOnlyDictionary<string, bool>>(result.Values.All(static value => value), result));
}
/// <summary>
@@ -177,9 +177,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
}
IList<bool> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.DeleteRedeemedKeysFiles))).ConfigureAwait(false);
IList<bool> results = await Utilities.InParallel(bots.Select(static bot => Task.Run(bot.DeleteRedeemedKeysFiles))).ConfigureAwait(false);
return Ok(results.All(result => result) ? new GenericResponse(true) : new GenericResponse(false, Strings.WarningFailed));
return Ok(results.All(static result => result) ? new GenericResponse(true) : new GenericResponse(false, Strings.WarningFailed));
}
/// <summary>
@@ -199,7 +199,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
}
IList<(Dictionary<string, string>? UnusedKeys, Dictionary<string, string>? UsedKeys)> results = await Utilities.InParallel(bots.Select(bot => bot.GetUsedAndUnusedKeys())).ConfigureAwait(false);
IList<(Dictionary<string, string>? UnusedKeys, Dictionary<string, string>? UsedKeys)> results = await Utilities.InParallel(bots.Select(static bot => bot.GetUsedAndUnusedKeys())).ConfigureAwait(false);
Dictionary<string, GamesToRedeemInBackgroundResponse> result = new(bots.Count, Bot.BotsComparer);
@@ -282,7 +282,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
IList<bool> results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.SetUserInput(request.Type, request.Value)))).ConfigureAwait(false);
return Ok(results.All(result => result) ? new GenericResponse(true) : new GenericResponse(false, Strings.WarningFailed));
return Ok(results.All(static result => result) ? new GenericResponse(true) : new GenericResponse(false, Strings.WarningFailed));
}
/// <summary>
@@ -309,7 +309,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => bot.Actions.Pause(request.Permanent, request.ResumeInSeconds))).ConfigureAwait(false);
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Message))));
return Ok(new GenericResponse(results.All(static result => result.Success), string.Join(Environment.NewLine, results.Select(static result => result.Message))));
}
/// <summary>
@@ -342,7 +342,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
}
IList<PurchaseResponseCallback?> results = await Utilities.InParallel(bots.Select(bot => request.KeysToRedeem.Select(key => bot.Actions.RedeemKey(key))).SelectMany(task => task)).ConfigureAwait(false);
IList<PurchaseResponseCallback?> results = await Utilities.InParallel(bots.Select(bot => request.KeysToRedeem.Select(key => bot.Actions.RedeemKey(key))).SelectMany(static task => task)).ConfigureAwait(false);
Dictionary<string, IReadOnlyDictionary<string, PurchaseResponseCallback?>> result = new(bots.Count, Bot.BotsComparer);
@@ -357,7 +357,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
}
}
return Ok(new GenericResponse<IReadOnlyDictionary<string, IReadOnlyDictionary<string, PurchaseResponseCallback?>>>(result.Values.SelectMany(responses => responses.Values).All(value => value != null), result));
return Ok(new GenericResponse<IReadOnlyDictionary<string, IReadOnlyDictionary<string, PurchaseResponseCallback?>>>(result.Values.SelectMany(static responses => responses.Values).All(static value => value != null), result));
}
/// <summary>
@@ -410,9 +410,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
}
IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.Actions.Resume))).ConfigureAwait(false);
IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(static bot => Task.Run(bot.Actions.Resume))).ConfigureAwait(false);
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Message))));
return Ok(new GenericResponse(results.All(static result => result.Success), string.Join(Environment.NewLine, results.Select(static result => result.Message))));
}
/// <summary>
@@ -432,9 +432,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
}
IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.Actions.Start))).ConfigureAwait(false);
IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(static bot => Task.Run(bot.Actions.Start))).ConfigureAwait(false);
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Message))));
return Ok(new GenericResponse(results.All(static result => result.Success), string.Join(Environment.NewLine, results.Select(static result => result.Message))));
}
/// <summary>
@@ -454,9 +454,9 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
}
IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.Actions.Stop))).ConfigureAwait(false);
IList<(bool Success, string Message)> results = await Utilities.InParallel(bots.Select(static bot => Task.Run(bot.Actions.Stop))).ConfigureAwait(false);
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Message))));
return Ok(new GenericResponse(results.All(static result => result.Success), string.Join(Environment.NewLine, results.Select(static result => result.Message))));
}
/// <summary>
@@ -513,7 +513,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, GenericResponse<string>>>(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)));
}
IList<(bool Success, string? Token, string Message)> results = await Utilities.InParallel(bots.Select(bot => bot.Actions.GenerateTwoFactorAuthenticationToken())).ConfigureAwait(false);
IList<(bool Success, string? Token, string Message)> results = await Utilities.InParallel(bots.Select(static bot => bot.Actions.GenerateTwoFactorAuthenticationToken())).ConfigureAwait(false);
Dictionary<string, GenericResponse<string>> result = new(bots.Count, Bot.BotsComparer);

View File

@@ -61,7 +61,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsInvalid, nameof(ASF.GlobalConfig.SteamOwnerID))));
}
Bot? targetBot = Bot.Bots?.OrderBy(bot => bot.Key, Bot.BotsComparer).Select(bot => bot.Value).FirstOrDefault();
Bot? targetBot = Bot.Bots?.OrderBy(static bot => bot.Key, Bot.BotsComparer).Select(static bot => bot.Value).FirstOrDefault();
if (targetBot == null) {
return BadRequest(new GenericResponse(false, Strings.ErrorNoBotsDefined));

View File

@@ -124,7 +124,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
string json = JsonConvert.SerializeObject(new GenericResponse<string>(newHistoryEntryArgs.Message));
await Task.WhenAll(ActiveLogWebSockets.Where(kv => kv.Key.State == WebSocketState.Open).Select(kv => PostLoggedJsonUpdate(kv.Key, json, kv.Value.Semaphore, kv.Value.CancellationToken))).ConfigureAwait(false);
await Task.WhenAll(ActiveLogWebSockets.Where(static kv => kv.Key.State == WebSocketState.Open).Select(kv => PostLoggedJsonUpdate(kv.Key, json, kv.Value.Semaphore, kv.Value.CancellationToken))).ConfigureAwait(false);
}
private static async Task PostLoggedJsonUpdate(WebSocket webSocket, string json, SemaphoreSlim sendSemaphore, CancellationToken cancellationToken) {

View File

@@ -55,13 +55,13 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
}
string? baseType = targetType.BaseType?.GetUnifiedName();
HashSet<string> customAttributes = targetType.CustomAttributes.Select(attribute => attribute.AttributeType.GetUnifiedName()).Where(customAttribute => !string.IsNullOrEmpty(customAttribute)).ToHashSet(StringComparer.Ordinal)!;
HashSet<string> customAttributes = targetType.CustomAttributes.Select(static attribute => attribute.AttributeType.GetUnifiedName()).Where(static customAttribute => !string.IsNullOrEmpty(customAttribute)).ToHashSet(StringComparer.Ordinal)!;
string? underlyingType = null;
Dictionary<string, string> body = new(StringComparer.Ordinal);
if (targetType.IsClass) {
foreach (FieldInfo field in targetType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Where(field => !field.IsPrivate)) {
foreach (FieldInfo field in targetType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Where(static field => !field.IsPrivate)) {
JsonPropertyAttribute? jsonProperty = field.GetCustomAttribute<JsonPropertyAttribute>();
if (jsonProperty != null) {
@@ -74,7 +74,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
}
}
foreach (PropertyInfo property in targetType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Where(property => property.CanRead && (property.GetMethod?.IsPrivate == false))) {
foreach (PropertyInfo property in targetType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Where(static property => property.CanRead && (property.GetMethod?.IsPrivate == false))) {
JsonPropertyAttribute? jsonProperty = property.GetCustomAttribute<JsonPropertyAttribute>();
if (jsonProperty != null) {

View File

@@ -141,7 +141,7 @@ namespace ArchiSteamFarm.IPC.Integration {
return (HttpStatusCode.Unauthorized, true);
}
string? inputPassword = passwords.FirstOrDefault(password => !string.IsNullOrEmpty(password));
string? inputPassword = passwords.FirstOrDefault(static password => !string.IsNullOrEmpty(password));
if (string.IsNullOrEmpty(inputPassword)) {
return (HttpStatusCode.Unauthorized, true);

View File

@@ -40,11 +40,11 @@ namespace ArchiSteamFarm.IPC.Integration {
OpenApiArray validValues = new();
if (ValidIntValues != null) {
validValues.AddRange(ValidIntValues.Select(type => new OpenApiInteger(type)));
validValues.AddRange(ValidIntValues.Select(static type => new OpenApiInteger(type)));
}
if (ValidStringValues != null) {
validValues.AddRange(ValidStringValues.Select(type => new OpenApiString(type)));
validValues.AddRange(ValidStringValues.Select(static type => new OpenApiString(type)));
}
if (schema.Items is { Reference: null }) {

View File

@@ -56,7 +56,7 @@ namespace ArchiSteamFarm.IPC.Requests {
/// </summary>
[JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(AcceptedCreatorIDs), Required = Required.DisallowNull)]
public ImmutableHashSet<string> SAcceptedCreatorIDs {
get => AcceptedCreatorIDs.Select(creatorID => creatorID.ToString(CultureInfo.InvariantCulture)).ToImmutableHashSet();
get => AcceptedCreatorIDs.Select(static creatorID => creatorID.ToString(CultureInfo.InvariantCulture)).ToImmutableHashSet();
set {
if (value == null) {
throw new ArgumentNullException(nameof(value));

View File

@@ -98,7 +98,7 @@ namespace ArchiSteamFarm.IPC {
// The default HTML file (usually index.html) is responsible for IPC GUI routing, so re-execute all non-API calls on /
// This must be called before default files, because we don't know the exact file name that will be used for index page
app.UseWhen(context => !context.Request.Path.StartsWithSegments("/Api", StringComparison.OrdinalIgnoreCase), appBuilder => appBuilder.UseStatusCodePagesWithReExecute("/"));
app.UseWhen(static context => !context.Request.Path.StartsWithSegments("/Api", StringComparison.OrdinalIgnoreCase), static appBuilder => appBuilder.UseStatusCodePagesWithReExecute("/"));
// Add support for default root path redirection (GET / -> GET /index.html), must come before static files
app.UseDefaultFiles();
@@ -106,7 +106,7 @@ namespace ArchiSteamFarm.IPC {
// Add support for static files (e.g. HTML, CSS and JS from IPC GUI)
app.UseStaticFiles(
new StaticFileOptions {
OnPrepareResponse = context => {
OnPrepareResponse = static context => {
if (context.File.Exists && !context.File.IsDirectory && !string.IsNullOrEmpty(context.File.Name)) {
string extension = Path.GetExtension(context.File.Name);
@@ -146,7 +146,7 @@ namespace ArchiSteamFarm.IPC {
#endif
// We want to protect our API with IPCPassword and additional security, this should be called after routing, so the middleware won't have to deal with API endpoints that do not exist
app.UseWhen(context => context.Request.Path.StartsWithSegments("/Api", StringComparison.OrdinalIgnoreCase), appBuilder => appBuilder.UseMiddleware<ApiAuthenticationMiddleware>());
app.UseWhen(static context => context.Request.Path.StartsWithSegments("/Api", StringComparison.OrdinalIgnoreCase), static appBuilder => appBuilder.UseMiddleware<ApiAuthenticationMiddleware>());
string? ipcPassword = ASF.GlobalConfig != null ? ASF.GlobalConfig.IPCPassword : GlobalConfig.DefaultIPCPassword;
@@ -163,7 +163,7 @@ namespace ArchiSteamFarm.IPC {
#if NETFRAMEWORK
app.UseMvcWithDefaultRoute();
#else
app.UseEndpoints(endpoints => endpoints.MapControllers());
app.UseEndpoints(static endpoints => endpoints.MapControllers());
#endif
// Add support for swagger, responsible for automatic API documentation generation, this should be on the end, once we're done with API
@@ -171,7 +171,7 @@ namespace ArchiSteamFarm.IPC {
// Add support for swagger UI, this should be after swagger, obviously
app.UseSwaggerUI(
options => {
static options => {
options.DisplayRequestDuration();
options.EnableDeepLinking();
options.ShowExtensions();
@@ -237,12 +237,12 @@ namespace ArchiSteamFarm.IPC {
if (!string.IsNullOrEmpty(ipcPassword)) {
// We want to apply CORS policy in order to allow userscripts and other third-party integrations to communicate with ASF API
// We apply CORS policy only with IPCPassword set as an extra authentication measure
services.AddCors(options => options.AddDefaultPolicy(policyBuilder => policyBuilder.AllowAnyOrigin()));
services.AddCors(static options => options.AddDefaultPolicy(static policyBuilder => policyBuilder.AllowAnyOrigin()));
}
// Add support for swagger, responsible for automatic API documentation generation
services.AddSwaggerGen(
options => {
static options => {
options.AddSecurityDefinition(
nameof(GlobalConfig.IPCPassword), new OpenApiSecurityScheme {
Description = $"{nameof(GlobalConfig.IPCPassword)} authentication using request headers. Check {SharedInfo.ProjectURL}/wiki/IPC#authentication for more info.",
@@ -267,7 +267,7 @@ namespace ArchiSteamFarm.IPC {
}
);
options.CustomSchemaIds(type => type.GetUnifiedName());
options.CustomSchemaIds(static type => type.GetUnifiedName());
options.EnableAnnotations(true, true);
options.SchemaFilter<CustomAttributesSchemaFilter>();
@@ -339,7 +339,7 @@ namespace ArchiSteamFarm.IPC {
#else
mvc.AddNewtonsoftJson(
#endif
options => {
static options => {
// Fix default contract resolver to use original names and not a camel case
options.SerializerSettings.ContractResolver = new DefaultContractResolver();

View File

@@ -37,7 +37,7 @@ namespace ArchiSteamFarm.IPC {
throw new ArgumentNullException(nameof(type));
}
return type.GenericTypeArguments.Length == 0 ? type.FullName : $"{type.Namespace}.{type.Name}{string.Join("", type.GenericTypeArguments.Select(innerType => $"[{innerType.GetUnifiedName()}]"))}";
return type.GenericTypeArguments.Length == 0 ? type.FullName : $"{type.Namespace}.{type.Name}{string.Join("", type.GenericTypeArguments.Select(static innerType => $"[{innerType.GetUnifiedName()}]"))}";
}
internal static Type? ParseType(string typeText) {