diff --git a/ArchiSteamFarm/ArchiSteamFarm.csproj b/ArchiSteamFarm/ArchiSteamFarm.csproj index 73435fc5d..1cab6f32f 100644 --- a/ArchiSteamFarm/ArchiSteamFarm.csproj +++ b/ArchiSteamFarm/ArchiSteamFarm.csproj @@ -57,6 +57,7 @@ + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Net.Http.dll diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index afc0125e7..f44cc1efa 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -48,10 +48,9 @@ namespace ArchiSteamFarm { private const char DefaultBackgroundKeysRedeemerSeparator = '\t'; private const byte FamilySharingInactivityMinutes = 5; private const byte LoginCooldownInMinutes = 25; // Captcha disappears after around 20 minutes, so we make it 25 - private const uint LoginID = GlobalConfig.DefaultIPCPort; // This must be the same for all ASF bots and all ASF processes + private const uint LoginID = 1242; // This must be the same for all ASF bots and all ASF processes private const ushort MaxMessageLength = 5000; // This is a limitation enforced by Steam private const byte MaxTwoFactorCodeFailures = 3; - private const byte MinHeartBeatTTL = GlobalConfig.DefaultConnectionTimeout; // Assume client is responsive for at least that amount of seconds private const byte RedeemCooldownInHours = 1; // 1 hour since first redeem attempt, this is a limitation enforced by Steam private const byte ReservedMessageLength = 2; // 2 for 2x optional … @@ -1529,7 +1528,7 @@ namespace ArchiSteamFarm { } try { - if (DateTime.UtcNow.Subtract(ArchiHandler.LastPacketReceived).TotalSeconds > MinHeartBeatTTL) { + if (DateTime.UtcNow.Subtract(ArchiHandler.LastPacketReceived).TotalSeconds > Program.GlobalConfig.ConnectionTimeout) { await SteamFriends.RequestProfileInfo(SteamClient.SteamID); } diff --git a/ArchiSteamFarm/BotConfig.cs b/ArchiSteamFarm/BotConfig.cs index 99fa2ad35..cf51a2710 100644 --- a/ArchiSteamFarm/BotConfig.cs +++ b/ArchiSteamFarm/BotConfig.cs @@ -20,9 +20,10 @@ // limitations under the License. using System; -using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using ArchiSteamFarm.Json; @@ -33,95 +34,123 @@ using SteamKit2; namespace ArchiSteamFarm { [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] internal sealed class BotConfig { + private const bool DefaultAcceptGifts = false; + private const bool DefaultAutoSteamSaleEvent = false; + private const EBotBehaviour DefaultBotBehaviour = EBotBehaviour.None; + private const string DefaultCustomGamePlayedWhileFarming = null; + private const string DefaultCustomGamePlayedWhileIdle = null; + private const bool DefaultEnabled = false; + private const byte DefaultHoursUntilCardDrops = 3; + private const bool DefaultIdlePriorityQueueOnly = false; + private const bool DefaultIdleRefundableGames = true; + private const EPersonaState DefaultOnlineStatus = EPersonaState.Online; + private const CryptoHelper.ECryptoMethod DefaultPasswordFormat = CryptoHelper.ECryptoMethod.PlainText; + private const bool DefaultPaused = false; + private const ERedeemingPreferences DefaultRedeemingPreferences = ERedeemingPreferences.None; + private const bool DefaultSendOnFarmingFinished = false; + private const byte DefaultSendTradePeriod = 0; + private const bool DefaultShutdownOnFarmingFinished = false; + private const string DefaultSteamLogin = null; + private const ulong DefaultSteamMasterClanID = 0; + private const string DefaultSteamParentalPIN = "0"; + private const string DefaultSteamPassword = null; + private const string DefaultSteamTradeToken = null; + private const ETradingPreferences DefaultTradingPreferences = ETradingPreferences.None; + private const bool DefaultUseLoginKeys = true; + + private static readonly ImmutableHashSet DefaultFarmingOrders = ImmutableHashSet.Empty; + private static readonly ImmutableHashSet DefaultGamesPlayedWhileIdle = ImmutableHashSet.Empty; + private static readonly ImmutableHashSet DefaultLootableTypes = ImmutableHashSet.Create(Steam.Asset.EType.BoosterPack, Steam.Asset.EType.FoilTradingCard, Steam.Asset.EType.TradingCard); + private static readonly ImmutableHashSet DefaultMatchableTypes = ImmutableHashSet.Create(Steam.Asset.EType.TradingCard); + private static readonly ImmutableDictionary DefaultSteamUserPermissions = ImmutableDictionary.Empty; + private static readonly SemaphoreSlim WriteSemaphore = new SemaphoreSlim(1, 1); [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool AcceptGifts; + internal readonly bool AcceptGifts = DefaultAcceptGifts; [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool AutoSteamSaleEvent; + internal readonly bool AutoSteamSaleEvent = DefaultAutoSteamSaleEvent; [JsonProperty(Required = Required.DisallowNull)] - internal readonly EBotBehaviour BotBehaviour; + internal readonly EBotBehaviour BotBehaviour = DefaultBotBehaviour; [JsonProperty] - internal readonly string CustomGamePlayedWhileFarming; + internal readonly string CustomGamePlayedWhileFarming = DefaultCustomGamePlayedWhileFarming; [JsonProperty] - internal readonly string CustomGamePlayedWhileIdle; + internal readonly string CustomGamePlayedWhileIdle = DefaultCustomGamePlayedWhileIdle; [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool Enabled; - - [JsonProperty(Required = Required.DisallowNull)] - internal readonly HashSet FarmingOrders = new HashSet(); - - [JsonProperty(Required = Required.DisallowNull)] - internal readonly HashSet GamesPlayedWhileIdle = new HashSet(); - - [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte HoursUntilCardDrops = 3; - - [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool IdlePriorityQueueOnly; - - [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool IdleRefundableGames = true; + internal readonly bool Enabled = DefaultEnabled; [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace, Required = Required.DisallowNull)] - internal readonly HashSet LootableTypes = new HashSet { - Steam.Asset.EType.BoosterPack, - Steam.Asset.EType.FoilTradingCard, - Steam.Asset.EType.TradingCard - }; + internal readonly ImmutableHashSet FarmingOrders = DefaultFarmingOrders; [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace, Required = Required.DisallowNull)] - internal readonly HashSet MatchableTypes = new HashSet { Steam.Asset.EType.TradingCard }; + internal readonly ImmutableHashSet GamesPlayedWhileIdle = DefaultGamesPlayedWhileIdle; [JsonProperty(Required = Required.DisallowNull)] - internal readonly EPersonaState OnlineStatus = EPersonaState.Online; + internal readonly byte HoursUntilCardDrops = DefaultHoursUntilCardDrops; [JsonProperty(Required = Required.DisallowNull)] - internal readonly CryptoHelper.ECryptoMethod PasswordFormat; + internal readonly bool IdlePriorityQueueOnly = DefaultIdlePriorityQueueOnly; [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool Paused; + internal readonly bool IdleRefundableGames = DefaultIdleRefundableGames; + + [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace, Required = Required.DisallowNull)] + internal readonly ImmutableHashSet LootableTypes = DefaultLootableTypes; + + [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace, Required = Required.DisallowNull)] + internal readonly ImmutableHashSet MatchableTypes = DefaultMatchableTypes; [JsonProperty(Required = Required.DisallowNull)] - internal readonly ERedeemingPreferences RedeemingPreferences; + internal readonly EPersonaState OnlineStatus = DefaultOnlineStatus; [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool SendOnFarmingFinished; + internal readonly CryptoHelper.ECryptoMethod PasswordFormat = DefaultPasswordFormat; [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte SendTradePeriod; + internal readonly bool Paused = DefaultPaused; [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool ShutdownOnFarmingFinished; + internal readonly ERedeemingPreferences RedeemingPreferences = DefaultRedeemingPreferences; + + [JsonProperty(Required = Required.DisallowNull)] + internal readonly bool SendOnFarmingFinished = DefaultSendOnFarmingFinished; + + [JsonProperty(Required = Required.DisallowNull)] + internal readonly byte SendTradePeriod = DefaultSendTradePeriod; + + [JsonProperty(Required = Required.DisallowNull)] + internal readonly bool ShutdownOnFarmingFinished = DefaultShutdownOnFarmingFinished; [JsonProperty] - internal readonly string SteamTradeToken; + internal readonly string SteamTradeToken = DefaultSteamTradeToken; + + [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace, Required = Required.DisallowNull)] + internal readonly ImmutableDictionary SteamUserPermissions = DefaultSteamUserPermissions; [JsonProperty(Required = Required.DisallowNull)] - internal readonly Dictionary SteamUserPermissions = new Dictionary(); + internal readonly ETradingPreferences TradingPreferences = DefaultTradingPreferences; [JsonProperty(Required = Required.DisallowNull)] - internal readonly ETradingPreferences TradingPreferences; + internal readonly bool UseLoginKeys = DefaultUseLoginKeys; - [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool UseLoginKeys = true; + internal bool ShouldSerializeEverything { private get; set; } = true; [JsonProperty] - internal string SteamLogin { get; set; } + internal string SteamLogin { get; set; } = DefaultSteamLogin; [JsonProperty(Required = Required.DisallowNull)] - internal ulong SteamMasterClanID { get; private set; } + internal ulong SteamMasterClanID { get; private set; } = DefaultSteamMasterClanID; [JsonProperty] - internal string SteamParentalPIN { get; set; } = "0"; + internal string SteamParentalPIN { get; set; } = DefaultSteamParentalPIN; [JsonProperty] - internal string SteamPassword { get; set; } + internal string SteamPassword { get; set; } = DefaultSteamPassword; private bool ShouldSerializeSensitiveDetails = true; @@ -138,10 +167,6 @@ namespace ArchiSteamFarm { } } - public bool ShouldSerializeSteamLogin() => ShouldSerializeSensitiveDetails; - public bool ShouldSerializeSteamParentalPIN() => ShouldSerializeSensitiveDetails; - public bool ShouldSerializeSteamPassword() => ShouldSerializeSensitiveDetails; - internal static async Task Load(string filePath) { if (string.IsNullOrEmpty(filePath)) { ASF.ArchiLogger.LogNullError(nameof(filePath)); @@ -217,11 +242,9 @@ namespace ArchiSteamFarm { return null; } - foreach (EPermission permission in botConfig.SteamUserPermissions.Values) { - if (!Enum.IsDefined(typeof(EPermission), permission)) { - ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorConfigPropertyInvalid, nameof(botConfig.SteamUserPermissions), permission)); - return null; - } + foreach (EPermission permission in botConfig.SteamUserPermissions.Values.Where(permission => !Enum.IsDefined(typeof(EPermission), permission))) { + ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorConfigPropertyInvalid, nameof(botConfig.SteamUserPermissions), permission)); + return null; } if (botConfig.TradingPreferences > ETradingPreferences.All) { @@ -235,6 +258,7 @@ namespace ArchiSteamFarm { botConfig.SteamPassword = CryptoHelper.Decrypt(botConfig.PasswordFormat, botConfig.SteamPassword); } + botConfig.ShouldSerializeEverything = false; botConfig.ShouldSerializeSensitiveDetails = false; return botConfig; } @@ -329,5 +353,38 @@ namespace ArchiSteamFarm { DontAcceptBotTrades = 8, All = AcceptDonations | SteamTradeMatcher | MatchEverything | DontAcceptBotTrades } + + // ReSharper disable UnusedMember.Global + public bool ShouldSerializeAcceptGifts() => ShouldSerializeEverything || (AcceptGifts != DefaultAcceptGifts); + public bool ShouldSerializeAutoSteamSaleEvent() => ShouldSerializeEverything || (AutoSteamSaleEvent != DefaultAutoSteamSaleEvent); + public bool ShouldSerializeBotBehaviour() => ShouldSerializeEverything || (BotBehaviour != DefaultBotBehaviour); + public bool ShouldSerializeCustomGamePlayedWhileFarming() => ShouldSerializeEverything || (CustomGamePlayedWhileFarming != DefaultCustomGamePlayedWhileFarming); + public bool ShouldSerializeCustomGamePlayedWhileIdle() => ShouldSerializeEverything || (CustomGamePlayedWhileIdle != DefaultCustomGamePlayedWhileIdle); + public bool ShouldSerializeEnabled() => ShouldSerializeEverything || (Enabled != DefaultEnabled); + public bool ShouldSerializeFarmingOrders() => ShouldSerializeEverything || ((FarmingOrders != DefaultFarmingOrders) && !FarmingOrders.SetEquals(DefaultFarmingOrders)); + public bool ShouldSerializeGamesPlayedWhileIdle() => ShouldSerializeEverything || ((GamesPlayedWhileIdle != DefaultGamesPlayedWhileIdle) && !GamesPlayedWhileIdle.SetEquals(DefaultGamesPlayedWhileIdle)); + public bool ShouldSerializeHoursUntilCardDrops() => ShouldSerializeEverything || (HoursUntilCardDrops != DefaultHoursUntilCardDrops); + public bool ShouldSerializeIdlePriorityQueueOnly() => ShouldSerializeEverything || (IdlePriorityQueueOnly != DefaultIdlePriorityQueueOnly); + public bool ShouldSerializeIdleRefundableGames() => ShouldSerializeEverything || (IdleRefundableGames != DefaultIdleRefundableGames); + public bool ShouldSerializeLootableTypes() => ShouldSerializeEverything || ((LootableTypes != DefaultLootableTypes) && !LootableTypes.SetEquals(DefaultLootableTypes)); + public bool ShouldSerializeMatchableTypes() => ShouldSerializeEverything || ((MatchableTypes != DefaultMatchableTypes) && !MatchableTypes.SetEquals(DefaultMatchableTypes)); + public bool ShouldSerializeOnlineStatus() => ShouldSerializeEverything || (OnlineStatus != DefaultOnlineStatus); + public bool ShouldSerializePasswordFormat() => ShouldSerializeEverything || (PasswordFormat != DefaultPasswordFormat); + public bool ShouldSerializePaused() => ShouldSerializeEverything || (Paused != DefaultPaused); + public bool ShouldSerializeRedeemingPreferences() => ShouldSerializeEverything || (RedeemingPreferences != DefaultRedeemingPreferences); + public bool ShouldSerializeSendOnFarmingFinished() => ShouldSerializeEverything || (SendOnFarmingFinished != DefaultSendOnFarmingFinished); + public bool ShouldSerializeSendTradePeriod() => ShouldSerializeEverything || (SendTradePeriod != DefaultSendTradePeriod); + public bool ShouldSerializeShutdownOnFarmingFinished() => ShouldSerializeEverything || (ShutdownOnFarmingFinished != DefaultShutdownOnFarmingFinished); + public bool ShouldSerializeSSteamMasterClanID() => ShouldSerializeEverything; // We never serialize helper properties + public bool ShouldSerializeSteamLogin() => ShouldSerializeSensitiveDetails && (ShouldSerializeEverything || (SteamLogin != DefaultSteamLogin)); + public bool ShouldSerializeSteamMasterClanID() => ShouldSerializeEverything || (SteamMasterClanID != DefaultSteamMasterClanID); + public bool ShouldSerializeSteamParentalPIN() => ShouldSerializeSensitiveDetails && (ShouldSerializeEverything || (SteamParentalPIN != DefaultSteamParentalPIN)); + public bool ShouldSerializeSteamPassword() => ShouldSerializeSensitiveDetails && (ShouldSerializeEverything || (SteamPassword != DefaultSteamPassword)); + public bool ShouldSerializeSteamTradeToken() => ShouldSerializeEverything || (SteamTradeToken != DefaultSteamTradeToken); + public bool ShouldSerializeSteamUserPermissions() => ShouldSerializeEverything || ((SteamUserPermissions != DefaultSteamUserPermissions) && ((SteamUserPermissions.Count != DefaultSteamUserPermissions.Count) || SteamUserPermissions.Except(DefaultSteamUserPermissions).Any())); + public bool ShouldSerializeTradingPreferences() => ShouldSerializeEverything || (TradingPreferences != DefaultTradingPreferences); + public bool ShouldSerializeUseLoginKeys() => ShouldSerializeEverything || (UseLoginKeys != DefaultUseLoginKeys); + + // ReSharper restore UnusedMember.Global } -} \ No newline at end of file +} diff --git a/ArchiSteamFarm/GlobalConfig.cs b/ArchiSteamFarm/GlobalConfig.cs index f19765174..1819a388a 100644 --- a/ArchiSteamFarm/GlobalConfig.cs +++ b/ArchiSteamFarm/GlobalConfig.cs @@ -20,7 +20,7 @@ // limitations under the License. using System; -using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Net; @@ -33,91 +33,118 @@ using SteamKit2; namespace ArchiSteamFarm { [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] internal sealed class GlobalConfig { - internal const byte DefaultConnectionTimeout = 60; - internal const ushort DefaultIPCPort = 1242; - internal const byte DefaultLoginLimiterDelay = 10; + private const bool DefaultAutoRestart = true; + private const string DefaultCommandPrefix = "!"; + private const byte DefaultConfirmationsLimiterDelay = 10; + private const byte DefaultConnectionTimeout = 60; + private const string DefaultCurrentCulture = null; + private const bool DefaultDebug = false; + private const byte DefaultFarmingDelay = 15; + private const byte DefaultGiftsLimiterDelay = 1; + private const bool DefaultHeadless = false; + private const byte DefaultIdleFarmingPeriod = 8; + private const byte DefaultInventoryLimiterDelay = 3; + private const bool DefaultIPC = false; + private const string DefaultIPCPassword = null; + private const ushort DefaultIPCPort = 1242; + private const byte DefaultLoginLimiterDelay = 10; + private const byte DefaultMaxFarmingTime = 10; + private const byte DefaultMaxTradeHoldDuration = 15; + private const EOptimizationMode DefaultOptimizationMode = EOptimizationMode.MaxPerformance; + private const bool DefaultStatistics = true; + private const string DefaultSteamMessagePrefix = "/me "; + private const ulong DefaultSteamOwnerID = 0; + private const ProtocolTypes DefaultSteamProtocols = ProtocolTypes.All; + private const EUpdateChannel DefaultUpdateChannel = EUpdateChannel.Stable; + private const byte DefaultUpdatePeriod = 24; + private const ushort DefaultWebLimiterDelay = 200; + private const string DefaultWebProxyPassword = null; + private const string DefaultWebProxyText = null; + private const string DefaultWebProxyUsername = null; - internal static readonly HashSet SalesBlacklist = new HashSet { 267420, 303700, 335590, 368020, 425280, 480730, 566020, 639900, 762800, 876740 }; // Steam Summer/Winter sales + internal static readonly ImmutableHashSet SalesBlacklist = ImmutableHashSet.Create(267420, 303700, 335590, 368020, 425280, 480730, 566020, 639900, 762800, 876740); + private static readonly ImmutableHashSet DefaultIPCPrefixes = ImmutableHashSet.Create("http://127.0.0.1:" + DefaultIPCPort + "/"); + private static readonly ImmutableHashSet DefaultBlacklist = ImmutableHashSet.Create(); private static readonly SemaphoreSlim WriteSemaphore = new SemaphoreSlim(1, 1); [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool AutoRestart = true; + internal readonly bool AutoRestart = DefaultAutoRestart; - [JsonProperty(Required = Required.DisallowNull)] - internal readonly HashSet Blacklist = new HashSet(); + [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace, Required = Required.DisallowNull)] + internal readonly ImmutableHashSet Blacklist = DefaultBlacklist; [JsonProperty] - internal readonly string CommandPrefix = "!"; + internal readonly string CommandPrefix = DefaultCommandPrefix; [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte ConfirmationsLimiterDelay = 10; + internal readonly byte ConfirmationsLimiterDelay = DefaultConfirmationsLimiterDelay; [JsonProperty(Required = Required.DisallowNull)] internal readonly byte ConnectionTimeout = DefaultConnectionTimeout; [JsonProperty] - internal readonly string CurrentCulture; + internal readonly string CurrentCulture = DefaultCurrentCulture; [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool Debug; + internal readonly bool Debug = DefaultDebug; [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte FarmingDelay = 15; + internal readonly byte FarmingDelay = DefaultFarmingDelay; [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte GiftsLimiterDelay = 1; + internal readonly byte GiftsLimiterDelay = DefaultGiftsLimiterDelay; [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool Headless; + internal readonly bool Headless = DefaultHeadless; [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte IdleFarmingPeriod = 8; + internal readonly byte IdleFarmingPeriod = DefaultIdleFarmingPeriod; [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte InventoryLimiterDelay = 3; + internal readonly byte InventoryLimiterDelay = DefaultInventoryLimiterDelay; [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool IPC; + internal readonly bool IPC = DefaultIPC; [JsonProperty] - internal readonly string IPCPassword; + internal readonly string IPCPassword = DefaultIPCPassword; [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace, Required = Required.DisallowNull)] - internal readonly HashSet IPCPrefixes = new HashSet { "http://127.0.0.1:" + DefaultIPCPort + "/" }; + internal readonly ImmutableHashSet IPCPrefixes = DefaultIPCPrefixes; [JsonProperty(Required = Required.DisallowNull)] internal readonly byte LoginLimiterDelay = DefaultLoginLimiterDelay; [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte MaxFarmingTime = 10; + internal readonly byte MaxFarmingTime = DefaultMaxFarmingTime; [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte MaxTradeHoldDuration = 15; + internal readonly byte MaxTradeHoldDuration = DefaultMaxTradeHoldDuration; [JsonProperty(Required = Required.DisallowNull)] - internal readonly EOptimizationMode OptimizationMode = EOptimizationMode.MaxPerformance; + internal readonly EOptimizationMode OptimizationMode = DefaultOptimizationMode; [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool Statistics = true; + internal readonly bool Statistics = DefaultStatistics; [JsonProperty] - internal readonly string SteamMessagePrefix = "/me "; + internal readonly string SteamMessagePrefix = DefaultSteamMessagePrefix; [JsonProperty(Required = Required.DisallowNull)] - internal readonly EUpdateChannel UpdateChannel = EUpdateChannel.Stable; + internal readonly EUpdateChannel UpdateChannel = DefaultUpdateChannel; [JsonProperty(Required = Required.DisallowNull)] - internal readonly byte UpdatePeriod = 24; + internal readonly byte UpdatePeriod = DefaultUpdatePeriod; [JsonProperty(Required = Required.DisallowNull)] - internal readonly ushort WebLimiterDelay = 200; + internal readonly ushort WebLimiterDelay = DefaultWebLimiterDelay; [JsonProperty(PropertyName = nameof(WebProxy))] - internal readonly string WebProxyText; + internal readonly string WebProxyText = DefaultWebProxyText; [JsonProperty] - internal readonly string WebProxyUsername; + internal readonly string WebProxyUsername = DefaultWebProxyUsername; internal WebProxy WebProxy { get { @@ -161,14 +188,16 @@ namespace ArchiSteamFarm { } } - [JsonProperty(Required = Required.DisallowNull)] - internal ulong SteamOwnerID { get; private set; } + internal bool ShouldSerializeEverything { private get; set; } = true; [JsonProperty(Required = Required.DisallowNull)] - internal ProtocolTypes SteamProtocols { get; private set; } = ProtocolTypes.All; + internal ulong SteamOwnerID { get; private set; } = DefaultSteamOwnerID; + + [JsonProperty(Required = Required.DisallowNull)] + internal ProtocolTypes SteamProtocols { get; private set; } = DefaultSteamProtocols; [JsonProperty] - internal string WebProxyPassword { get; set; } + internal string WebProxyPassword { get; set; } = DefaultWebProxyPassword; private WebProxy _WebProxy; private bool ShouldSerializeSensitiveDetails = true; @@ -186,8 +215,6 @@ namespace ArchiSteamFarm { } } - public bool ShouldSerializeWebProxyPassword() => ShouldSerializeSensitiveDetails; - internal static async Task Load(string filePath) { if (string.IsNullOrEmpty(filePath)) { ASF.ArchiLogger.LogNullError(nameof(filePath)); @@ -247,6 +274,7 @@ namespace ArchiSteamFarm { return null; } + globalConfig.ShouldSerializeEverything = false; globalConfig.ShouldSerializeSensitiveDetails = false; return globalConfig; } @@ -292,5 +320,39 @@ namespace ArchiSteamFarm { [SuppressMessage("ReSharper", "UnusedMember.Global")] Experimental } + + // ReSharper disable UnusedMember.Global + public bool ShouldSerializeAutoRestart() => ShouldSerializeEverything || (AutoRestart != DefaultAutoRestart); + public bool ShouldSerializeBlacklist() => ShouldSerializeEverything || ((Blacklist != DefaultBlacklist) && !Blacklist.SetEquals(DefaultBlacklist)); + public bool ShouldSerializeCommandPrefix() => ShouldSerializeEverything || (CommandPrefix != DefaultCommandPrefix); + public bool ShouldSerializeConfirmationsLimiterDelay() => ShouldSerializeEverything || (ConfirmationsLimiterDelay != DefaultConfirmationsLimiterDelay); + public bool ShouldSerializeConnectionTimeout() => ShouldSerializeEverything || (ConnectionTimeout != DefaultConnectionTimeout); + public bool ShouldSerializeCurrentCulture() => ShouldSerializeEverything || (CurrentCulture != DefaultCurrentCulture); + public bool ShouldSerializeDebug() => ShouldSerializeEverything || (Debug != DefaultDebug); + public bool ShouldSerializeFarmingDelay() => ShouldSerializeEverything || (FarmingDelay != DefaultFarmingDelay); + public bool ShouldSerializeGiftsLimiterDelay() => ShouldSerializeEverything || (GiftsLimiterDelay != DefaultGiftsLimiterDelay); + public bool ShouldSerializeHeadless() => ShouldSerializeEverything || (Headless != DefaultHeadless); + public bool ShouldSerializeIdleFarmingPeriod() => ShouldSerializeEverything || (IdleFarmingPeriod != DefaultIdleFarmingPeriod); + public bool ShouldSerializeInventoryLimiterDelay() => ShouldSerializeEverything || (InventoryLimiterDelay != DefaultInventoryLimiterDelay); + public bool ShouldSerializeIPC() => ShouldSerializeEverything || (IPC != DefaultIPC); + public bool ShouldSerializeIPCPassword() => ShouldSerializeEverything || (IPCPassword != DefaultIPCPassword); + public bool ShouldSerializeIPCPrefixes() => ShouldSerializeEverything || ((IPCPrefixes != DefaultIPCPrefixes) && !IPCPrefixes.SetEquals(DefaultIPCPrefixes)); + public bool ShouldSerializeLoginLimiterDelay() => ShouldSerializeEverything || (LoginLimiterDelay != DefaultLoginLimiterDelay); + public bool ShouldSerializeMaxFarmingTime() => ShouldSerializeEverything || (MaxFarmingTime != DefaultMaxFarmingTime); + public bool ShouldSerializeMaxTradeHoldDuration() => ShouldSerializeEverything || (MaxTradeHoldDuration != DefaultMaxTradeHoldDuration); + public bool ShouldSerializeOptimizationMode() => ShouldSerializeEverything || (OptimizationMode != DefaultOptimizationMode); + public bool ShouldSerializeSSteamOwnerID() => ShouldSerializeEverything; // We never serialize helper properties + public bool ShouldSerializeStatistics() => ShouldSerializeEverything || (Statistics != DefaultStatistics); + public bool ShouldSerializeSteamMessagePrefix() => ShouldSerializeEverything || (SteamMessagePrefix != DefaultSteamMessagePrefix); + public bool ShouldSerializeSteamOwnerID() => ShouldSerializeEverything || (SteamOwnerID != DefaultSteamOwnerID); + public bool ShouldSerializeSteamProtocols() => ShouldSerializeEverything || (SteamProtocols != DefaultSteamProtocols); + public bool ShouldSerializeUpdateChannel() => ShouldSerializeEverything || (UpdateChannel != DefaultUpdateChannel); + public bool ShouldSerializeUpdatePeriod() => ShouldSerializeEverything || (UpdatePeriod != DefaultUpdatePeriod); + public bool ShouldSerializeWebLimiterDelay() => ShouldSerializeEverything || (WebLimiterDelay != DefaultWebLimiterDelay); + public bool ShouldSerializeWebProxyPassword() => ShouldSerializeSensitiveDetails && (ShouldSerializeEverything || (WebProxyPassword != DefaultWebProxyPassword)); + public bool ShouldSerializeWebProxyText() => ShouldSerializeEverything || (WebProxyText != DefaultWebProxyText); + public bool ShouldSerializeWebProxyUsername() => ShouldSerializeEverything || (WebProxyUsername != DefaultWebProxyUsername); + + // ReSharper restore UnusedMember.Global } -} \ No newline at end of file +} diff --git a/ArchiSteamFarm/IPC.cs b/ArchiSteamFarm/IPC.cs index 7180d4ebc..2d0899cd2 100644 --- a/ArchiSteamFarm/IPC.cs +++ b/ArchiSteamFarm/IPC.cs @@ -96,7 +96,7 @@ namespace ArchiSteamFarm { } } - internal static void Start(HashSet prefixes) { + internal static void Start(IReadOnlyCollection prefixes) { if ((prefixes == null) || (prefixes.Count == 0)) { ASF.ArchiLogger.LogNullError(nameof(prefixes)); return; @@ -275,6 +275,8 @@ namespace ArchiSteamFarm { } } + jsonRequest.GlobalConfig.ShouldSerializeEverything = false; + string filePath = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalConfigFileName); if (!await GlobalConfig.Write(filePath, jsonRequest.GlobalConfig).ConfigureAwait(false)) { @@ -408,6 +410,8 @@ namespace ArchiSteamFarm { } } + jsonRequest.BotConfig.ShouldSerializeEverything = false; + string filePath = Path.Combine(SharedInfo.ConfigDirectory, botName + SharedInfo.ConfigExtension); if (!await BotConfig.Write(filePath, jsonRequest.BotConfig).ConfigureAwait(false)) { diff --git a/ArchiSteamFarm/Program.cs b/ArchiSteamFarm/Program.cs index 7011d54b3..28c678438 100644 --- a/ArchiSteamFarm/Program.cs +++ b/ArchiSteamFarm/Program.cs @@ -36,12 +36,7 @@ using SteamKit2; namespace ArchiSteamFarm { internal static class Program { - internal static byte LoadBalancingDelay { - get { - byte result = GlobalConfig?.LoginLimiterDelay ?? GlobalConfig.DefaultLoginLimiterDelay; - return result >= GlobalConfig.DefaultLoginLimiterDelay ? result : GlobalConfig.DefaultLoginLimiterDelay; - } - } + internal static byte LoadBalancingDelay => Math.Max(GlobalConfig?.LoginLimiterDelay ?? 0, (byte) 10); internal static GlobalConfig GlobalConfig { get; private set; } internal static GlobalDatabase GlobalDatabase { get; private set; }