From cf4c5ea551d7e23291f59b05fb727ca9accf9b3c Mon Sep 17 00:00:00 2001 From: Jeddunk Date: Wed, 13 Jan 2021 18:57:10 +0100 Subject: [PATCH] Replace single cache with two separate caches for Games and DLC --- GoldbergGUI.Core/Models/SteamAppModel.cs | 50 ++++++-- GoldbergGUI.Core/Services/SteamService.cs | 141 +++++++++++++--------- 2 files changed, 121 insertions(+), 70 deletions(-) diff --git a/GoldbergGUI.Core/Models/SteamAppModel.cs b/GoldbergGUI.Core/Models/SteamAppModel.cs index 1a13adf..d8f60e4 100644 --- a/GoldbergGUI.Core/Models/SteamAppModel.cs +++ b/GoldbergGUI.Core/Models/SteamAppModel.cs @@ -28,34 +28,58 @@ namespace GoldbergGUI.Core.Models } } - public bool CompareName(string value) - { - return _comparableName.Equals(value); - } + public bool CompareName(string value) => _comparableName.Equals(value); + + public AppType type { get; set; } public override string ToString() { return $"{AppId}={Name}"; } + + [JsonPropertyName("last_modified")] public long LastModified { get; set; } + + [JsonPropertyName("price_change_number")] + public long PriceChangeNumber { get; set; } } public class AppList { [JsonPropertyName("apps")] public List Apps { get; set; } + + [JsonPropertyName("have_more_results")] + public bool HaveMoreResults { get; set; } + + [JsonPropertyName("last_appid")] public long LastAppid { get; set; } } public class SteamApps { - [JsonPropertyName("applist")] public AppList AppList { get; set; } + public virtual AppList AppList { get; set; } } - public static class AppType + + public class SteamAppsV2 : SteamApps { - public const string Game = "game"; - public const string DLC = "dlc"; - public const string Music = "music"; - public const string Demo = "demo"; - public const string Ad = "advertising"; - public const string Mod = "mod"; - public const string Video = "video"; + [JsonPropertyName("applist")] public override AppList AppList { get; set; } + } + + public class SteamAppsV1 : SteamApps + { + [JsonPropertyName("response")] public override AppList AppList { get; set; } + } + + public class AppType + { + private AppType(string value) => Value = value; + + public string Value { get; } + + public static AppType Game => new AppType("game"); + public static AppType DLC => new AppType("dlc"); + public static AppType Music => new AppType("music"); + public static AppType Demo => new AppType("demo"); + public static AppType Ad => new AppType("advertising"); + public static AppType Mod => new AppType("mod"); + public static AppType Video => new AppType("video"); } } \ No newline at end of file diff --git a/GoldbergGUI.Core/Services/SteamService.cs b/GoldbergGUI.Core/Services/SteamService.cs index 89edaaa..23925de 100644 --- a/GoldbergGUI.Core/Services/SteamService.cs +++ b/GoldbergGUI.Core/Services/SteamService.cs @@ -32,26 +32,29 @@ namespace GoldbergGUI.Core.Services public class SteamService : ISteamService { // ReSharper disable StringLiteralTypo - private readonly List<(string filename, string uri, string type)> _caches = new List<(string, string, string)> - { - ( - "steamapps.json", - "https://api.steampowered.com/ISteamApps/GetAppList/v2/", - null - ), - ( - "steamapps_games.json", - "https://api.steampowered.com/IStoreService/GetAppList/v1/?include_games=1&key=" + - Secrets.SteamWebApiKey(), - AppType.Game - ), - ( - "steamapps_dlc.json", - "https://api.steampowered.com/IStoreService/GetAppList/v1/?include_games=0&include_dlc=1&key=" + - Secrets.SteamWebApiKey(), - AppType.DLC - ) - }; + private readonly List<(string filename, string uri, Type jsonType, AppType type)> _cacheSetup = + new List<(string, string, Type, AppType)> + { + ( + "steamapps_games.json", + "https://api.steampowered.com/IStoreService/GetAppList/v1/" + + "?max_results=50000" + + "&include_games=1" + + "&key=" + Secrets.SteamWebApiKey(), + typeof(SteamAppsV1), + AppType.Game + ), + ( + "steamapps_dlc.json", + "https://api.steampowered.com/IStoreService/GetAppList/v1/" + + "?max_results=50000" + + "&include_games=0" + + "&include_dlc=1" + + "&key=" + Secrets.SteamWebApiKey(), + typeof(SteamAppsV1), + AppType.DLC + ) + }; // ReSharper enable StringLiteralTypo private static readonly Secrets Secrets = new Secrets(); @@ -60,30 +63,69 @@ namespace GoldbergGUI.Core.Services "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/87.0.4280.88 Safari/537.36"; - private HashSet _cache = new HashSet(); + //private HashSet _cacheAll = new HashSet(); + //private HashSet _cacheGame = new HashSet(); + //private HashSet _cacheDlc = new HashSet(); + private Dictionary> _caches = new Dictionary>(); private IMvxLog _log; public async Task Initialize(IMvxLog log) { - var path = _caches.First().filename; - var uri = _caches.First().uri; - _log = log; - _log.Info("Updating cache..."); - var updateNeeded = DateTime.Now.Subtract(File.GetLastWriteTimeUtc(path)).TotalDays >= 1; - var cacheString = await GetCache(updateNeeded, uri, path).ConfigureAwait(false); - SteamApps steamApps; - try + //var (path, uri, jsonType, appType) = _caches[0]; + static SteamApps SteamApps(Type type, string s) { - steamApps = JsonSerializer.Deserialize(cacheString); - } - catch (JsonException) - { - cacheString = await GetCache(true, uri, path).ConfigureAwait(false); - steamApps = JsonSerializer.Deserialize(cacheString); + SteamApps steamApps1 = null; + if (type == typeof(SteamAppsV1)) + steamApps1 = JsonSerializer.Deserialize(s); + else if (type == typeof(SteamAppsV2)) + steamApps1 = JsonSerializer.Deserialize(s); + return steamApps1; } - _cache = new HashSet(steamApps.AppList.Apps); - _log.Info("Loaded cache into memory!"); + foreach (var (path, uri, jsonType, appType) in _cacheSetup) + { + _log = log; + _log.Info("Updating cache..."); + var updateNeeded = DateTime.Now.Subtract(File.GetLastWriteTimeUtc(path)).TotalDays >= 1; + var cacheString = await GetCache(updateNeeded, uri, path).ConfigureAwait(false); + SteamApps steamApps = null; + try + { + steamApps = SteamApps(jsonType, cacheString); + } + catch (JsonException) + { + _log.Error("Local cache broken, forcing update..."); + cacheString = await GetCache(true, uri, path).ConfigureAwait(false); + steamApps = SteamApps(jsonType, cacheString); + } + + try + { + var cache = new HashSet(steamApps.AppList.Apps); + + if (appType != null) + { + var cacheEdited = new HashSet(); + foreach (var steamApp in cache) + { + steamApp.type = appType; + cacheEdited.Add(steamApp); + } + + cache = cacheEdited; + } + + _caches.Add(path, cache); + + _log.Info("Loaded cache into memory!"); + } + catch (NullReferenceException e) + { + Console.WriteLine(e); + throw; + } + } } private async Task GetCache(bool updateNeeded, string steamUri, string cachePath) @@ -113,32 +155,17 @@ namespace GoldbergGUI.Core.Services public IEnumerable GetListOfAppsByName(string name) { - var listOfAppsByName = _cache.Search(x => x.Name) + var listOfAppsByName = _caches["steamapps_games.json"].Search(x => x.Name) .SetCulture(StringComparison.OrdinalIgnoreCase) .ContainingAll(name.Split(' ')); return listOfAppsByName; - /*var filteredList = new HashSet(); - foreach (var steamApp in listOfAppsByName) - { - try - { - var task = AppDetails.GetAsync(steamApp.AppId); - var details = await task.ConfigureAwait(false); - if (details?.Type != null && details.Type == AppType.Game) filteredList.Add(steamApp); - } - catch (Exception e) - { - _log.Debug($"{e.GetType()}: {steamApp}"); - } - } - return filteredList;*/ } public SteamApp GetAppByName(string name) { _log.Info($"Trying to get app {name}"); var comparableName = Regex.Replace(name, Misc.SpecialCharsRegex, "").ToLower(); - var app = _cache.FirstOrDefault(x => x.CompareName(comparableName)); + var app = _caches["steamapps_games.json"].FirstOrDefault(x => x.CompareName(comparableName)); if (app != null) _log.Info($"Successfully got app {app}"); return app; } @@ -146,7 +173,7 @@ namespace GoldbergGUI.Core.Services public SteamApp GetAppById(int appid) { _log.Info($"Trying to get app with ID {appid}"); - var app = _cache.FirstOrDefault(x => x.AppId.Equals(appid)); + var app = _caches["steamapps_games.json"].FirstOrDefault(x => x.AppId.Equals(appid)); if (app != null) _log.Info($"Successfully got app {app}"); return app; } @@ -159,11 +186,11 @@ namespace GoldbergGUI.Core.Services { var task = AppDetails.GetAsync(steamApp.AppId); var steamAppDetails = await task.ConfigureAwait(true); - if (steamAppDetails.Type == AppType.Game) + if (steamAppDetails.Type == AppType.Game.Value) { steamAppDetails.DLC.ForEach(x => { - var result = _cache.FirstOrDefault(y => y.AppId.Equals(x)) ?? + var result = _caches["steamapps_dlc.json"].FirstOrDefault(y => y.AppId.Equals(x)) ?? new SteamApp {AppId = x, Name = $"Unknown DLC {x}"}; dlcList.Add(result); });