Skip to content

Commit

Permalink
Properly resolve #3358
Browse files Browse the repository at this point in the history
  • Loading branch information
JustArchi committed Dec 20, 2024
1 parent b251598 commit 7dc3d16
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ private static async Task Refresh(Bot bot) {
return;
}

HashSet<uint> packageIDs = bot.OwnedPackageIDs.Where(static package => (Config?.SecretPackageIDs.Contains(package.Key) != true) && ((package.Value.PaymentMethod != EPaymentMethod.AutoGrant) || (Config?.SkipAutoGrantPackages == false))).Select(static package => package.Key).ToHashSet();
HashSet<uint> packageIDs = bot.OwnedPackages.Where(static package => (Config?.SecretPackageIDs.Contains(package.Key) != true) && ((package.Value.PaymentMethod != EPaymentMethod.AutoGrant) || (Config?.SkipAutoGrantPackages == false))).Select(static package => package.Key).ToHashSet();

HashSet<uint> appIDsToRefresh = [];

Expand Down Expand Up @@ -644,7 +644,7 @@ private static async Task SubmitData(CancellationToken cancellationToken = defau
return;
}

ulong contributorSteamID = ASF.GlobalConfig is { SteamOwnerID: > 0 } && new SteamID(ASF.GlobalConfig.SteamOwnerID).IsIndividualAccount ? ASF.GlobalConfig.SteamOwnerID : Bot.Bots.Values.Where(static bot => bot.SteamID > 0).MaxBy(static bot => bot.OwnedPackageIDs.Count)?.SteamID ?? 0;
ulong contributorSteamID = ASF.GlobalConfig is { SteamOwnerID: > 0 } && new SteamID(ASF.GlobalConfig.SteamOwnerID).IsIndividualAccount ? ASF.GlobalConfig.SteamOwnerID : Bot.Bots.Values.Where(static bot => bot.SteamID > 0).MaxBy(static bot => bot.OwnedPackages.Count)?.SteamID ?? 0;

