Skip to content

Commit

Permalink
Discover packages posted to Reddit
Browse files Browse the repository at this point in the history
  • Loading branch information
Citrinate committed Mar 24, 2024
1 parent 5803cf8 commit 67313c2
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 1 deletion.
97 changes: 97 additions & 0 deletions FreePackages/Data/ASFInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using ArchiSteamFarm.Core;
using ArchiSteamFarm.Web.Responses;
using FreePackages.Localization;

// There are limitations to using PICS for discovery such that an account that's online 24/7 can still miss certain free games
// For more information see here: https://github.com/Citrinate/FreePackages/commit/7541807f10e8dde53b1352a2c103b867e5446fa1#commitcomment-137669223
// To fill in some of these gaps, we periodically check the free apps/subs list provided by https://github.com/C4illin/ASFinfo

namespace FreePackages {
internal static class ASFInfo {
private static Uri Source = new("https://gist.githubusercontent.com/C4illin/e8c5cf365d816f2640242bf01d8d3675/raw/Steam%2520Codes");
private static TimeSpan UpdateFrequency = TimeSpan.FromHours(1);

private static Timer UpdateTimer = new(async e => await DoUpdate().ConfigureAwait(false), null, Timeout.Infinite, Timeout.Infinite);

internal static void Update() {
UpdateTimer.Change(TimeSpan.FromMinutes(15), UpdateFrequency);
}

private static async Task DoUpdate() {
ArgumentNullException.ThrowIfNull(ASF.WebBrowser);
ArgumentNullException.ThrowIfNull(FreePackages.GlobalCache);

StreamResponse? response = await ASF.WebBrowser.UrlGetToStream(Source).ConfigureAwait(false);

if (response == null) {
ASF.ArchiLogger.LogNullError(response);

return;
}

if (response.Content == null) {
ASF.ArchiLogger.LogNullError(response.Content);

return;
}

HashSet<uint> appIDs = new();
HashSet<uint> packageIDs = new();
uint itemCount = 0;

using (StreamReader sr = new StreamReader(response.Content)) {
while (sr.Peek() >= 0) {
itemCount++;
string? line = sr.ReadLine();

if (line == null) {
ASF.ArchiLogger.LogNullError(line);

return;
}

if (itemCount <= FreePackages.GlobalCache.LastASFInfoItemCount) {
continue;
}

// Match examples: a/12345 or s/12345
Match item = Regex.Match(line, "(?<type>[as])/(?<id>[0-9]+)");

if (!item.Success) {
ASF.ArchiLogger.LogGenericError(String.Format("{0}: {1}", Strings.ASFInfoParseFailed, line));

return;
}

if (!uint.TryParse(item.Groups["id"].Value, out uint id)) {
ASF.ArchiLogger.LogGenericError(String.Format("{0}: {1}", Strings.ASFInfoParseFailed, line));

return;
}

if (item.Groups["type"].Value == "a") {
// App
appIDs.Add(id);
} else if (item.Groups["type"].Value == "s") {
// Sub
packageIDs.Add(id);
}
}
}

if (appIDs.Count == 0 && packageIDs.Count == 0) {
return;
}

PackageHandler.Handlers.Values.ToList().ForEach(x => x.BotCache.AddChanges(appIDs, packageIDs));
FreePackages.GlobalCache.UpdateASFInfoItemCount(itemCount);
}
}
}
11 changes: 10 additions & 1 deletion FreePackages/Data/GlobalCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ internal sealed class GlobalCache : SerializableFile {
private static string SharedFilePath => Path.Combine(ArchiSteamFarm.SharedInfo.ConfigDirectory, $"{nameof(FreePackages)}.cache");

[JsonInclude]
[JsonRequired]
internal uint LastChangeNumber { get; private set; }

[JsonInclude]
internal uint LastASFInfoItemCount { get; private set; }

public bool ShouldSerializeLastChangeNumber() => LastChangeNumber > 0;
public bool ShouldSerializeLastASFInfoItemCount() => LastASFInfoItemCount > 0;

[JsonConstructor]
internal GlobalCache() {
Expand Down Expand Up @@ -59,5 +62,11 @@ internal void UpdateChangeNumber(uint currentChangeNumber) {

Utilities.InBackground(Save);
}

internal void UpdateASFInfoItemCount(uint currentASFInfoItemCount) {
LastASFInfoItemCount = currentASFInfoItemCount;

Utilities.InBackground(Save);
}
}
}
1 change: 1 addition & 0 deletions FreePackages/FreePackages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public async Task OnASFInit(IReadOnlyDictionary<string, JsonElement>? additional
}

CardApps.Update();
ASFInfo.Update();
}

public async Task OnBotInitModules(Bot bot, IReadOnlyDictionary<string, JsonElement>? additionalConfigProperties = null) {
Expand Down
4 changes: 4 additions & 0 deletions FreePackages/Localization/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,8 @@
<value>Free Packages plugin not enabled</value>
<comment/>
</data>
<data name="ASFInfoParseFailed" xml:space="preserve">
<value>Failed to parse data from ASFInfo</value>
<comment/>
</data>
</root>

0 comments on commit 67313c2

Please sign in to comment.