From dd59d796f789716148243a4a9d696dd7d37e6788 Mon Sep 17 00:00:00 2001
From: DrakiaXYZ <565558+TheDgtl@users.noreply.github.com>
Date: Thu, 25 Apr 2024 23:33:20 -0700
Subject: [PATCH] Utilize R2 for release downloads

Implemented by pulling `release.json` from R2 to get a list of mirrors, and pulling the sptaki 7z file based on the mirror
The current R2 mirror is setup with a re-build of SPT 3.8.0 that Refringe is working on automating
---
 SPTInstaller/Installer Tasks/DownloadTask.cs  | 29 ++++++++++++-------
 .../Installer Tasks/ReleaseCheckTask.cs       | 22 +++++++++-----
 SPTInstaller/Models/InternalData.cs           | 12 ++------
 3 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/SPTInstaller/Installer Tasks/DownloadTask.cs b/SPTInstaller/Installer Tasks/DownloadTask.cs
index 375f154..b9e67c6 100644
--- a/SPTInstaller/Installer Tasks/DownloadTask.cs	
+++ b/SPTInstaller/Installer Tasks/DownloadTask.cs	
@@ -83,6 +83,24 @@ public class DownloadTask : InstallerTaskBase
         return Result.FromError("Failed to download Patcher");
     }
 
+    private async Task<IResult> DownloadSptAkiFromMirrors(IProgress<double> progress)
+    {
+        // Note that GetOrDownloadFileAsync handles the cached file hash check, so we don't need to check it first
+        foreach (var mirror in _data.ReleaseInfo.Mirrors)
+        {
+            SetStatus("Downloading SPT-AKI", mirror.DownloadUrl, progressStyle: ProgressStyle.Indeterminate);
+
+            _data.AkiZipInfo = await DownloadCacheHelper.GetOrDownloadFileAsync("sptaki", mirror.DownloadUrl, progress, mirror.Hash);
+
+            if (_data.AkiZipInfo != null)
+            {
+                return Result.FromSuccess();
+            }
+        }
+
+        return Result.FromError("Failed to download spt-aki");
+    }
+
     public override async Task<IResult> TaskOperation()
     {
         var progress = new Progress<double>((d) => { SetStatus(null, null, (int)Math.Floor(d)); });
@@ -106,15 +124,6 @@ public class DownloadTask : InstallerTaskBase
             }
         }
 
-        SetStatus("Downloading SPT-AKI", _data.AkiReleaseDownloadLink, 0);
-
-        _data.AkiZipInfo = await DownloadCacheHelper.GetOrDownloadFileAsync("sptaki", _data.AkiReleaseDownloadLink, progress, _data.AkiReleaseHash);
-
-        if (_data.AkiZipInfo == null)
-        {
-            return Result.FromError("Failed to download spt-aki");
-        }
-
-        return Result.FromSuccess();
+        return await DownloadSptAkiFromMirrors(progress);
     }
 }
\ No newline at end of file
diff --git a/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs b/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs
index 6037550..f30211d 100644
--- a/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs	
+++ b/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs	
@@ -4,6 +4,8 @@ using SPTInstaller.Interfaces;
 using SPTInstaller.Models;
 using System.Threading.Tasks;
 using SPTInstaller.Helpers;
+using Newtonsoft.Json;
+using SPTInstaller.Models.Releases;
 
 namespace SPTInstaller.Installer_Tasks;
 
@@ -24,21 +26,25 @@ public class ReleaseCheckTask : InstallerTaskBase
 
             SetStatus("Checking SPT Releases", "", null, ProgressStyle.Indeterminate);
 
-            var akiRepoReleases = await repo.RepoListReleasesAsync("SPT-AKI", "Stable-releases");
+            var progress = new Progress<double>((d) => { SetStatus(null, null, (int)Math.Floor(d)); });
+            var akiReleaseInfoFile = await DownloadCacheHelper.DownloadFileAsync("release.json", "https://spt-releases.modd.in/release.json", progress);
+            if (akiReleaseInfoFile == null)
+            {
+                return Result.FromError("Failed to download release metadata");
+            }
+
+            var akiReleaseInfo = JsonConvert.DeserializeObject<ReleaseInfo>(File.ReadAllText(akiReleaseInfoFile.FullName));
 
             SetStatus("Checking for Patches", "", null, ProgressStyle.Indeterminate);
 
             var patchRepoReleases = await repo.RepoListReleasesAsync("SPT-AKI", "Downgrade-Patches");
 
-            var latestAkiRelease = akiRepoReleases.FindAll(x => !x.Prerelease)[0];
-            var latestAkiVersion = latestAkiRelease.Name.Replace('(', ' ').Replace(')', ' ').Split(' ')[3];
-            var comparePatchToAki = patchRepoReleases?.Find(x => x.Name.Contains(_data.OriginalGameVersion) && x.Name.Contains(latestAkiVersion));
+            var comparePatchToAki = patchRepoReleases?.Find(x => x.Name.Contains(_data.OriginalGameVersion) && x.Name.Contains(akiReleaseInfo.ClientVersion));
 
             _data.PatcherMirrorsLink = comparePatchToAki?.Assets[0].BrowserDownloadUrl;
-            _data.AkiReleaseDownloadLink = latestAkiRelease.Assets[0].BrowserDownloadUrl;
-            _data.AkiReleaseHash = FileHashHelper.GetGiteaReleaseHash(latestAkiRelease);
+            _data.ReleaseInfo = akiReleaseInfo;
 
-            int IntAkiVersion = int.Parse(latestAkiVersion);
+            int IntAkiVersion = int.Parse(akiReleaseInfo.ClientVersion);
             int IntGameVersion = int.Parse(_data.OriginalGameVersion);
             bool patchNeedCheck = false;
 
@@ -65,7 +71,7 @@ public class ReleaseCheckTask : InstallerTaskBase
 
             _data.PatchNeeded = patchNeedCheck;
 
-            string status = $"Current Release: {latestAkiVersion} - {(_data.PatchNeeded ? "Patch Available" : "No Patch Needed")}";
+            string status = $"Current Release: {akiReleaseInfo.ClientVersion} - {(_data.PatchNeeded ? "Patch Available" : "No Patch Needed")}";
 
             SetStatus(null, status);
 
diff --git a/SPTInstaller/Models/InternalData.cs b/SPTInstaller/Models/InternalData.cs
index e81a2b7..3ceffb6 100644
--- a/SPTInstaller/Models/InternalData.cs
+++ b/SPTInstaller/Models/InternalData.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using SPTInstaller.Models.Mirrors;
+using SPTInstaller.Models.Releases;
 
 namespace SPTInstaller.Models;
 
@@ -31,14 +30,9 @@ public class InternalData
     public FileInfo AkiZipInfo { get; set; }
 
     /// <summary>
-    /// The release download link for SPT-AKI
+    /// The release information from release.json
     /// </summary>
-    public string AkiReleaseDownloadLink { get; set; }
-
-    /// <summary>
-    /// The release zip hash
-    /// </summary>
-    public string AkiReleaseHash { get; set; } = null;
+    public ReleaseInfo ReleaseInfo { get; set; }
 
     /// <summary>
     /// The release download link for the patcher mirror list