if (contributorSteamID == 0) {
ASF.ArchiLogger.LogGenericError(Strings.FormatSubmissionNoContributorSet(nameof(ASF.GlobalConfig.SteamOwnerID)));
Expand Down
26 changes: 16 additions & 10 deletions ArchiSteamFarm/Steam/Bot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,13 @@ private set {
public string? Nickname { get; private set; }

[JsonIgnore]
[Obsolete($"Use {nameof(OwnedPackages)} instead, this property will be removed in the future version")]
[PublicAPI]
public FrozenDictionary<uint, (EPaymentMethod PaymentMethod, DateTime TimeCreated)> OwnedPackageIDs { get; private set; } = FrozenDictionary<uint, (EPaymentMethod PaymentMethod, DateTime TimeCreated)>.Empty;
public FrozenDictionary<uint, (EPaymentMethod PaymentMethod, DateTime TimeCreated)> OwnedPackageIDs => OwnedPackages.Values.ToFrozenDictionary(static entry => entry.PackageID, static entry => (entry.PaymentMethod, entry.TimeCreated));

[JsonIgnore]
[PublicAPI]
public FrozenDictionary<uint, SteamApps.LicenseListCallback.License> OwnedPackages { get; private set; } = FrozenDictionary<uint, SteamApps.LicenseListCallback.License>.Empty;

[JsonInclude]
[JsonRequired]
Expand Down Expand Up @@ -1112,7 +1117,7 @@ internal static string FormatBotResponse(string response, string botName) {
ArgumentOutOfRangeException.ThrowIfZero(appID);
ArgumentOutOfRangeException.ThrowIfNegative(hoursPlayed);

HashSet<uint>? packageIDs = ASF.GlobalDatabase?.GetPackageIDs(appID, OwnedPackageIDs.Keys);
HashSet<uint>? packageIDs = ASF.GlobalDatabase?.GetPackageIDs(appID, OwnedPackages.Keys);

if ((packageIDs == null) || (packageIDs.Count == 0)) {
return (0, DateTime.MaxValue, true);
Expand All @@ -1122,7 +1127,7 @@ internal static string FormatBotResponse(string response, string botName) {
DateTime mostRecent = DateTime.MinValue;

foreach (uint packageID in packageIDs) {
if (!OwnedPackageIDs.TryGetValue(packageID, out (EPaymentMethod PaymentMethod, DateTime TimeCreated) packageData)) {
if (!OwnedPackages.TryGetValue(packageID, out SteamApps.LicenseListCallback.License? packageData)) {
continue;
}

Expand All @@ -1147,7 +1152,7 @@ internal static string FormatBotResponse(string response, string botName) {
DateTime safePlayableBefore = DateTime.UtcNow.AddMonths(-RegionRestrictionPlayableBlockMonths);

foreach (uint packageID in packageIDs) {
if (!OwnedPackageIDs.TryGetValue(packageID, out (EPaymentMethod PaymentMethod, DateTime TimeCreated) ownedPackageData)) {
if (!OwnedPackages.TryGetValue(packageID, out SteamApps.LicenseListCallback.License? ownedPackageData)) {
// We don't own that packageID, keep checking
continue;
}
Expand Down Expand Up @@ -2849,7 +2854,7 @@ private async void OnDisconnected(SteamClient.DisconnectedCallback callback) {
Trading.OnDisconnected();

FirstTradeSent = false;
OwnedPackageIDs = FrozenDictionary<uint, (EPaymentMethod PaymentMethod, DateTime TimeCreated)>.Empty;
OwnedPackages = FrozenDictionary<uint, SteamApps.LicenseListCallback.License>.Empty;

EResult lastLogOnResult = LastLogOnResult;

Expand Down Expand Up @@ -3173,17 +3178,18 @@ private async void OnLicenseList(SteamApps.LicenseListCallback callback) {

Commands.OnNewLicenseList();

Dictionary<uint, (EPaymentMethod PaymentMethod, DateTime TimeCreated)> ownedPackageIDs = new();
Dictionary<uint, SteamApps.LicenseListCallback.License> ownedPackages = new();

Dictionary<uint, ulong> packageAccessTokens = new();
Dictionary<uint, uint> packagesToRefresh = new();

bool hasNewEntries = false;

foreach (SteamApps.LicenseListCallback.License license in callback.LicenseList.GroupBy(static license => license.PackageID, static (_, licenses) => licenses.OrderByDescending(static license => license.TimeCreated).First())) {
ownedPackageIDs[license.PackageID] = (license.PaymentMethod, license.TimeCreated);
// We want to record only the most relevant entry, therefore we apply ordering here so we end up preferably with the most recent non-borrowed entry
foreach (SteamApps.LicenseListCallback.License license in callback.LicenseList.OrderByDescending(static license => license.LicenseFlags.HasFlag(ELicenseFlags.Borrowed)).ThenBy(static license => license.TimeCreated)) {
ownedPackages[license.PackageID] = license;

if (!OwnedPackageIDs.ContainsKey(license.PackageID)) {
if (!OwnedPackages.ContainsKey(license.PackageID)) {
hasNewEntries = true;
}

Expand All @@ -3197,7 +3203,7 @@ private async void OnLicenseList(SteamApps.LicenseListCallback callback) {
}
}

OwnedPackageIDs = ownedPackageIDs.ToFrozenDictionary();
OwnedPackages = ownedPackages.ToFrozenDictionary();

if (packageAccessTokens.Count > 0) {
ASF.GlobalDatabase.RefreshPackageAccessTokens(packageAccessTokens);
Expand Down
4 changes: 2 additions & 2 deletions ArchiSteamFarm/Steam/Cards/CardsFarmer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1496,11 +1496,11 @@ private async Task SortGamesToFarm() {

foreach (Game game in GamesToFarm) {
DateTime redeemDate = DateTime.MinValue;
HashSet<uint>? packageIDs = ASF.GlobalDatabase?.GetPackageIDs(game.AppID, Bot.OwnedPackageIDs.Keys);
HashSet<uint>? packageIDs = ASF.GlobalDatabase?.GetPackageIDs(game.AppID, Bot.OwnedPackages.Values.Where(static package => !package.LicenseFlags.HasFlag(ELicenseFlags.Borrowed)).Select(static package => package.PackageID));

if (packageIDs != null) {
foreach (uint packageID in packageIDs) {
if (!Bot.OwnedPackageIDs.TryGetValue(packageID, out (EPaymentMethod PaymentMethod, DateTime TimeCreated) packageData)) {
if (!Bot.OwnedPackages.TryGetValue(packageID, out SteamApps.LicenseListCallback.License? packageData)) {
Bot.ArchiLogger.LogNullError(packageData);

return;
Expand Down
10 changes: 5 additions & 5 deletions ArchiSteamFarm/Steam/Interaction/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ internal void OnNewLicenseList() {

switch (type.ToUpperInvariant()) {
case "A" or "APP": {
HashSet<uint>? packageIDs = ASF.GlobalDatabase?.GetPackageIDs(gameID, Bot.OwnedPackageIDs.Keys, 1);
HashSet<uint>? packageIDs = ASF.GlobalDatabase?.GetPackageIDs(gameID, Bot.OwnedPackages.Values.Where(static package => !package.LicenseFlags.HasFlag(ELicenseFlags.Borrowed)).Select(static package => package.PackageID), 1);

if (packageIDs is { Count: > 0 }) {
response.AppendLine(FormatBotResponse(Strings.FormatBotAddLicense($"app/{gameID}", $"{EResult.Fail}/{EPurchaseResultDetail.AlreadyPurchased}")));
Expand All @@ -690,7 +690,7 @@ internal void OnNewLicenseList() {
break;
}
default: {
if (Bot.OwnedPackageIDs.ContainsKey(gameID)) {
if (Bot.OwnedPackages.TryGetValue(gameID, out SteamApps.LicenseListCallback.License? package) && !package.LicenseFlags.HasFlag(ELicenseFlags.Borrowed)) {
response.AppendLine(FormatBotResponse(Strings.FormatBotAddLicense($"sub/{gameID}", $"{EResult.Fail}/{EPurchaseResultDetail.AlreadyPurchased}")));

break;
Expand Down Expand Up @@ -2020,7 +2020,7 @@ internal void OnNewLicenseList() {

switch (type.ToUpperInvariant()) {
case "A" or "APP" when uint.TryParse(game, out uint appID) && (appID > 0):
HashSet<uint>? packageIDs = ASF.GlobalDatabase?.GetPackageIDs(appID, Bot.OwnedPackageIDs.Keys, 1);
HashSet<uint>? packageIDs = ASF.GlobalDatabase?.GetPackageIDs(appID, Bot.OwnedPackages.Values.Where(static package => !package.LicenseFlags.HasFlag(ELicenseFlags.Borrowed)).Select(static package => package.PackageID), 1);

if (packageIDs?.Count > 0) {
if ((gamesOwned != null) && gamesOwned.TryGetValue(appID, out string? cachedGameName)) {
Expand Down Expand Up @@ -2087,7 +2087,7 @@ internal void OnNewLicenseList() {

continue;
case "S" or "SUB" when uint.TryParse(game, out uint packageID) && (packageID > 0):
if (Bot.OwnedPackageIDs.ContainsKey(packageID)) {
if (Bot.OwnedPackages.TryGetValue(packageID, out SteamApps.LicenseListCallback.License? package) && !package.LicenseFlags.HasFlag(ELicenseFlags.Borrowed)) {
result[$"sub/{packageID}"] = packageID.ToString(CultureInfo.InvariantCulture);
response.AppendLine(FormatBotResponse(Strings.FormatBotOwnedAlready($"sub/{packageID}")));
} else {
Expand Down Expand Up @@ -2658,7 +2658,7 @@ internal void OnNewLicenseList() {

bool alreadyHandled = false;

foreach (Bot innerBot in Bot.Bots.Where(bot => (bot.Value != currentBot) && (!redeemFlags.HasFlag(ERedeemFlags.SkipInitial) || (bot.Value != Bot)) && !triedBots.Contains(bot.Value) && !rateLimitedBots.Contains(bot.Value) && bot.Value.IsConnectedAndLoggedOn && ((access >= EAccess.Owner) || ((steamID != 0) && (bot.Value.GetAccess(steamID) >= EAccess.Operator))) && ((items.Count == 0) || items.Keys.Any(packageID => !bot.Value.OwnedPackageIDs.ContainsKey(packageID)))).OrderBy(static bot => bot.Key, Bot.BotsComparer).Select(static bot => bot.Value)) {
foreach (Bot innerBot in Bot.Bots.Where(bot => (bot.Value != currentBot) && (!redeemFlags.HasFlag(ERedeemFlags.SkipInitial) || (bot.Value != Bot)) && !triedBots.Contains(bot.Value) && !rateLimitedBots.Contains(bot.Value) && bot.Value.IsConnectedAndLoggedOn && ((access >= EAccess.Owner) || ((steamID != 0) && (bot.Value.GetAccess(steamID) >= EAccess.Operator))) && ((items.Count == 0) || items.Keys.Any(packageID => !bot.Value.OwnedPackages.ContainsKey(packageID)))).OrderBy(static bot => bot.Key, Bot.BotsComparer).Select(static bot => bot.Value)) {
CStore_RegisterCDKey_Response? redeemResponse = await innerBot.Actions.RedeemKey(key).ConfigureAwait(false);

if (redeemResponse == null) {
Expand Down

0 comments on commit 7dc3d16

Please sign in to comment.