From cd31ac1cfa26230284d738c42c3175821b49bdc8 Mon Sep 17 00:00:00 2001 From: pointfeev Date: Fri, 25 Feb 2022 00:22:27 -0500 Subject: [PATCH] steam store web parsing for extra DLC --- CreamInstaller/Classes/HttpClientManager.cs | 16 ++++++++++++++++ CreamInstaller/Classes/ProgramSelection.cs | 2 +- CreamInstaller/Forms/MainForm.cs | 2 +- CreamInstaller/Forms/SelectForm.cs | 19 +++++++++---------- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/CreamInstaller/Classes/HttpClientManager.cs b/CreamInstaller/Classes/HttpClientManager.cs index e5ac363..2e32f5c 100644 --- a/CreamInstaller/Classes/HttpClientManager.cs +++ b/CreamInstaller/Classes/HttpClientManager.cs @@ -1,9 +1,12 @@ using System; +using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; +using System.Web; using HtmlAgilityPack; @@ -44,5 +47,18 @@ internal static class HttpClientManager return null; } + internal static async Task ParseSteamStoreDlcAppIds(int appId, List dlcIds) + { + // currently this is only really needed to get DLC that release without changing game buildid (very rare) + // it also finds things which aren't really connected to the game itself, and thus not needed (usually soundtracks, collections, packs, etc.) + HtmlNodeCollection nodes = await GetDocumentNodes( + $"https://store.steampowered.com/dlc/{appId}", + "//div[@class='recommendation']/div/a"); + if (nodes is not null) + foreach (HtmlNode node in nodes) + if (int.TryParse(node.Attributes["data-ds-appid"]?.Value, out int dlcAppId) && !dlcIds.Contains(dlcAppId)) + dlcIds.Add(dlcAppId); + } + internal static void Cleanup() => httpClient.Dispose(); } diff --git a/CreamInstaller/Classes/ProgramSelection.cs b/CreamInstaller/Classes/ProgramSelection.cs index 6df9231..9b5ddf1 100644 --- a/CreamInstaller/Classes/ProgramSelection.cs +++ b/CreamInstaller/Classes/ProgramSelection.cs @@ -98,7 +98,7 @@ internal class ProgramSelection internal static void ValidateAll() => AllSafe.ForEach(selection => selection.Validate()); - internal static List All => new(); + internal static List All = new(); internal static List AllSafe => All.ToList(); diff --git a/CreamInstaller/Forms/MainForm.cs b/CreamInstaller/Forms/MainForm.cs index b2df1cb..9589758 100644 --- a/CreamInstaller/Forms/MainForm.cs +++ b/CreamInstaller/Forms/MainForm.cs @@ -110,7 +110,7 @@ internal partial class MainForm : CustomForm Program.Invoke(changelogTreeView, delegate { TreeNode change = new(); - change.Text = $"{HttpUtility.HtmlDecode(node.InnerText)}"; + change.Text = HttpUtility.HtmlDecode(node.InnerText); root.Nodes.Add(change); root.Expand(); }); diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs index 193c673..9844019 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.Web; using System.Windows.Forms; using CreamInstaller.Classes; @@ -15,6 +16,8 @@ using CreamInstaller.Resources; using Gameloop.Vdf.Linq; +using HtmlAgilityPack; + namespace CreamInstaller; internal partial class SelectForm : CustomForm @@ -131,18 +134,19 @@ internal partial class SelectForm : CustomForm ConcurrentDictionary dlc = new(); List dlcTasks = new(); List dlcIds = await SteamCMD.ParseDlcAppIds(appInfo); + await HttpClientManager.ParseSteamStoreDlcAppIds(appId, dlcIds); if (dlcIds.Count > 0) { - foreach (int id in dlcIds) + foreach (int dlcAppId in dlcIds) { if (Program.Canceled) return; - AddToRemainingDLCs(id.ToString()); + AddToRemainingDLCs(dlcAppId.ToString()); Task task = Task.Run(async () => { if (Program.Canceled) return; string dlcName = null; string dlcIconStaticId = null; - VProperty dlcAppInfo = await SteamCMD.GetAppInfo(id); + VProperty dlcAppInfo = await SteamCMD.GetAppInfo(dlcAppId); if (dlcAppInfo is not null) { dlcName = dlcAppInfo.Value?.GetChild("common")?.GetChild("name")?.ToString(); @@ -152,8 +156,8 @@ internal partial class SelectForm : CustomForm } if (Program.Canceled) return; if (!string.IsNullOrWhiteSpace(dlcName)) - dlc[id] = (dlcName, dlcIconStaticId); - RemoveFromRemainingDLCs(id.ToString()); + dlc[dlcAppId] = (dlcName, dlcIconStaticId); + RemoveFromRemainingDLCs(dlcAppId.ToString()); progress.Report(++CompleteTasks); }); dlcTasks.Add(task); @@ -168,11 +172,6 @@ internal partial class SelectForm : CustomForm return; } if (Program.Canceled) return; - if (string.IsNullOrWhiteSpace(name)) - { - RemoveFromRemainingGames(name); - return; - } foreach (Task task in dlcTasks) { if (Program.Canceled) return;