Skip to content

Commit

Permalink
Use a more robust way to detect Invalid App Purchase
Browse files Browse the repository at this point in the history
Bug fixed "Reduce plugin's log spam on invalid/already owned appid" which was only active after 1 day
Bug fixed not saving fgldict files on changes
  • Loading branch information
maxisoft committed Oct 24, 2022
1 parent cd2d3c2 commit acb8e2a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 9 deletions.
56 changes: 48 additions & 8 deletions ASFFreeGames/ASFFreeGamesPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using ArchiSteamFarm;
Expand Down Expand Up @@ -38,8 +40,10 @@ internal sealed class ASFFreeGamesPlugin : IASF, IBot, IBotConnection, IBotComma
private readonly RedditHelper RedditHelper = new();
private readonly SemaphoreSlim SemaphoreSlim = new(1, 1);
private readonly Lazy<CancellationTokenSource> CancellationTS = new(static () => new CancellationTokenSource());
private HashSet<GameIdentifier> PreviouslySeenAppIds = new HashSet<GameIdentifier>();
private static readonly EPurchaseResultDetail[] InvalidAppPurchaseCodes = new[] { EPurchaseResultDetail.AlreadyPurchased, EPurchaseResultDetail.RegionNotSupported, EPurchaseResultDetail.InvalidPackage };
private readonly HashSet<GameIdentifier> PreviouslySeenAppIds = new();
private static readonly EPurchaseResultDetail[] InvalidAppPurchaseCodes = { EPurchaseResultDetail.AlreadyPurchased, EPurchaseResultDetail.RegionNotSupported, EPurchaseResultDetail.InvalidPackage, EPurchaseResultDetail.DoesNotOwnRequiredApp };
private static readonly Lazy<Regex> InvalidAppPurchaseRegex = new(BuildInvalidAppPurchaseRegex);


private Timer? Timer;

Expand Down Expand Up @@ -212,14 +216,16 @@ private async Task<int> CollectGames(IEnumerable<Bot> bots, CancellationToken ca
save = true;
res++;
}
else if (DateTimeOffset.UtcNow.ToUnixTimeSeconds() - time > DayInSeconds) {
lock (context) {
context.AppTickCount(in gid, increment: true);

if (InvalidAppPurchaseCodes.Any(c => resp?.Contains(c.ToString(), StringComparison.InvariantCultureIgnoreCase) ?? false)) {
context.RegisterInvalidApp(in gid);
else {
if (DateTimeOffset.UtcNow.ToUnixTimeSeconds() - time > DayInSeconds) {
lock (context) {
context.AppTickCount(in gid, increment: true);
}
}

if (InvalidAppPurchaseRegex.Value.IsMatch(resp ?? "")) {
save |= context.RegisterInvalidApp(in gid);
}
}
}

Expand Down Expand Up @@ -255,5 +261,39 @@ private void LogNewGameCount(ICollection<RedditGameEntry> games) {
ArchiLogger.LogGenericInfo($"[FreeGames] found {newGameCounter} fresh free game(s) on reddit", nameof(CollectGames));
}
}

private static Regex BuildInvalidAppPurchaseRegex() {
StringBuilder stringBuilder = new("^.*(?:");

foreach (EPurchaseResultDetail code in InvalidAppPurchaseCodes) {
stringBuilder.Append("(?:");
ReadOnlySpan<char> codeString = code.ToString().Replace(nameof(EPurchaseResultDetail), @"\w*", StringComparison.InvariantCultureIgnoreCase);
codeString = codeString.TrimStart('.');

if (codeString.Length <= 1) {
continue;
}

stringBuilder.Append(codeString[0]);

foreach (char c in codeString[1..]) {
if (char.IsUpper(c)) {
stringBuilder.Append(@"\s*");
}

stringBuilder.Append(c);
}

stringBuilder.Append(")|");
}

while ((stringBuilder.Length > 0) && (stringBuilder[^1] == '|')) {
stringBuilder.Length -= 1;
}

stringBuilder.Append(").*$");

return new Regex(stringBuilder.ToString(), RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
}
}
#pragma warning restore CA1812 // ASF uses this class during runtime
2 changes: 1 addition & 1 deletion ASFFreeGames/BotContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void RegisterApp(in GameIdentifier gameIdentifier) {
}
}

public void RegisterInvalidApp(in GameIdentifier gameIdentifier) => CompletedApps.AddInvalid(in gameIdentifier);
public bool RegisterInvalidApp(in GameIdentifier gameIdentifier) => CompletedApps.AddInvalid(in gameIdentifier);

public bool HasApp(in GameIdentifier gameIdentifier) {
if (!gameIdentifier.Valid) {
Expand Down

0 comments on commit acb8e2a

Please sign in to comment.