Move to announce endpoint v3

By using ordered list for json body, we can further minimize amount of data sent by getting rid of the index.

We still need previous asset ID, as we send only a subset of real data and server is unable to calculate it from the data sent.
This commit is contained in:
Archi 2023-01-21 20:32:42 +01:00
parent 41fef74e36
commit 4cb8244353
No known key found for this signature in database
GPG key ID: 6B138B4C64555AEA
4 changed files with 9 additions and 14 deletions

View file

@ -38,7 +38,7 @@ using SteamKit2;
namespace ArchiSteamFarm.OfficialPlugins.ItemsMatcher;
internal static class Backend {
internal static async Task<BasicResponse?> AnnounceForListing(ulong steamID, WebBrowser webBrowser, IReadOnlyCollection<AssetForListing> inventory, IReadOnlyCollection<Asset.EType> acceptedMatchableTypes, uint totalInventoryCount, bool matchEverything, string tradeToken, string? nickname = null, string? avatarHash = null) {
internal static async Task<BasicResponse?> AnnounceForListing(ulong steamID, WebBrowser webBrowser, IReadOnlyList<AssetForListing> inventory, IReadOnlyCollection<Asset.EType> acceptedMatchableTypes, uint totalInventoryCount, bool matchEverything, string tradeToken, string? nickname = null, string? avatarHash = null) {
if ((steamID == 0) || !new SteamID(steamID).IsIndividualAccount) {
throw new ArgumentOutOfRangeException(nameof(steamID));
}
@ -65,7 +65,7 @@ internal static class Backend {
throw new ArgumentOutOfRangeException(nameof(tradeToken));
}
Uri request = new(ArchiNet.URL, "/Api/Listing/Announce/v2");
Uri request = new(ArchiNet.URL, "/Api/Listing/Announce/v3");
AnnouncementRequest data = new(ASF.GlobalDatabase?.Identifier ?? Guid.NewGuid(), steamID, tradeToken, inventory, acceptedMatchableTypes, totalInventoryCount, matchEverything, ASF.GlobalConfig?.MaxTradeHoldDuration ?? GlobalConfig.DefaultMaxTradeHoldDuration, nickname, avatarHash);

View file

@ -38,7 +38,7 @@ internal sealed class AnnouncementRequest {
private readonly Guid Guid;
[JsonProperty(Required = Required.Always)]
private readonly ImmutableHashSet<AssetForListing> Inventory;
private readonly ImmutableList<AssetForListing> Inventory;
[JsonProperty(Required = Required.Always)]
private readonly ImmutableHashSet<Asset.EType> MatchableTypes;
@ -61,7 +61,7 @@ internal sealed class AnnouncementRequest {
[JsonProperty(Required = Required.Always)]
private readonly string TradeToken;
internal AnnouncementRequest(Guid guid, ulong steamID, string tradeToken, IReadOnlyCollection<AssetForListing> inventory, IReadOnlyCollection<Asset.EType> matchableTypes, uint totalInventoryCount, bool matchEverything, byte maxTradeHoldDuration, string? nickname = null, string? avatarHash = null) {
internal AnnouncementRequest(Guid guid, ulong steamID, string tradeToken, IReadOnlyList<AssetForListing> inventory, IReadOnlyCollection<Asset.EType> matchableTypes, uint totalInventoryCount, bool matchEverything, byte maxTradeHoldDuration, string? nickname = null, string? avatarHash = null) {
if (guid == Guid.Empty) {
throw new ArgumentOutOfRangeException(nameof(guid));
}
@ -93,7 +93,7 @@ internal sealed class AnnouncementRequest {
Guid = guid;
SteamID = steamID;
TradeToken = tradeToken;
Inventory = inventory.ToImmutableHashSet();
Inventory = inventory.ToImmutableList();
MatchableTypes = matchableTypes.ToImmutableHashSet();
MatchEverything = matchEverything;
MaxTradeHoldDuration = maxTradeHoldDuration;

View file

@ -26,16 +26,12 @@ using Newtonsoft.Json;
namespace ArchiSteamFarm.OfficialPlugins.ItemsMatcher.Data;
internal sealed class AssetForListing : AssetInInventory {
[JsonProperty("i", Required = Required.Always)]
internal readonly uint Index;
[JsonProperty("l", Required = Required.Always)]
internal readonly ulong PreviousAssetID;
internal AssetForListing(Asset asset, uint index, ulong previousAssetID) : base(asset) {
internal AssetForListing(Asset asset, ulong previousAssetID) : base(asset) {
ArgumentNullException.ThrowIfNull(asset);
Index = index;
PreviousAssetID = previousAssetID;
}
}

View file

@ -238,10 +238,9 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
bool matchEverything = Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchEverything);
uint index = 0;
ulong previousAssetID = 0;
HashSet<AssetForListing> assetsForListing = new();
List<AssetForListing> assetsForListing = new();
Dictionary<(uint RealAppID, Asset.EType Type, Asset.ERarity Rarity), bool> tradableSets = new();
@ -249,7 +248,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
if (acceptedMatchableTypes.Contains(item.Type)) {
// Only tradable assets matter for MatchEverything bots
if (!matchEverything || item.Tradable) {
assetsForListing.Add(new AssetForListing(item, index++, previousAssetID));
assetsForListing.Add(new AssetForListing(item, previousAssetID));
}
// But even for Fair bots, we should track and skip sets where we don't have any item to trade with
@ -279,7 +278,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
// We can now skip sets where we don't have any item to trade with, MatchEverything bots are already filtered to tradable only
if (!matchEverything) {
assetsForListing.RemoveWhere(item => tradableSets.TryGetValue((item.RealAppID, item.Type, item.Rarity), out bool tradable) && !tradable);
assetsForListing.RemoveAll(item => tradableSets.TryGetValue((item.RealAppID, item.Type, item.Rarity), out bool tradable) && !tradable);
if (assetsForListing.Count == 0) {
// We're not eligible, record this as a valid check