Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closes #3061 #3145

Merged
merged 48 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
89019e6
Good start
JustArchi Nov 22, 2023
e072123
Misc
JustArchi Nov 22, 2023
45a21d9
Make ApiAuthenticationMiddleware use new json
JustArchi Nov 22, 2023
fa76a60
Remove first newtonsoft dependency
JustArchi Nov 22, 2023
08ce23b
Merge branch 'main' into feature/3061
JustArchi Feb 11, 2024
ce73091
Pull latest ASFB json enhancements
JustArchi Feb 11, 2024
a5927b2
Start reimplementing newtonsoft!
JustArchi Feb 11, 2024
fc4e6d0
One thing at a time
JustArchi Feb 11, 2024
95a385b
Keep doing all kind of breaking changes which need to be tested later
JustArchi Feb 11, 2024
46ac564
Add back ShouldSerialize() support
JustArchi Feb 11, 2024
f413772
Misc
JustArchi Feb 11, 2024
b86d66b
Eradicate remaining parts of newtonsoft
JustArchi Feb 11, 2024
3533c74
WIP
JustArchi Feb 12, 2024
5af2c24
Workaround STJ stupidity in regards to derived types
JustArchi Feb 12, 2024
7115b35
Make CI happy
JustArchi Feb 12, 2024
743528e
Bunch of further fixes
JustArchi Feb 12, 2024
0d6d670
Merge branch 'main' into feature/3061
JustArchi Feb 12, 2024
d30a4c9
Fix AddFreeLicense() after rewrite
JustArchi Feb 12, 2024
96218ac
Merge branch 'main' into feature/3061
JustArchi Feb 12, 2024
6f31630
Add full support for JsonDisallowNullAttribute
JustArchi Feb 12, 2024
4ab7ec1
Optimize our json utilities even further
JustArchi Feb 12, 2024
8ee8862
Misc
JustArchi Feb 12, 2024
b9392e8
Add support for fields in disallow null
JustArchi Feb 12, 2024
ef2af89
Misc optimization
JustArchi Feb 13, 2024
998e7c1
Merge branch 'main' into feature/3061
JustArchi Feb 14, 2024
b13e5f8
Fix deserialization of GlobalCache in STD
JustArchi Feb 14, 2024
db4dfff
Fix non-public [JsonExtensionData]
JustArchi Feb 14, 2024
490e4d2
Fix IM missing method exception, correct db storage helpers
JustArchi Feb 14, 2024
7820caf
Fix saving into generic databases
JustArchi Feb 14, 2024
d1446c8
Make Save() function abstract to force inheritors to implement it pro…
JustArchi Feb 14, 2024
b44c56b
Correct ShouldSerializeAdditionalProperties to be a method
JustArchi Feb 15, 2024
e4fa51b
Misc cleanup
JustArchi Feb 15, 2024
445ac5c
Merge branch 'main' into feature/3061
JustArchi Feb 15, 2024
a2c165c
Code review
JustArchi Feb 15, 2024
5becf3f
Allow JSON comments in configs, among other
JustArchi Feb 15, 2024
6206063
Allow trailing commas in configs
JustArchi Feb 15, 2024
66bf1b1
Fix confirmation ID
JustArchi Feb 16, 2024
3f2a231
Correct confirmations deserialization
JustArchi Feb 17, 2024
c5a3452
Use JsonNumberHandling
JustArchi Feb 17, 2024
27d94a9
Misc
JustArchi Feb 17, 2024
f6939c1
Misc
JustArchi Feb 17, 2024
9717b3b
[JsonDisallowNull] corrections
JustArchi Feb 17, 2024
e6a9ba9
Merge branch 'main' into feature/3061
JustArchi Feb 17, 2024
d08f3f8
Forbid [JsonDisallowNull] on non-nullable structs
JustArchi Feb 17, 2024
c0075e6
Not really but okay
JustArchi Feb 17, 2024
dfdcca6
Add and use ToJson() helpers
JustArchi Feb 18, 2024
40fb953
Misc
JustArchi Feb 18, 2024
cbf1758
Misc
JustArchi Feb 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<ItemGroup>
<PackageReference Include="ConfigureAwaitChecker.Analyzer" PrivateAssets="all" />
<PackageReference Include="JetBrains.Annotations" PrivateAssets="all" />
<PackageReference Include="Newtonsoft.Json" IncludeAssets="compile" />
<PackageReference Include="SteamKit2" IncludeAssets="compile" />
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
</ItemGroup>
Expand Down
25 changes: 15 additions & 10 deletions ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using ArchiSteamFarm.Core;
using ArchiSteamFarm.Plugins.Interfaces;
using ArchiSteamFarm.Steam;
using ArchiSteamFarm.Steam.Data;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SteamKit2;

namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin;
Expand All @@ -45,31 +46,35 @@ namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin;
internal sealed class ExamplePlugin : IASF, IBot, IBotCommand2, IBotConnection, IBotFriendRequest, IBotMessage, IBotModules, IBotTradeOffer {
// This is used for identification purposes, typically you want to use a friendly name of your plugin here, such as the name of your main class
// Please note that this property can have direct dependencies only on structures that were initialized by the constructor, as it's possible to be called before OnLoaded() takes place
[JsonInclude]
[Required]
public string Name => nameof(ExamplePlugin);

// This will be displayed to the user and written in the log file, typically you should point it to the version of your library, but alternatively you can do some more advanced logic if you'd like to
// Please note that this property can have direct dependencies only on structures that were initialized by the constructor, as it's possible to be called before OnLoaded() takes place
[JsonInclude]
[Required]
public Version Version => typeof(ExamplePlugin).Assembly.GetName().Version ?? throw new InvalidOperationException(nameof(Version));

// Plugins can expose custom properties for our GET /Api/Plugins API call, simply annotate them with [JsonProperty] (or keep public)
[JsonProperty]
public bool CustomIsEnabledField { get; private set; } = true;
[JsonInclude]
[Required]
public bool CustomIsEnabledField { get; private init; } = true;

// This method, apart from being called before any bot initialization takes place, allows you to read custom global config properties that are not recognized by ASF
// Thanks to that, you can extend default ASF config with your own stuff, then parse it here in order to customize your plugin during runtime
// Keep in mind that, as noted in the interface, additionalConfigProperties can be null if no custom, unrecognized properties are found by ASF, you should handle that case appropriately
// In addition to that, this method also guarantees that all plugins were already OnLoaded(), which allows cross-plugins-communication to be possible
public Task OnASFInit(IReadOnlyDictionary<string, JToken>? additionalConfigProperties = null) {
public Task OnASFInit(IReadOnlyDictionary<string, JsonElement>? additionalConfigProperties = null) {
if (additionalConfigProperties == null) {
return Task.CompletedTask;
}

foreach ((string configProperty, JToken configValue) in additionalConfigProperties) {
foreach ((string configProperty, JsonElement configValue) in additionalConfigProperties) {
// It's a good idea to prefix your custom properties with the name of your plugin, so there will be no possible conflict of ASF or other plugins using the same name, neither now or in the future
switch (configProperty) {
case $"{nameof(ExamplePlugin)}TestProperty" when configValue.Type == JTokenType.Boolean:
bool exampleBooleanValue = configValue.Value<bool>();
ASF.ArchiLogger.LogGenericInfo($"{nameof(ExamplePlugin)}TestProperty boolean property has been found with a value of: {exampleBooleanValue}");
case $"{nameof(ExamplePlugin)}TestProperty" when configValue.ValueKind == JsonValueKind.True:
ASF.ArchiLogger.LogGenericInfo($"{nameof(ExamplePlugin)}TestProperty boolean property has been found with a value of true");

break;
}
Expand Down Expand Up @@ -135,7 +140,7 @@ public Task OnBotInit(Bot bot) {
// Keep in mind that, as noted in the interface, additionalConfigProperties can be null if no custom, unrecognized properties are found by ASF, you should handle that case appropriately
// Also keep in mind that this function can be called multiple times, e.g. when user edits their bot configs during runtime
// Take a look at OnASFInit() for example parsing code
public async Task OnBotInitModules(Bot bot, IReadOnlyDictionary<string, JToken>? additionalConfigProperties = null) {
public async Task OnBotInitModules(Bot bot, IReadOnlyDictionary<string, JsonElement>? additionalConfigProperties = null) {
// For example, we'll ensure that every bot starts paused regardless of Paused property, in order to do this, we'll just call Pause here in InitModules()
// Thanks to the fact that this method is called with each bot config reload, we'll ensure that our bot stays paused even if it'd get unpaused otherwise
bot.ArchiLogger.LogGenericInfo("Pausing this bot as asked from the plugin");
Expand Down
8 changes: 5 additions & 3 deletions ArchiSteamFarm.CustomPlugins.ExamplePlugin/MeowResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@

using System;
using System.Diagnostics.CodeAnalysis;
using Newtonsoft.Json;
using System.Text.Json.Serialization;

namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin;

#pragma warning disable CA1812 // False positive, the class is used during json deserialization
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
internal sealed class MeowResponse {
[JsonProperty("url", Required = Required.Always)]
internal readonly Uri URL = null!;
[JsonInclude]
[JsonPropertyName("url")]
[JsonRequired]
internal Uri URL { get; private init; } = null!;

[JsonConstructor]
private MeowResponse() { }
Expand Down
6 changes: 6 additions & 0 deletions ArchiSteamFarm.CustomPlugins.PeriodicGC/PeriodicGCPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
// limitations under the License.

using System;
using System.ComponentModel.DataAnnotations;
using System.Composition;
using System.Runtime;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using ArchiSteamFarm.Core;
Expand All @@ -38,8 +40,12 @@ internal sealed class PeriodicGCPlugin : IPlugin {
private static readonly object LockObject = new();
private static readonly Timer PeriodicGCTimer = new(PerformGC);

[JsonInclude]
[Required]
public string Name => nameof(PeriodicGCPlugin);

[JsonInclude]
[Required]
public Version Version => typeof(PeriodicGCPlugin).Assembly.GetName().Version ?? throw new InvalidOperationException(nameof(Version));

public Task OnLoaded() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
<PackageReference Include="AngleSharp.XPath" IncludeAssets="compile" />
<PackageReference Include="ConfigureAwaitChecker.Analyzer" PrivateAssets="all" />
<PackageReference Include="JetBrains.Annotations" PrivateAssets="all" />
<PackageReference Include="Newtonsoft.Json" IncludeAssets="compile" />
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
// limitations under the License.

using System;
using Newtonsoft.Json;
using System.Text.Json.Serialization;

namespace ArchiSteamFarm.CustomPlugins.SignInWithSteam.Data;

public sealed class SignInWithSteamRequest {
[JsonProperty(Required = Required.Always)]
public Uri RedirectURL { get; private set; } = null!;
[JsonInclude]
[JsonRequired]
public Uri RedirectURL { get; private init; } = null!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
// limitations under the License.

using System;
using Newtonsoft.Json;
using System.Text.Json.Serialization;

namespace ArchiSteamFarm.CustomPlugins.SignInWithSteam.Data;

public sealed class SignInWithSteamResponse {
[JsonProperty(Required = Required.Always)]
public Uri ReturnURL { get; private set; }
[JsonInclude]
[JsonRequired]
public Uri ReturnURL { get; private init; }

internal SignInWithSteamResponse(Uri returnURL) {
ArgumentNullException.ThrowIfNull(returnURL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
// limitations under the License.

using System;
using System.ComponentModel.DataAnnotations;
using System.Composition;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using ArchiSteamFarm.Core;
using ArchiSteamFarm.Plugins.Interfaces;
Expand All @@ -31,8 +33,12 @@ namespace ArchiSteamFarm.CustomPlugins.SignInWithSteam;
[Export(typeof(IPlugin))]
[UsedImplicitly]
internal sealed class SignInWithSteamPlugin : IPlugin {
[JsonInclude]
[Required]
public string Name => nameof(SignInWithSteamPlugin);

[JsonInclude]
[Required]
public Version Version => typeof(SignInWithSteamPlugin).Assembly.GetName().Version ?? throw new InvalidOperationException(nameof(Version));

public Task OnLoaded() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<ItemGroup>
<PackageReference Include="ConfigureAwaitChecker.Analyzer" PrivateAssets="all" />
<PackageReference Include="JetBrains.Annotations" PrivateAssets="all" />
<PackageReference Include="Newtonsoft.Json" IncludeAssets="compile" />
<PackageReference Include="SteamKit2" IncludeAssets="compile" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" IncludeAssets="compile" />
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
Expand Down
25 changes: 15 additions & 10 deletions ArchiSteamFarm.OfficialPlugins.ItemsMatcher/BotCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,23 @@
using System;
using System.Globalization;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using ArchiSteamFarm.Collections;
using ArchiSteamFarm.Core;
using ArchiSteamFarm.Helpers;
using ArchiSteamFarm.Helpers.Json;
using ArchiSteamFarm.Localization;
using ArchiSteamFarm.OfficialPlugins.ItemsMatcher.Data;
using JetBrains.Annotations;
using Newtonsoft.Json;

namespace ArchiSteamFarm.OfficialPlugins.ItemsMatcher;

internal sealed class BotCache : SerializableFile {
[JsonProperty(Required = Required.DisallowNull)]
internal readonly ConcurrentList<AssetForListing> LastAnnouncedAssetsForListing = [];
[JsonDisallowNull]
[JsonInclude]
internal ConcurrentList<AssetForListing> LastAnnouncedAssetsForListing { get; private init; } = [];

internal string? LastAnnouncedTradeToken {
get => BackingLastAnnouncedTradeToken;
Expand Down Expand Up @@ -76,14 +79,14 @@ internal DateTime? LastRequestAt {
}
}

[JsonProperty]
private string? BackingLastAnnouncedTradeToken;
[JsonInclude]
private string? BackingLastAnnouncedTradeToken { get; set; }

[JsonProperty]
private string? BackingLastInventoryChecksumBeforeDeduplication;
[JsonInclude]
private string? BackingLastInventoryChecksumBeforeDeduplication { get; set; }

[JsonProperty]
private DateTime? BackingLastRequestAt;
[JsonInclude]
private DateTime? BackingLastRequestAt { get; set; }

private BotCache(string filePath) : this() {
ArgumentException.ThrowIfNullOrEmpty(filePath);
Expand Down Expand Up @@ -116,6 +119,8 @@ protected override void Dispose(bool disposing) {
base.Dispose(disposing);
}

protected override Task Save() => Save(this);

internal static async Task<BotCache> CreateOrLoad(string filePath) {
ArgumentException.ThrowIfNullOrEmpty(filePath);

Expand All @@ -134,7 +139,7 @@ internal static async Task<BotCache> CreateOrLoad(string filePath) {
return new BotCache(filePath);
}

botCache = JsonConvert.DeserializeObject<BotCache>(json);
botCache = JsonSerializer.Deserialize<BotCache>(json, JsonUtilities.DefaultJsonSerialierOptions);
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,21 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text.Json.Serialization;
using ArchiSteamFarm.Steam.Data;
using ArchiSteamFarm.Steam.Storage;
using Newtonsoft.Json;
using SteamKit2;

namespace ArchiSteamFarm.OfficialPlugins.ItemsMatcher.Data;

internal sealed class AnnouncementDiffRequest : AnnouncementRequest {
[JsonProperty(Required = Required.Always)]
private readonly ImmutableHashSet<AssetForListing> InventoryRemoved;
[JsonInclude]
[JsonRequired]
private ImmutableHashSet<AssetForListing> InventoryRemoved { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly string PreviousInventoryChecksum;
[JsonInclude]
[JsonRequired]
private string PreviousInventoryChecksum { get; init; }

internal AnnouncementDiffRequest(Guid guid, ulong steamID, IReadOnlyCollection<AssetForListing> inventory, string inventoryChecksum, IReadOnlyCollection<Asset.EType> matchableTypes, uint totalInventoryCount, bool matchEverything, byte maxTradeHoldDuration, string tradeToken, IReadOnlyCollection<AssetForListing> inventoryRemoved, string previousInventoryChecksum, string? nickname = null, string? avatarHash = null) : base(guid, steamID, inventory, inventoryChecksum, matchableTypes, totalInventoryCount, matchEverything, maxTradeHoldDuration, tradeToken, nickname, avatarHash) {
ArgumentOutOfRangeException.ThrowIfEqual(guid, Guid.Empty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,47 +22,56 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text.Json.Serialization;
using ArchiSteamFarm.Steam.Data;
using ArchiSteamFarm.Steam.Storage;
using JetBrains.Annotations;
using Newtonsoft.Json;
using SteamKit2;

namespace ArchiSteamFarm.OfficialPlugins.ItemsMatcher.Data;

internal class AnnouncementRequest {
[JsonProperty]
private readonly string? AvatarHash;
[JsonInclude]
private string? AvatarHash { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly Guid Guid;
[JsonInclude]
[JsonRequired]
private Guid Guid { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly ImmutableHashSet<AssetForListing> Inventory;
[JsonInclude]
[JsonRequired]
private ImmutableHashSet<AssetForListing> Inventory { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly string InventoryChecksum;
[JsonInclude]
[JsonRequired]
private string InventoryChecksum { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly ImmutableHashSet<Asset.EType> MatchableTypes;
[JsonInclude]
[JsonRequired]
private ImmutableHashSet<Asset.EType> MatchableTypes { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly bool MatchEverything;
[JsonInclude]
[JsonRequired]
private bool MatchEverything { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly byte MaxTradeHoldDuration;
[JsonInclude]
[JsonRequired]
private byte MaxTradeHoldDuration { get; init; }

[JsonProperty]
private readonly string? Nickname;
[JsonInclude]
private string? Nickname { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly ulong SteamID;
[JsonInclude]
[JsonRequired]
private ulong SteamID { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly uint TotalInventoryCount;
[JsonInclude]
[JsonRequired]
private uint TotalInventoryCount { get; init; }

[JsonProperty(Required = Required.Always)]
private readonly string TradeToken;
[JsonInclude]
[JsonRequired]
private string TradeToken { get; init; }

internal AnnouncementRequest(Guid guid, ulong steamID, IReadOnlyCollection<AssetForListing> inventory, string inventoryChecksum, IReadOnlyCollection<Asset.EType> matchableTypes, uint totalInventoryCount, bool matchEverything, byte maxTradeHoldDuration, string tradeToken, string? nickname = null, string? avatarHash = null) {
ArgumentOutOfRangeException.ThrowIfEqual(guid, Guid.Empty);
Expand Down
Loading
Loading