Use new C# features for serializable files

This commit is contained in:
Łukasz Domeradzki
2025-08-13 22:15:41 +02:00
parent 2b43cec8fe
commit ff2a2a728d
5 changed files with 100 additions and 117 deletions

View File

@@ -41,54 +41,51 @@ internal sealed class BotCache : SerializableFile {
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
internal ConcurrentList<AssetForListing> LastAnnouncedAssetsForListing { get; private init; } = []; internal ConcurrentList<AssetForListing> LastAnnouncedAssetsForListing { get; private init; } = [];
[JsonInclude]
[JsonPropertyName("BackingLastAnnouncedTradeToken")]
internal string? LastAnnouncedTradeToken { internal string? LastAnnouncedTradeToken {
get => BackingLastAnnouncedTradeToken; get;
set { set {
if (BackingLastAnnouncedTradeToken == value) { if (field == value) {
return; return;
} }
BackingLastAnnouncedTradeToken = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
[JsonInclude]
[JsonPropertyName("BackingLastInventoryChecksumBeforeDeduplication")]
internal string? LastInventoryChecksumBeforeDeduplication { internal string? LastInventoryChecksumBeforeDeduplication {
get => BackingLastInventoryChecksumBeforeDeduplication; get;
set { set {
if (BackingLastInventoryChecksumBeforeDeduplication == value) { if (field == value) {
return; return;
} }
BackingLastInventoryChecksumBeforeDeduplication = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
[JsonInclude]
[JsonPropertyName("BackingLastRequestAt")]
internal DateTime? LastRequestAt { internal DateTime? LastRequestAt {
get => BackingLastRequestAt; get;
set { set {
if (BackingLastRequestAt == value) { if (field == value) {
return; return;
} }
BackingLastRequestAt = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
[JsonInclude]
private string? BackingLastAnnouncedTradeToken { get; set; }
[JsonInclude]
private string? BackingLastInventoryChecksumBeforeDeduplication { get; set; }
[JsonInclude]
private DateTime? BackingLastRequestAt { get; set; }
private BotCache(string filePath) : this() { private BotCache(string filePath) : this() {
ArgumentException.ThrowIfNullOrEmpty(filePath); ArgumentException.ThrowIfNullOrEmpty(filePath);
@@ -98,18 +95,18 @@ internal sealed class BotCache : SerializableFile {
[JsonConstructor] [JsonConstructor]
private BotCache() => LastAnnouncedAssetsForListing.OnModified += OnObjectModified; private BotCache() => LastAnnouncedAssetsForListing.OnModified += OnObjectModified;
[UsedImplicitly]
public bool ShouldSerializeBackingLastAnnouncedTradeToken() => !string.IsNullOrEmpty(BackingLastAnnouncedTradeToken);
[UsedImplicitly]
public bool ShouldSerializeBackingLastInventoryChecksumBeforeDeduplication() => !string.IsNullOrEmpty(BackingLastInventoryChecksumBeforeDeduplication);
[UsedImplicitly]
public bool ShouldSerializeBackingLastRequestAt() => BackingLastRequestAt.HasValue;
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeLastAnnouncedAssetsForListing() => LastAnnouncedAssetsForListing.Count > 0; public bool ShouldSerializeLastAnnouncedAssetsForListing() => LastAnnouncedAssetsForListing.Count > 0;
[UsedImplicitly]
public bool ShouldSerializeLastAnnouncedTradeToken() => !string.IsNullOrEmpty(LastAnnouncedTradeToken);
[UsedImplicitly]
public bool ShouldSerializeLastInventoryChecksumBeforeDeduplication() => !string.IsNullOrEmpty(LastInventoryChecksumBeforeDeduplication);
[UsedImplicitly]
public bool ShouldSerializeLastRequestAt() => LastRequestAt.HasValue;
protected override void Dispose(bool disposing) { protected override void Dispose(bool disposing) {
if (disposing) { if (disposing) {
// Events we registered // Events we registered

View File

@@ -67,7 +67,7 @@ public abstract class SerializableFile : IDisposable {
ArgumentNullException.ThrowIfNull(serializableFile); ArgumentNullException.ThrowIfNull(serializableFile);
if (string.IsNullOrEmpty(serializableFile.FilePath)) { if (string.IsNullOrEmpty(serializableFile.FilePath)) {
throw new InvalidOperationException(nameof(serializableFile.FilePath)); return;
} }
if (serializableFile.ReadOnly) { if (serializableFile.ReadOnly) {

View File

@@ -50,30 +50,33 @@ public sealed class BotDatabase : GenericDatabase {
internal bool HasGamesToRedeemInBackground => GamesToRedeemInBackgroundCount > 0; internal bool HasGamesToRedeemInBackground => GamesToRedeemInBackgroundCount > 0;
[JsonIgnore] [JsonInclude]
[JsonPropertyName("BackingTradeRestrictionsAcknowledged")]
[PublicAPI] [PublicAPI]
public bool TradeRestrictionsAcknowledged { public bool TradeRestrictionsAcknowledged {
get => BackingTradeRestrictionsAcknowledged; get;
internal set { internal set {
if (BackingTradeRestrictionsAcknowledged == value) { if (field == value) {
return; return;
} }
BackingTradeRestrictionsAcknowledged = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
[JsonInclude]
[JsonPropertyName("BackingAccessToken")]
internal string? AccessToken { internal string? AccessToken {
get => BackingAccessToken; get;
set { set {
if (BackingAccessToken == value) { if (field == value) {
return; return;
} }
BackingAccessToken = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
@@ -83,15 +86,17 @@ public sealed class BotDatabase : GenericDatabase {
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
internal ConcurrentHashSet<uint> ExtraStorePackages { get; private init; } = []; internal ConcurrentHashSet<uint> ExtraStorePackages { get; private init; } = [];
[JsonInclude]
[JsonPropertyName("BackingExtraStorePackagesRefreshedAt")]
internal DateTime ExtraStorePackagesRefreshedAt { internal DateTime ExtraStorePackagesRefreshedAt {
get => BackingExtraStorePackagesRefreshedAt; get => field;
set { set {
if (BackingExtraStorePackagesRefreshedAt == value) { if (field == value) {
return; return;
} }
BackingExtraStorePackagesRefreshedAt = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
@@ -121,41 +126,47 @@ public sealed class BotDatabase : GenericDatabase {
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
internal ConcurrentHashSet<uint> MatchActivelyBlacklistAppIDs { get; private init; } = []; internal ConcurrentHashSet<uint> MatchActivelyBlacklistAppIDs { get; private init; } = [];
[JsonInclude]
[JsonPropertyName($"_{nameof(MobileAuthenticator)}")]
internal MobileAuthenticator? MobileAuthenticator { internal MobileAuthenticator? MobileAuthenticator {
get => BackingMobileAuthenticator; get;
set { set {
if (BackingMobileAuthenticator == value) { if (field == value) {
return; return;
} }
BackingMobileAuthenticator = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
[JsonInclude]
[JsonPropertyName("BackingRefreshToken")]
internal string? RefreshToken { internal string? RefreshToken {
get => BackingRefreshToken; get;
set { set {
if (BackingRefreshToken == value) { if (field == value) {
return; return;
} }
BackingRefreshToken = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
[JsonInclude]
[JsonPropertyName("BackingSteamGuardData")]
internal string? SteamGuardData { internal string? SteamGuardData {
get => BackingSteamGuardData; get;
set { set {
if (BackingSteamGuardData == value) { if (field == value) {
return; return;
} }
BackingSteamGuardData = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
@@ -165,25 +176,6 @@ public sealed class BotDatabase : GenericDatabase {
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
internal ConcurrentHashSet<ulong> TradingBlacklistSteamIDs { get; private init; } = []; internal ConcurrentHashSet<ulong> TradingBlacklistSteamIDs { get; private init; } = [];
[JsonInclude]
private string? BackingAccessToken { get; set; }
[JsonInclude]
private DateTime BackingExtraStorePackagesRefreshedAt { get; set; }
[JsonInclude]
[JsonPropertyName($"_{nameof(MobileAuthenticator)}")]
private MobileAuthenticator? BackingMobileAuthenticator { get; set; }
[JsonInclude]
private string? BackingRefreshToken { get; set; }
[JsonInclude]
private string? BackingSteamGuardData { get; set; }
[JsonInclude]
private bool BackingTradeRestrictionsAcknowledged { get; set; }
[JsonDisallowNull] [JsonDisallowNull]
[JsonInclude] [JsonInclude]
private OrderedDictionary GamesToRedeemInBackground { get; init; } = new(); private OrderedDictionary GamesToRedeemInBackground { get; init; } = new();
@@ -232,26 +224,14 @@ public sealed class BotDatabase : GenericDatabase {
} }
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeBackingAccessToken() => !string.IsNullOrEmpty(BackingAccessToken); public bool ShouldSerializeAccessToken() => !string.IsNullOrEmpty(AccessToken);
[UsedImplicitly]
public bool ShouldSerializeBackingExtraStorePackagesRefreshedAt() => BackingExtraStorePackagesRefreshedAt > DateTime.MinValue;
[UsedImplicitly]
public bool ShouldSerializeBackingMobileAuthenticator() => BackingMobileAuthenticator != null;
[UsedImplicitly]
public bool ShouldSerializeBackingRefreshToken() => !string.IsNullOrEmpty(BackingRefreshToken);
[UsedImplicitly]
public bool ShouldSerializeBackingSteamGuardData() => !string.IsNullOrEmpty(BackingSteamGuardData);
[UsedImplicitly]
public bool ShouldSerializeBackingTradeRestrictionsAcknowledged() => BackingTradeRestrictionsAcknowledged;
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeExtraStorePackages() => ExtraStorePackages.Count > 0; public bool ShouldSerializeExtraStorePackages() => ExtraStorePackages.Count > 0;
[UsedImplicitly]
public bool ShouldSerializeExtraStorePackagesRefreshedAt() => ExtraStorePackagesRefreshedAt > DateTime.MinValue;
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeFarmingBlacklistAppIDs() => FarmingBlacklistAppIDs.Count > 0; public bool ShouldSerializeFarmingBlacklistAppIDs() => FarmingBlacklistAppIDs.Count > 0;
@@ -270,6 +250,18 @@ public sealed class BotDatabase : GenericDatabase {
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeMatchActivelyBlacklistAppIDs() => MatchActivelyBlacklistAppIDs.Count > 0; public bool ShouldSerializeMatchActivelyBlacklistAppIDs() => MatchActivelyBlacklistAppIDs.Count > 0;
[UsedImplicitly]
public bool ShouldSerializeMobileAuthenticator() => MobileAuthenticator != null;
[UsedImplicitly]
public bool ShouldSerializeRefreshToken() => !string.IsNullOrEmpty(RefreshToken);
[UsedImplicitly]
public bool ShouldSerializeSteamGuardData() => !string.IsNullOrEmpty(SteamGuardData);
[UsedImplicitly]
public bool ShouldSerializeTradeRestrictionsAcknowledged() => TradeRestrictionsAcknowledged;
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeTradingBlacklistSteamIDs() => TradingBlacklistSteamIDs.Count > 0; public bool ShouldSerializeTradingBlacklistSteamIDs() => TradingBlacklistSteamIDs.Count > 0;
@@ -285,7 +277,7 @@ public sealed class BotDatabase : GenericDatabase {
TradingBlacklistSteamIDs.OnModified -= OnObjectModified; TradingBlacklistSteamIDs.OnModified -= OnObjectModified;
// Those are objects that might be null and the check should be in-place // Those are objects that might be null and the check should be in-place
BackingMobileAuthenticator?.Dispose(); MobileAuthenticator?.Dispose();
} }
// Base dispose // Base dispose

View File

@@ -34,38 +34,36 @@ using JetBrains.Annotations;
namespace ArchiSteamFarm.Storage; namespace ArchiSteamFarm.Storage;
internal sealed class CrashFile : SerializableFile { internal sealed class CrashFile : SerializableFile {
[JsonInclude]
[JsonPropertyName("BackingLastStartup")]
internal DateTime LastStartup { internal DateTime LastStartup {
get => BackingLastStartup; get;
set { set {
if (BackingLastStartup == value) { if (field == value) {
return; return;
} }
BackingLastStartup = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
[JsonInclude]
[JsonPropertyName("BackingStartupCount")]
internal byte StartupCount { internal byte StartupCount {
get => BackingStartupCount; get;
set { set {
if (BackingStartupCount == value) { if (field == value) {
return; return;
} }
BackingStartupCount = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
[JsonInclude]
private DateTime BackingLastStartup { get; set; }
[JsonInclude]
private byte BackingStartupCount { get; set; }
private CrashFile(string filePath) : this() { private CrashFile(string filePath) : this() {
ArgumentException.ThrowIfNullOrEmpty(filePath); ArgumentException.ThrowIfNullOrEmpty(filePath);
@@ -76,10 +74,10 @@ internal sealed class CrashFile : SerializableFile {
private CrashFile() { } private CrashFile() { }
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeBackingLastStartup() => BackingLastStartup > DateTime.MinValue; public bool ShouldSerializeLastStartup() => LastStartup > DateTime.MinValue;
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeBackingStartupCount() => BackingStartupCount > 0; public bool ShouldSerializeStartupCount() => StartupCount > 0;
protected override Task Save() => Save(this); protected override Task Save() => Save(this);

View File

@@ -65,28 +65,32 @@ public sealed class GlobalDatabase : GenericDatabase {
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
internal ObservableConcurrentDictionary<uint, byte> CardCountsPerGame { get; private init; } = new(); internal ObservableConcurrentDictionary<uint, byte> CardCountsPerGame { get; private init; } = new();
[JsonInclude]
[JsonPropertyName($"_{nameof(CellID)}")]
internal uint CellID { internal uint CellID {
get => BackingCellID; get;
set { set {
if (BackingCellID == value) { if (field == value) {
return; return;
} }
BackingCellID = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
[JsonInclude]
[JsonPropertyName($"_{nameof(LastChangeNumber)}")]
internal uint LastChangeNumber { internal uint LastChangeNumber {
get => BackingLastChangeNumber; get;
set { set {
if (BackingLastChangeNumber == value) { if (field == value) {
return; return;
} }
BackingLastChangeNumber = value; field = value;
Utilities.InBackground(Save); Utilities.InBackground(Save);
} }
} }
@@ -96,14 +100,6 @@ public sealed class GlobalDatabase : GenericDatabase {
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
internal InMemoryServerListProvider ServerListProvider { get; private init; } = new(); internal InMemoryServerListProvider ServerListProvider { get; private init; } = new();
[JsonInclude]
[JsonPropertyName($"_{nameof(CellID)}")]
private uint BackingCellID { get; set; }
[JsonInclude]
[JsonPropertyName($"_{nameof(LastChangeNumber)}")]
private uint BackingLastChangeNumber { get; set; }
[JsonDisallowNull] [JsonDisallowNull]
[JsonInclude] [JsonInclude]
private ConcurrentDictionary<uint, ulong> PackagesAccessTokens { get; init; } = new(); private ConcurrentDictionary<uint, ulong> PackagesAccessTokens { get; init; } = new();
@@ -151,18 +147,18 @@ public sealed class GlobalDatabase : GenericDatabase {
SaveToJsonStorage(this, key, value); SaveToJsonStorage(this, key, value);
} }
[UsedImplicitly]
public bool ShouldSerializeBackingCellID() => BackingCellID != 0;
[UsedImplicitly]
public bool ShouldSerializeBackingLastChangeNumber() => BackingLastChangeNumber != 0;
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeCachedBadBots() => CachedBadBots.Count > 0; public bool ShouldSerializeCachedBadBots() => CachedBadBots.Count > 0;
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializeCardCountsPerGame() => !CardCountsPerGame.IsEmpty; public bool ShouldSerializeCardCountsPerGame() => !CardCountsPerGame.IsEmpty;
[UsedImplicitly]
public bool ShouldSerializeCellID() => CellID != 0;
[UsedImplicitly]
public bool ShouldSerializeLastChangeNumber() => LastChangeNumber != 0;
[UsedImplicitly] [UsedImplicitly]
public bool ShouldSerializePackagesAccessTokens() => !PackagesAccessTokens.IsEmpty; public bool ShouldSerializePackagesAccessTokens() => !PackagesAccessTokens.IsEmpty;