diff --git a/ArchiSteamFarm/Core/ArchiNet.cs b/ArchiSteamFarm/Core/ArchiNet.cs index e8da5a91c..0a4f49b2c 100644 --- a/ArchiSteamFarm/Core/ArchiNet.cs +++ b/ArchiSteamFarm/Core/ArchiNet.cs @@ -20,7 +20,9 @@ // limitations under the License. using System; +using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; using System.Threading.Tasks; using ArchiSteamFarm.Helpers; using ArchiSteamFarm.IPC.Responses; @@ -32,7 +34,7 @@ namespace ArchiSteamFarm.Core; internal static class ArchiNet { internal static Uri URL => new("https://asf.JustArchi.net"); - private static readonly ArchiCacheable> CachedBadBots = new(ResolveCachedBadBots, TimeSpan.FromDays(1)); + private static readonly ArchiCacheable> CachedBadBots = new(ResolveCachedBadBots, TimeSpan.FromDays(1)); internal static async Task FetchBuildChecksum(Version version, string variant) { ArgumentNullException.ThrowIfNull(version); @@ -61,12 +63,16 @@ internal static class ArchiNet { throw new ArgumentOutOfRangeException(nameof(steamID)); } - (_, ImmutableHashSet? badBots) = await CachedBadBots.GetValue(ArchiCacheable>.EFallback.SuccessPreviously).ConfigureAwait(false); + (_, IReadOnlyCollection? badBots) = await CachedBadBots.GetValue(ArchiCacheable>.EFallback.FailedNow).ConfigureAwait(false); return badBots?.Contains(steamID); } - private static async Task<(bool Success, ImmutableHashSet? Result)> ResolveCachedBadBots() { + private static async Task<(bool Success, IReadOnlyCollection? Result)> ResolveCachedBadBots() { + if (ASF.GlobalDatabase == null) { + throw new InvalidOperationException(nameof(ASF.WebBrowser)); + } + if (ASF.WebBrowser == null) { throw new InvalidOperationException(nameof(ASF.WebBrowser)); } @@ -75,6 +81,12 @@ internal static class ArchiNet { ObjectResponse>>? response = await ASF.WebBrowser.UrlGetToJsonObject>>(request).ConfigureAwait(false); - return response?.Content != null ? (true, response.Content.Result) : (false, null); + if (response?.Content?.Result == null) { + return (false, ASF.GlobalDatabase.CachedBadBots); + } + + ASF.GlobalDatabase.CachedBadBots.ReplaceIfNeededWith(response.Content.Result); + + return (true, response.Content.Result); } } diff --git a/ArchiSteamFarm/Storage/GlobalDatabase.cs b/ArchiSteamFarm/Storage/GlobalDatabase.cs index e378950e6..96636f755 100644 --- a/ArchiSteamFarm/Storage/GlobalDatabase.cs +++ b/ArchiSteamFarm/Storage/GlobalDatabase.cs @@ -48,6 +48,9 @@ public sealed class GlobalDatabase : SerializableFile { [PublicAPI] public IReadOnlyDictionary PackagesDataReadOnly => PackagesData; + [JsonProperty(Required = Required.DisallowNull)] + internal readonly ConcurrentHashSet CachedBadBots = new(); + [JsonProperty(Required = Required.DisallowNull)] internal readonly ObservableConcurrentDictionary CardCountsPerGame = new(); @@ -111,6 +114,7 @@ public sealed class GlobalDatabase : SerializableFile { [JsonConstructor] private GlobalDatabase() { + CachedBadBots.OnModified += OnObjectModified; CardCountsPerGame.OnModified += OnObjectModified; ServerListProvider.ServerListUpdated += OnObjectModified; } @@ -165,6 +169,9 @@ public sealed class GlobalDatabase : SerializableFile { [UsedImplicitly] public bool ShouldSerializeBackingLastChangeNumber() => LastChangeNumber != 0; + [UsedImplicitly] + public bool ShouldSerializeCachedBadBots() => CachedBadBots.Count > 0; + [UsedImplicitly] public bool ShouldSerializeCardCountsPerGame() => !CardCountsPerGame.IsEmpty; @@ -183,6 +190,7 @@ public sealed class GlobalDatabase : SerializableFile { protected override void Dispose(bool disposing) { if (disposing) { // Events we registered + CachedBadBots.OnModified -= OnObjectModified; CardCountsPerGame.OnModified -= OnObjectModified; ServerListProvider.ServerListUpdated -= OnObjectModified;