diff --git a/SPTInstaller/Helpers/DownloadCacheHelper.cs b/SPTInstaller/Helpers/DownloadCacheHelper.cs
index 2866bb3..45ddb8b 100644
--- a/SPTInstaller/Helpers/DownloadCacheHelper.cs
+++ b/SPTInstaller/Helpers/DownloadCacheHelper.cs
@@ -8,7 +8,8 @@ namespace SPTInstaller.Helpers;
public static class DownloadCacheHelper
{
private static HttpClient _httpClient = new() { Timeout = TimeSpan.FromMinutes(15) };
-
+
+ public static TimeSpan SuggestedTtl = TimeSpan.FromHours(1);
public static string CachePath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"spt-installer/cache");
@@ -50,10 +51,10 @@ public static class DownloadCacheHelper
/// The expected hash of the file in the cache
/// The file found in the cache; null if no file is found
/// True if the file is in the cache and its hash matches the expected hash, otherwise false
- public static bool CheckCache(string fileName, string expectedHash, out FileInfo cachedFile)
- => CheckCache(new FileInfo(Path.Join(CachePath, fileName)), expectedHash, out cachedFile);
+ public static bool CheckCacheHash(string fileName, string expectedHash, out FileInfo cachedFile)
+ => CheckCacheHash(new FileInfo(Path.Join(CachePath, fileName)), expectedHash, out cachedFile);
- private static bool CheckCache(FileInfo cacheFile, string expectedHash, out FileInfo fileInCache)
+ private static bool CheckCacheHash(FileInfo cacheFile, string expectedHash, out FileInfo fileInCache)
{
fileInCache = cacheFile;
@@ -85,6 +86,44 @@ public static class DownloadCacheHelper
return false;
}
}
+
+ ///
+ /// Gets a file in the cache based on a time-to-live from its last modified time
+ ///
+ /// The name of the file to look for in the cache
+ /// The time-to-live to check against
+ /// The file found in the cache if it exists
+ /// Returns true if the file was found in the cache, otherwise false
+ public static bool CheckCacheTTL(string fileName, TimeSpan ttl, out FileInfo cachedFile) =>
+ CheckCacheTTL(new FileInfo(Path.Join(CachePath, fileName)), ttl, out cachedFile);
+
+ private static bool CheckCacheTTL(FileInfo cacheFile, TimeSpan ttl, out FileInfo fileInCache)
+ {
+ fileInCache = cacheFile;
+
+ try
+ {
+ cacheFile.Refresh();
+ Directory.CreateDirectory(CachePath);
+
+ if (!cacheFile.Exists)
+ {
+ Log.Information($"{cacheFile.Name} {(cacheFile.Exists ? "is in cache" : "NOT in cache")}");
+ return false;
+ }
+
+ var validTimeToLive = cacheFile.LastWriteTime.Add(ttl) > DateTime.Now;
+
+ Log.Information($"{cacheFile.Name} TTL is {(validTimeToLive ? "OK" : "INVALID")}");
+
+ return validTimeToLive;
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex, "Something went wrong during hashing");
+ return false;
+ }
+ }
///
/// Download a file to the cache folder
@@ -166,6 +205,33 @@ public static class DownloadCacheHelper
return null;
}
}
+
+ ///
+ /// Get or download a file using a time to live
+ ///
+ /// The file to get from cache
+ /// The link to use for the download
+ /// A progress object for reporting download progress
+ /// The time-to-live to check against in the cache
+ ///
+ public static async Task GetOrDownloadFileAsync(string fileName, string targetLink,
+ IProgress progress, TimeSpan timeToLive)
+ {
+ try
+ {
+ if (CheckCacheTTL(fileName, timeToLive, out FileInfo cachedFile))
+ {
+ return cachedFile;
+ }
+
+ return await DownloadFileAsync(fileName, targetLink, progress);
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex, $"Error while getting file: {fileName}");
+ return null;
+ }
+ }
///
/// Get the file from cache or download it
@@ -181,7 +247,7 @@ public static class DownloadCacheHelper
{
try
{
- if (CheckCache(fileName, expectedHash, out var cacheFile))
+ if (CheckCacheHash(fileName, expectedHash, out var cacheFile))
return cacheFile;
return await DownloadFileAsync(fileName, targetLink, progress);
@@ -206,7 +272,7 @@ public static class DownloadCacheHelper
{
try
{
- if (CheckCache(fileName, expectedHash, out var cacheFile))
+ if (CheckCacheHash(fileName, expectedHash, out var cacheFile))
return cacheFile;
return await DownloadFileAsync(fileName, fileDownloadStream);
diff --git a/SPTInstaller/Installer Tasks/DownloadTask.cs b/SPTInstaller/Installer Tasks/DownloadTask.cs
index af0785d..75875cc 100644
--- a/SPTInstaller/Installer Tasks/DownloadTask.cs
+++ b/SPTInstaller/Installer Tasks/DownloadTask.cs
@@ -45,7 +45,7 @@ public class DownloadTask : InstallerTaskBase
{
SetStatus("Downloading Patcher", "Verifying cached patcher ...", progressStyle: ProgressStyle.Indeterminate);
- if (DownloadCacheHelper.CheckCache("patcher", _expectedPatcherHash, out var cacheFile))
+ if (DownloadCacheHelper.CheckCacheHash("patcher", _expectedPatcherHash, out var cacheFile))
{
_data.PatcherZipInfo = cacheFile;
Log.Information("Using cached file {fileName} - Hash: {hash}", _data.PatcherZipInfo.Name,
diff --git a/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs b/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs
index 7add179..8857c55 100644
--- a/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs
+++ b/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs
@@ -25,8 +25,9 @@ public class ReleaseCheckTask : InstallerTaskBase
var progress = new Progress((d) => { SetStatus(null, null, (int)Math.Floor(d)); });
var akiReleaseInfoFile =
- await DownloadCacheHelper.DownloadFileAsync("release.json", DownloadCacheHelper.ReleaseMirrorUrl,
- progress);
+ await DownloadCacheHelper.GetOrDownloadFileAsync("release.json", DownloadCacheHelper.ReleaseMirrorUrl,
+ progress, DownloadCacheHelper.SuggestedTtl);
+
if (akiReleaseInfoFile == null)
{
return Result.FromError("Failed to download release metadata");
@@ -38,8 +39,8 @@ public class ReleaseCheckTask : InstallerTaskBase
SetStatus("Checking for Patches", "", null, ProgressStyle.Indeterminate);
var akiPatchMirrorsFile =
- await DownloadCacheHelper.DownloadFileAsync("mirrors.json", DownloadCacheHelper.PatchMirrorUrl,
- progress);
+ await DownloadCacheHelper.GetOrDownloadFileAsync("mirrors.json", DownloadCacheHelper.PatchMirrorUrl,
+ progress, DownloadCacheHelper.SuggestedTtl);
if (akiPatchMirrorsFile == null)
{
diff --git a/SPTInstaller/Models/InstallerUpdateInfo.cs b/SPTInstaller/Models/InstallerUpdateInfo.cs
index e8575ce..cd58bc8 100644
--- a/SPTInstaller/Models/InstallerUpdateInfo.cs
+++ b/SPTInstaller/Models/InstallerUpdateInfo.cs
@@ -140,8 +140,8 @@ public class InstallerUpdateInfo : ReactiveObject
try
{
var installerInfoFile =
- await DownloadCacheHelper.DownloadFileAsync("installer.json", DownloadCacheHelper.InstallerInfoUrl,
- null);
+ await DownloadCacheHelper.GetOrDownloadFileAsync("installer.json", DownloadCacheHelper.InstallerInfoUrl, null
+ , DownloadCacheHelper.SuggestedTtl);
if (installerInfoFile == null)
{
diff --git a/SPTInstaller/ViewModels/PreChecksViewModel.cs b/SPTInstaller/ViewModels/PreChecksViewModel.cs
index 182db76..7b111c6 100644
--- a/SPTInstaller/ViewModels/PreChecksViewModel.cs
+++ b/SPTInstaller/ViewModels/PreChecksViewModel.cs
@@ -286,9 +286,11 @@ public class PreChecksViewModel : ViewModelBase
InstallButtonCheckState = StatusSpinner.SpinnerState.Running;
var progress = new Progress((d) => { });
+
var akiReleaseInfoFile =
- await DownloadCacheHelper.DownloadFileAsync("release.json", DownloadCacheHelper.ReleaseMirrorUrl,
- progress);
+ await DownloadCacheHelper.GetOrDownloadFileAsync("release.json", DownloadCacheHelper.ReleaseMirrorUrl,
+ progress, DownloadCacheHelper.SuggestedTtl);
+
if (akiReleaseInfoFile == null)
{
InstallButtonText = "Could not get SPT release metadata";