Skip to content

Commit

Permalink
Add "discoverallapps" command
Browse files Browse the repository at this point in the history
  • Loading branch information
Citrinate committed May 6, 2024
1 parent 69bcba8 commit a7f678a
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 3 deletions.
15 changes: 14 additions & 1 deletion FreePackages/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ArchiSteamFarm.Core;
using ArchiSteamFarm.Steam;
using FreePackages.Localization;

namespace FreePackages {
internal static class Commands {
internal static string? Response(Bot bot, EAccess access, ulong steamID, string message, string[] args) {
internal static async Task<string?> Response(Bot bot, EAccess access, ulong steamID, string message, string[] args) {
if (!Enum.IsDefined(access)) {
throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess));
}
Expand All @@ -27,6 +29,9 @@ internal static class Commands {
case "CLEARFREEPACKAGESQUEUE":
return ResponseClearQueue(bot, access);

case "DISCOVERALLAPPS" or "DISCOVERALL" or "DALLAPPS" or "DALL" or "DAPPS" or "QUEUEALLAPPS" or "QUEUEALL" or "QALLAPPS" or "QALL" or "QAPPS":
return await ResponseDiscoverAllApps(bot, access).ConfigureAwait(false);

case "QSA":
return ResponseQueueStatus(access, steamID, "ASF");
case "QSTATUS" or "QUEUESTATUS":
Expand Down Expand Up @@ -93,6 +98,14 @@ internal static class Commands {
return responses.Count > 0 ? String.Join(Environment.NewLine, responses) : null;
}

private static async Task<string?> ResponseDiscoverAllApps(Bot bot, EAccess access) {
if (access < EAccess.Master) {
return null;
}

return FormatBotResponse(bot, await PackageHandler.DiscoverAllApps().ConfigureAwait(false));
}

private static string? ResponseQueueStatus(Bot bot, EAccess access) {
if (access < EAccess.Master) {
return null;
Expand Down
96 changes: 96 additions & 0 deletions FreePackages/Data/AppList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using ArchiSteamFarm.Core;
using ArchiSteamFarm.Steam;
using ArchiSteamFarm.Web.Responses;
using SteamKit2;

namespace FreePackages {
internal static class AppList {
internal static async Task<HashSet<uint>?> GetAllApps() {
try {
return (await GetCachedAPIApps().ConfigureAwait(false))
.Union(await GetAPIApps().ConfigureAwait(false))
.Union(await GetStoreAPIApps().ConfigureAwait(false))
.ToHashSet<uint>();

} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);

return null;
}
}

private static async Task<HashSet<uint>> GetCachedAPIApps() {
ArgumentNullException.ThrowIfNull(ASF.WebBrowser);

try {
Uri source = new("https://raw.githubusercontent.com/Citrinate/Steam-MarketableApps/main/data/marketable_apps.min.json");
ObjectResponse<HashSet<uint>>? response = await ASF.WebBrowser.UrlGetToJsonObject<HashSet<uint>>(source).ConfigureAwait(false);

ArgumentNullException.ThrowIfNull(response);
ArgumentNullException.ThrowIfNull(response.Content);

return response.Content;
} catch (Exception) {
throw;
}
}

private static async Task<HashSet<uint>> GetAPIApps() {
Bot? bot = Bot.BotsReadOnly?.Values.FirstOrDefault(static bot => bot.IsConnectedAndLoggedOn);

ArgumentNullException.ThrowIfNull(bot);

MethodInfo? GetMarketableAppIDs = typeof(Bot).GetMethods(BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance).FirstOrDefault(x => x.Name == "GetMarketableAppIDs");

ArgumentNullException.ThrowIfNull(GetMarketableAppIDs);

try {
var res = (Task<HashSet<uint>?>?) GetMarketableAppIDs.Invoke(bot, new object[]{});

ArgumentNullException.ThrowIfNull(res);

await res.ConfigureAwait(false);

ArgumentNullException.ThrowIfNull(res.Result);

return res.Result;
} catch (Exception) {
throw;
}
}

private static async Task<HashSet<uint>> GetStoreAPIApps() {
Bot? bot = Bot.BotsReadOnly?.Values.FirstOrDefault(static bot => bot.IsConnectedAndLoggedOn);

ArgumentNullException.ThrowIfNull(bot);

try {
using WebAPI.AsyncInterface storeService = bot.SteamConfiguration.GetAsyncWebAPIInterface("IStoreService");

List<uint> apps = new();
uint lastAppId = 0;
KeyValue response;
do {
response = await storeService.CallAsync(HttpMethod.Get, "GetAppList", 1, new Dictionary<string, object?> {
{ "access_token", bot.AccessToken },
{ "last_appid", lastAppId },
{ "max_results", 50000 },
}).ConfigureAwait(false);

apps.AddRange(response["apps"].Children.Select(app => app["appid"].AsUnsignedInteger()).ToList());
lastAppId = response["last_appid"].AsUnsignedInteger();
} while (response["have_more_results"].AsBoolean());

return apps.Distinct().ToHashSet<uint>();
} catch (Exception) {
throw;
}
}
}
}
4 changes: 2 additions & 2 deletions FreePackages/FreePackages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public Task OnLoaded() {
return Task.CompletedTask;
}

public Task<string?> OnBotCommand(Bot bot, EAccess access, string message, string[] args, ulong steamID = 0) {
return Task.FromResult(Commands.Response(bot, access, steamID, message, args));
public async Task<string?> OnBotCommand(Bot bot, EAccess access, string message, string[] args, ulong steamID = 0) {
return await Commands.Response(bot, access, steamID, message, args).ConfigureAwait(false);
}

public async Task OnASFInit(IReadOnlyDictionary<string, JsonElement>? additionalConfigProperties = null) {
Expand Down
12 changes: 12 additions & 0 deletions FreePackages/Handlers/PackageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -484,5 +484,17 @@ internal void AddPackages(HashSet<uint>? appIDs, HashSet<uint>? packageIDs, bool

PackageQueue.AddPackages(packages);
}

internal static async Task<string> DiscoverAllApps() {
HashSet<uint>? appIDs = await AppList.GetAllApps().ConfigureAwait(false);
if (appIDs == null) {
return Strings.AppListFailed;
}

Handlers.Values.ToList().ForEach(x => x.BotCache.AddChanges(appIDs));
Utilities.InBackground(async() => await HandleChanges().ConfigureAwait(false));

return String.Format(Strings.AppsDiscovered, appIDs.Count);
}
}
}
8 changes: 8 additions & 0 deletions FreePackages/Localization/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,12 @@
<value>Failed to parse data from ASFInfo</value>
<comment/>
</data>
<data name="AppsDiscovered" xml:space="preserve">
<value>Discovered {0} apps</value>
<comment>{0} will be replaced by a number</comment>
</data>
<data name="AppListFailed" xml:space="preserve">
<value>Failed to get app list</value>
<comment/>
</data>
</root>

0 comments on commit a7f678a

Please sign in to comment.