Skip to content

Commit

Permalink
Add helpful limitations on properties for JustArchiNET/ASF-ui#1445
Browse files Browse the repository at this point in the history
Monologue explaining how it works: https://ptb.discord.com/channels/267292556709068800/332735075315744768/859854787634004049

(eventually also on wiki)
  • Loading branch information
JustArchi committed Jun 30, 2021
1 parent 689dbc4 commit 874eb4d
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 1 deletion.
87 changes: 87 additions & 0 deletions ArchiSteamFarm/IPC/Integration/BotConfigSchemaFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// _ _ _ ____ _ _____
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
// |
// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki
// Contact: JustArchi@JustArchi.net
// |
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// |
// http://www.apache.org/licenses/LICENSE-2.0
// |
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Linq;
using ArchiSteamFarm.Steam.Storage;
using JetBrains.Annotations;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
using SteamKit2;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace ArchiSteamFarm.IPC.Integration {
[UsedImplicitly]
internal sealed class BotConfigSchemaFilter : ISchemaFilter {
public void Apply(OpenApiSchema schema, SchemaFilterContext context) {
if (schema == null) {
throw new ArgumentNullException(nameof(schema));
}

if (context == null) {
throw new ArgumentNullException(nameof(context));
}

if (context.MemberInfo?.DeclaringType != typeof(BotConfig)) {
return;
}

OpenApiArray validValues;

switch (context.MemberInfo.Name) {
case nameof(BotConfig.CompleteTypesToSend):
validValues = new OpenApiArray();

validValues.AddRange(BotConfig.AllowedCompleteTypesToSend.Select(type => new OpenApiInteger((int) type)));

// Note, we'd love to add this to schema.Items, but since items are ref to the enum, it's not possible to add it that way
schema.AddExtension("x-valid-values", validValues);

break;
case nameof(BotConfig.GamesPlayedWhileIdle):
schema.Items.Minimum = 1;
schema.Items.Maximum = uint.MaxValue;

break;
case nameof(BotConfig.SteamMasterClanID):
schema.Maximum = new SteamID(uint.MaxValue, EUniverse.Public, EAccountType.Clan);
schema.Minimum = new SteamID(1, EUniverse.Public, EAccountType.Clan);

validValues = new OpenApiArray();

validValues.Add(new OpenApiInteger(0));

schema.AddExtension("x-valid-values", validValues);

break;
case nameof(BotConfig.SteamParentalCode):
validValues = new OpenApiArray();

validValues.Add(new OpenApiString("0"));

schema.AddExtension("x-valid-values", validValues);

break;
}
}
}
}
67 changes: 67 additions & 0 deletions ArchiSteamFarm/IPC/Integration/GlobalConfigSchemaFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// _ _ _ ____ _ _____
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
// |
// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki
// Contact: JustArchi@JustArchi.net
// |
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// |
// http://www.apache.org/licenses/LICENSE-2.0
// |
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using ArchiSteamFarm.Storage;
using JetBrains.Annotations;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
using SteamKit2;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace ArchiSteamFarm.IPC.Integration {
[UsedImplicitly]
internal sealed class GlobalConfigSchemaFilter : ISchemaFilter {
public void Apply(OpenApiSchema schema, SchemaFilterContext context) {
if (schema == null) {
throw new ArgumentNullException(nameof(schema));
}

if (context == null) {
throw new ArgumentNullException(nameof(context));
}

if (context.MemberInfo?.DeclaringType != typeof(GlobalConfig)) {
return;
}

switch (context.MemberInfo.Name) {
case nameof(GlobalConfig.Blacklist):
schema.Items.Minimum = 1;
schema.Items.Maximum = uint.MaxValue;

break;
case nameof(GlobalConfig.SteamOwnerID):
schema.Maximum = new SteamID(uint.MaxValue, EUniverse.Public, EAccountType.Individual);
schema.Minimum = new SteamID(1, EUniverse.Public, EAccountType.Individual);

OpenApiArray validValues = new();

validValues.Add(new OpenApiInteger(0));

schema.AddExtension("x-valid-values", validValues);

break;
}
}
}
}
3 changes: 3 additions & 0 deletions ArchiSteamFarm/IPC/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,10 @@ public void ConfigureServices(IServiceCollection services) {

options.CustomSchemaIds(type => type.GetUnifiedName());
options.EnableAnnotations(true, true);

options.SchemaFilter<BotConfigSchemaFilter>();
options.SchemaFilter<EnumSchemaFilter>();
options.SchemaFilter<GlobalConfigSchemaFilter>();

options.SwaggerDoc(
SharedInfo.ASF, new OpenApiInfo {
Expand Down
14 changes: 13 additions & 1 deletion ArchiSteamFarm/Steam/Storage/BotConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
Expand Down Expand Up @@ -173,9 +174,11 @@ public sealed class BotConfig {
public bool FarmPriorityQueueOnly { get; private set; } = DefaultFarmPriorityQueueOnly;

[JsonProperty(Required = Required.DisallowNull)]
[MaxLength(ArchiHandler.MaxGamesPlayedConcurrently)]
public ImmutableHashSet<uint> GamesPlayedWhileIdle { get; private set; } = DefaultGamesPlayedWhileIdle;

[JsonProperty(Required = Required.DisallowNull)]
[Range(byte.MinValue, byte.MaxValue)]
public byte HoursUntilCardDrops { get; private set; } = DefaultHoursUntilCardDrops;

[JsonProperty(Required = Required.DisallowNull)]
Expand All @@ -200,6 +203,7 @@ public sealed class BotConfig {
public bool SendOnFarmingFinished { get; private set; } = DefaultSendOnFarmingFinished;

[JsonProperty(Required = Required.DisallowNull)]
[Range(byte.MinValue, byte.MaxValue)]
public byte SendTradePeriod { get; private set; } = DefaultSendTradePeriod;

[JsonProperty(Required = Required.DisallowNull)]
Expand All @@ -222,6 +226,8 @@ internal set {
public ulong SteamMasterClanID { get; private set; } = DefaultSteamMasterClanID;

[JsonProperty]
[MaxLength(4)]
[MinLength(4)]
public string? SteamParentalCode {
get => BackingSteamParentalCode;

Expand All @@ -242,6 +248,8 @@ internal set {
}

[JsonProperty]
[MaxLength(8)]
[MinLength(8)]
public string? SteamTradeToken { get; private set; } = DefaultSteamTradeToken;

[JsonProperty(Required = Required.DisallowNull)]
Expand Down Expand Up @@ -367,8 +375,12 @@ public static async Task<bool> Write(string filePath, BotConfig botConfig) {
return (false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorConfigPropertyInvalid, nameof(FarmingOrders), farmingOrder));
}

if (GamesPlayedWhileIdle.Contains(0)) {
return (false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorConfigPropertyInvalid, nameof(GamesPlayedWhileIdle), 0));
}

if (GamesPlayedWhileIdle.Count > ArchiHandler.MaxGamesPlayedConcurrently) {
return (false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorConfigPropertyInvalid, nameof(GamesPlayedWhileIdle), GamesPlayedWhileIdle.Count + " > " + ArchiHandler.MaxGamesPlayedConcurrently));
return (false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorConfigPropertyInvalid, nameof(GamesPlayedWhileIdle), nameof(GamesPlayedWhileIdle.Count) + " " + GamesPlayedWhileIdle.Count + " > " + ArchiHandler.MaxGamesPlayedConcurrently));
}

foreach (Asset.EType lootableType in LootableTypes.Where(lootableType => !Enum.IsDefined(typeof(Asset.EType), lootableType))) {
Expand Down
17 changes: 17 additions & 0 deletions ArchiSteamFarm/Storage/GlobalConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
Expand Down Expand Up @@ -183,9 +184,11 @@ public WebProxy? WebProxy {
public string? CommandPrefix { get; private set; } = DefaultCommandPrefix;

[JsonProperty(Required = Required.DisallowNull)]
[Range(byte.MinValue, byte.MaxValue)]
public byte ConfirmationsLimiterDelay { get; private set; } = DefaultConfirmationsLimiterDelay;

[JsonProperty(Required = Required.DisallowNull)]
[Range(1, byte.MaxValue)]
public byte ConnectionTimeout { get; private set; } = DefaultConnectionTimeout;

[JsonProperty]
Expand All @@ -195,18 +198,22 @@ public WebProxy? WebProxy {
public bool Debug { get; private set; } = DefaultDebug;

[JsonProperty(Required = Required.DisallowNull)]
[Range(1, byte.MaxValue)]
public byte FarmingDelay { get; private set; } = DefaultFarmingDelay;

[JsonProperty(Required = Required.DisallowNull)]
[Range(byte.MinValue, byte.MaxValue)]
public byte GiftsLimiterDelay { get; private set; } = DefaultGiftsLimiterDelay;

[JsonProperty(Required = Required.DisallowNull)]
public bool Headless { get; private set; } = DefaultHeadless;

[JsonProperty(Required = Required.DisallowNull)]
[Range(byte.MinValue, byte.MaxValue)]
public byte IdleFarmingPeriod { get; private set; } = DefaultIdleFarmingPeriod;

[JsonProperty(Required = Required.DisallowNull)]
[Range(byte.MinValue, byte.MaxValue)]
public byte InventoryLimiterDelay { get; private set; } = DefaultInventoryLimiterDelay;

[JsonProperty(Required = Required.DisallowNull)]
Expand All @@ -219,12 +226,15 @@ public WebProxy? WebProxy {
public ArchiCryptoHelper.EHashingMethod IPCPasswordFormat { get; private set; } = DefaultIPCPasswordFormat;

[JsonProperty(Required = Required.DisallowNull)]
[Range(byte.MinValue, byte.MaxValue)]
public byte LoginLimiterDelay { get; private set; } = DefaultLoginLimiterDelay;

[JsonProperty(Required = Required.DisallowNull)]
[Range(1, byte.MaxValue)]
public byte MaxFarmingTime { get; private set; } = DefaultMaxFarmingTime;

[JsonProperty(Required = Required.DisallowNull)]
[Range(byte.MinValue, byte.MaxValue)]
public byte MaxTradeHoldDuration { get; private set; } = DefaultMaxTradeHoldDuration;

[JsonProperty(Required = Required.DisallowNull)]
Expand All @@ -234,6 +244,7 @@ public WebProxy? WebProxy {
public bool Statistics { get; private set; } = DefaultStatistics;

[JsonProperty]
[MaxLength(SteamChatMessage.MaxMessagePrefixBytes / 4)]
public string? SteamMessagePrefix { get; private set; } = DefaultSteamMessagePrefix;

[JsonProperty(Required = Required.DisallowNull)]
Expand All @@ -246,9 +257,11 @@ public WebProxy? WebProxy {
public EUpdateChannel UpdateChannel { get; private set; } = DefaultUpdateChannel;

[JsonProperty(Required = Required.DisallowNull)]
[Range(byte.MinValue, byte.MaxValue)]
public byte UpdatePeriod { get; private set; } = DefaultUpdatePeriod;

[JsonProperty(Required = Required.DisallowNull)]
[Range(ushort.MinValue, ushort.MaxValue)]
public ushort WebLimiterDelay { get; private set; } = DefaultWebLimiterDelay;

[JsonProperty(PropertyName = nameof(WebProxy))]
Expand Down Expand Up @@ -299,6 +312,10 @@ private string SSteamOwnerID {
internal GlobalConfig() { }

internal (bool Valid, string? ErrorMessage) CheckValidation() {
if (Blacklist.Contains(0)) {
return (false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorConfigPropertyInvalid, nameof(Blacklist), 0));
}

if (ConnectionTimeout == 0) {
return (false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorConfigPropertyInvalid, nameof(ConnectionTimeout), ConnectionTimeout));
}
Expand Down

0 comments on commit 874eb4d

Please sign in to comment.