v3.2.3.0
- Minor refactoring - Querying cooldown is now written to and read from ProgramData so it can be persistent and hopefully steam's API limit is reached a little less often - Increased steam game info querying cooldown to 600 seconds (10 minutes) and steam DLC info querying cooldown to 1200 seconds (20 minutes) - Introduced a 600 second (10 minute) cooldown for Epic game queries using the same system above
This commit is contained in:
parent
dc2bc0e9e1
commit
62f9ba8ee9
8 changed files with 91 additions and 50 deletions
|
@ -5,7 +5,7 @@
|
|||
<UseWindowsForms>True</UseWindowsForms>
|
||||
<ApplicationIcon>Resources\ini.ico</ApplicationIcon>
|
||||
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
|
||||
<Version>3.2.2.5</Version>
|
||||
<Version>3.2.3.0</Version>
|
||||
<PackageIcon>Resources\ini.ico</PackageIcon>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>
|
||||
|
|
|
@ -27,21 +27,18 @@ internal static class EpicLibrary
|
|||
if (!Directory.Exists(EpicAppDataPath)) return games;
|
||||
string manifests = EpicAppDataPath + @"\Manifests";
|
||||
if (!Directory.Exists(manifests)) return games;
|
||||
string[] files = Directory.GetFiles(manifests);
|
||||
string[] files = Directory.GetFiles(manifests, "*.item");
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (Program.Canceled) return games;
|
||||
if (Path.GetExtension(file) == ".item")
|
||||
string json = File.ReadAllText(file);
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(file);
|
||||
try
|
||||
{
|
||||
Manifest manifest = JsonSerializer.Deserialize<Manifest>(json);
|
||||
if (manifest is not null && manifest.CatalogItemId == manifest.MainGameCatalogItemId)
|
||||
games.Add(manifest);
|
||||
}
|
||||
catch { };
|
||||
Manifest manifest = JsonSerializer.Deserialize<Manifest>(json);
|
||||
if (manifest is not null && manifest.CatalogItemId == manifest.MainGameCatalogItemId)
|
||||
games.Add(manifest);
|
||||
}
|
||||
catch { };
|
||||
}
|
||||
return games;
|
||||
});
|
||||
|
|
|
@ -16,36 +16,42 @@ namespace CreamInstaller.Epic;
|
|||
|
||||
internal static class EpicStore
|
||||
{
|
||||
//private const int COOLDOWN_CATALOG_ITEM = 600;
|
||||
|
||||
/* need a method to query catalog items
|
||||
internal static async Task QueryCatalogItems(Manifest manifest)
|
||||
{
|
||||
}*/
|
||||
|
||||
private const int COOLDOWN_ENTITLEMENT = 600;
|
||||
internal static async Task<List<(string id, string name, string product, string icon, string developer)>> QueryEntitlements(string categoryNamespace)
|
||||
{
|
||||
List<(string id, string name, string product, string icon, string developer)> dlcIds = new();
|
||||
Response response = await QueryGraphQL(categoryNamespace);
|
||||
string cacheFile = ProgramData.AppInfoPath + @$"\{categoryNamespace}.json";
|
||||
bool cachedExists = Directory.Exists(Directory.GetDirectoryRoot(cacheFile)) && File.Exists(cacheFile);
|
||||
Response response = null;
|
||||
if (!cachedExists || ProgramData.CheckCooldown(categoryNamespace, COOLDOWN_ENTITLEMENT))
|
||||
{
|
||||
response = await QueryGraphQL(categoryNamespace);
|
||||
try
|
||||
{
|
||||
File.WriteAllText(cacheFile, JsonConvert.SerializeObject(response, Formatting.Indented));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else if (cachedExists)
|
||||
{
|
||||
try
|
||||
{
|
||||
response = JsonConvert.DeserializeObject<Response>(File.ReadAllText(cacheFile));
|
||||
}
|
||||
catch
|
||||
{
|
||||
File.Delete(cacheFile);
|
||||
}
|
||||
}
|
||||
if (response is null)
|
||||
if (Directory.Exists(Directory.GetDirectoryRoot(cacheFile)) && File.Exists(cacheFile))
|
||||
try
|
||||
{
|
||||
response = JsonConvert.DeserializeObject<Response>(File.ReadAllText(cacheFile));
|
||||
}
|
||||
catch
|
||||
{
|
||||
File.Delete(cacheFile);
|
||||
}
|
||||
if (response is null) return dlcIds;
|
||||
try
|
||||
{
|
||||
File.WriteAllText(cacheFile, JsonConvert.SerializeObject(response, Formatting.Indented));
|
||||
}
|
||||
catch //(Exception e)
|
||||
{
|
||||
//using DialogForm dialogForm = new(null);
|
||||
//dialogForm.Show(SystemIcons.Error, "Unsuccessful serialization of query for category namespace " + categoryNamespace + ":\n\n" + e.ToString(), "FUCK");
|
||||
}
|
||||
return dlcIds;
|
||||
List<Element> searchStore = new(response.Data.Catalog.SearchStore.Elements);
|
||||
foreach (Element element in searchStore)
|
||||
{
|
||||
|
|
|
@ -144,7 +144,7 @@ internal partial class SelectForm : CustomForm
|
|||
RemoveFromRemainingGames(name);
|
||||
return;
|
||||
}
|
||||
AppData appData = await SteamStore.QueryStoreAPI(appId, 60);
|
||||
AppData appData = await SteamStore.QueryStoreAPI(appId);
|
||||
VProperty appInfo = await SteamCMD.GetAppInfo(appId, branch, buildId);
|
||||
if (appData is null && appInfo is null)
|
||||
{
|
||||
|
@ -169,7 +169,7 @@ internal partial class SelectForm : CustomForm
|
|||
Thread.Sleep(0);
|
||||
string dlcName = null;
|
||||
string dlcIcon = null;
|
||||
AppData dlcAppData = await SteamStore.QueryStoreAPI(dlcAppId);
|
||||
AppData dlcAppData = await SteamStore.QueryStoreAPI(dlcAppId, true);
|
||||
if (dlcAppData is not null)
|
||||
{
|
||||
dlcName = dlcAppData.name;
|
||||
|
|
|
@ -112,12 +112,12 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="Icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\resources\ini.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
|
|
|
@ -68,11 +68,11 @@ internal static class SteamLibrary
|
|||
{
|
||||
List<Tuple<string, string, string, int, string>> games = new();
|
||||
if (Program.Canceled || !Directory.Exists(libraryDirectory)) return null;
|
||||
string[] files = Directory.GetFiles(libraryDirectory);
|
||||
string[] files = Directory.GetFiles(libraryDirectory, "*.acf");
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (Program.Canceled) return null;
|
||||
if (Path.GetExtension(file) == ".acf" && ValveDataFile.TryDeserialize(File.ReadAllText(file, Encoding.UTF8), out VProperty result))
|
||||
if (ValveDataFile.TryDeserialize(File.ReadAllText(file, Encoding.UTF8), out VProperty result))
|
||||
{
|
||||
string appId = result.Value.GetChild("appid")?.ToString();
|
||||
string installdir = result.Value.GetChild("installdir")?.ToString();
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using CreamInstaller.Utility;
|
||||
|
@ -23,23 +20,22 @@ internal static class SteamStore
|
|||
return dlcIds;
|
||||
});
|
||||
|
||||
private static readonly ConcurrentDictionary<string, DateTime> lastQueries = new();
|
||||
internal static async Task<AppData> QueryStoreAPI(string appId, int cooldown = 10)
|
||||
private const int COOLDOWN_GAME = 600;
|
||||
private const int COOLDOWN_DLC = 1200;
|
||||
|
||||
internal static async Task<AppData> QueryStoreAPI(string appId, bool isDlc = false)
|
||||
{
|
||||
if (Program.Canceled) return null;
|
||||
Thread.Sleep(0);
|
||||
string cacheFile = ProgramData.AppInfoPath + @$"\{appId}.json";
|
||||
DateTime now = DateTime.UtcNow;
|
||||
if (!lastQueries.TryGetValue(appId, out DateTime lastQuery) || (now - lastQuery).TotalSeconds > cooldown)
|
||||
bool cachedExists = Directory.Exists(Directory.GetDirectoryRoot(cacheFile)) && File.Exists(cacheFile);
|
||||
if (!cachedExists || ProgramData.CheckCooldown(appId, isDlc ? COOLDOWN_DLC : COOLDOWN_GAME))
|
||||
{
|
||||
lastQueries[appId] = now;
|
||||
string response = await HttpClientManager.EnsureGet($"https://store.steampowered.com/api/appdetails?appids={appId}");
|
||||
if (response is not null)
|
||||
{
|
||||
IDictionary<string, JToken> apps = (dynamic)JsonConvert.DeserializeObject(response);
|
||||
foreach (KeyValuePair<string, JToken> app in apps)
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
try
|
||||
{
|
||||
AppData data = JsonConvert.DeserializeObject<AppDetails>(app.Value.ToString()).data;
|
||||
|
@ -65,7 +61,7 @@ internal static class SteamStore
|
|||
}
|
||||
}
|
||||
}
|
||||
if (Directory.Exists(Directory.GetDirectoryRoot(cacheFile)) && File.Exists(cacheFile))
|
||||
if (cachedExists)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -16,6 +16,8 @@ internal static class ProgramData
|
|||
|
||||
internal static readonly Version MinimumAppInfoVersion = Version.Parse("3.2.0.0");
|
||||
|
||||
internal static readonly string CooldownPath = DirectoryPath + @"\cooldown";
|
||||
|
||||
internal static async Task Setup() => await Task.Run(() =>
|
||||
{
|
||||
if (Directory.Exists(DirectoryPathOld))
|
||||
|
@ -30,5 +32,45 @@ internal static class ProgramData
|
|||
Directory.CreateDirectory(AppInfoPath);
|
||||
File.WriteAllText(AppInfoVersionPath, Application.ProductVersion, Encoding.UTF8);
|
||||
}
|
||||
if (!Directory.Exists(CooldownPath))
|
||||
Directory.CreateDirectory(CooldownPath);
|
||||
});
|
||||
|
||||
internal static bool CheckCooldown(string identifier, int cooldown)
|
||||
{
|
||||
DateTime now = DateTime.UtcNow;
|
||||
DateTime lastCheck = GetCooldown(identifier) ?? now;
|
||||
bool cooldownOver = (now - lastCheck).TotalSeconds > cooldown;
|
||||
if (cooldownOver || now == lastCheck)
|
||||
SetCooldown(identifier, now);
|
||||
return cooldownOver;
|
||||
}
|
||||
private static DateTime? GetCooldown(string identifier)
|
||||
{
|
||||
if (Directory.Exists(CooldownPath))
|
||||
{
|
||||
string cooldownFile = CooldownPath + @$"\{identifier}.txt";
|
||||
if (File.Exists(cooldownFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DateTime.TryParse(File.ReadAllText(cooldownFile), out DateTime cooldown))
|
||||
return cooldown;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static void SetCooldown(string identifier, DateTime time)
|
||||
{
|
||||
if (!Directory.Exists(CooldownPath))
|
||||
Directory.CreateDirectory(CooldownPath);
|
||||
string cooldownFile = CooldownPath + @$"\{identifier}.txt";
|
||||
try
|
||||
{
|
||||
File.WriteAllText(cooldownFile, time.ToString());
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue