diff --git a/LevelImposter/LevelImposter.csproj b/LevelImposter/LevelImposter.csproj index 118799e..2eaa6dd 100644 --- a/LevelImposter/LevelImposter.csproj +++ b/LevelImposter/LevelImposter.csproj @@ -1,7 +1,7 @@ LevelImposter - 0.20.1 + 0.20.2 Custom Among Us Mapping Studio DigiWorm diff --git a/LevelImposter/Shop/Util/GitHubAPI.cs b/LevelImposter/Shop/Util/GitHubAPI.cs index 6e7b139..4af3783 100644 --- a/LevelImposter/Shop/Util/GitHubAPI.cs +++ b/LevelImposter/Shop/Util/GitHubAPI.cs @@ -4,6 +4,7 @@ using System.Text.Json; using Il2CppInterop.Runtime.Attributes; using LevelImposter.Core; +using UnityEngine; namespace LevelImposter.Shop; @@ -12,9 +13,10 @@ namespace LevelImposter.Shop; /// public static class GitHubAPI { - public const string API_PATH = "https://api.github.com/repos/DigiWorm0/LevelImposter/releases?per_page=5"; - public const string UPDATE_FORBIDDEN_FLAG = "[NoAutoUpdate]"; + public const string API_PATH = "https://api.github.com/repos/DigiWorm0/LevelImposter/releases?per_page=1"; public const string DEV_VERSION_FLAG = "dev"; + public const string UPDATE_BLACKLIST_FLAG = "[NoAutoUpdate]"; + public static readonly string UPDATE_WHITELIST_FLAG = $"[AU={Application.version}]"; /// /// Gets the current path where the LevelImposter DLL is stored. @@ -32,60 +34,64 @@ public static string GetDLLDirectory() /// Callback on success /// Callback on error [HideFromIl2Cpp] - private static void GetLatestReleases(Action onSuccess, Action onError) + public static void GetLatestRelease(Action onSuccess, Action onError) { LILogger.Info("Getting latest release info from GitHub"); + LILogger.Info(UPDATE_WHITELIST_FLAG); HTTPHandler.Instance?.Request(API_PATH, json => { - var response = JsonSerializer.Deserialize(json); - if (response != null) - onSuccess(response); + var responses = JsonSerializer.Deserialize(json); + if (responses != null && responses.Length > 0) + onSuccess(responses[0]); else onError("Invalid API response"); }, onError); } /// - /// Gets the latest release data from GitHub + /// Checks if a GHRelease can be updated to /// - /// Callback on success - /// Callback on error + /// GitHub release object + /// Reason for not being able to update + /// True if the release can be updated to [HideFromIl2Cpp] - public static void GetLatestRelease(Action onSuccess, Action onError) + public static bool CanUpdateTo(GHRelease release, out string reason) { - GetLatestReleases(releases => { onSuccess(releases[0]); }, onError); - } + // Get version info + var versionString = release.Name?.Split(" ")[1]; + var isCurrent = IsCurrent(release); + var isDevVersion = versionString?.Contains(DEV_VERSION_FLAG) ?? false; + var isWhitelisted = release.Body?.Contains(UPDATE_WHITELIST_FLAG) ?? false; + var isBlacklisted = release.Body?.Contains(UPDATE_BLACKLIST_FLAG) ?? false; + var hasReleaseAssets = release.Assets?.Length > 0; - /// - /// Checks release chain if update is forbidden - /// - /// List of releases in order of relevancy - /// TRUE if the update is forbidden. FALSE otherwise - [HideFromIl2Cpp] - private static bool IsUpdateForbidden(GHRelease[] releases) - { - foreach (var release in releases) - { - if (IsCurrent(release)) - return false; - if (release.Body.Contains(UPDATE_FORBIDDEN_FLAG)) - return true; - } + // Set reason + if (isCurrent) + reason = "Already up-to-date"; + else if (isDevVersion) + reason = "You're on a dev version"; + else if (!isWhitelisted) + reason = "Incorrect Among Us version"; + else if (isBlacklisted) + reason = "Auto-update to this version is disabled"; + else if (!hasReleaseAssets) + reason = "No release assets found"; + else + reason = "Unknown"; - return false; + // Return result + return !isCurrent && !isDevVersion && isWhitelisted && !isBlacklisted && hasReleaseAssets; } /// - /// Checks if the GitHub release matches - /// the current release version + /// Checks if the release is the current version installed /// - /// Release data to check - /// True if the release matches the current version + /// True if the release matches the current mod version [HideFromIl2Cpp] public static bool IsCurrent(GHRelease release) { - var versionString = release.Name.Split(" ")[1]; - return versionString == LevelImposter.DisplayVersion || LevelImposter.DisplayVersion.Contains(DEV_VERSION_FLAG); + var versionString = release.Name?.Split(" ")[1]; + return versionString == LevelImposter.DisplayVersion; } /// @@ -97,46 +103,42 @@ public static bool IsCurrent(GHRelease release) public static void UpdateMod(Action onSuccess, Action onError) { LILogger.Info("Updating mod from GitHub"); - GetLatestReleases(releases => + GetLatestRelease(release => { - var release = releases[0]; - LILogger.Info($"Downloading DLL from {release}"); - if (release.Assets.Length <= 0) + // Check if update is available + if (!CanUpdateTo(release, out var reason)) { - var errorMsg = $"No release assets were found for {release}"; + var errorMsg = $"Auto-update to {release} is unavailable:\n{reason}"; LILogger.Error(errorMsg); onError(errorMsg); return; } - if (IsUpdateForbidden(releases)) - { - var errorMsg = $"Auto-update to {release} is unavailable."; - LILogger.Error(errorMsg); - onError(errorMsg); - return; - } - - var downloadURL = release.Assets[0].BrowserDownloadURL; + // Download DLL + LILogger.Info($"Downloading DLL from {release}"); + var downloadURL = release.Assets?[0].BrowserDownloadURL ?? ""; HTTPHandler.Instance?.Request(downloadURL, dllBytes => { LILogger.Info($"Saving {dllBytes.Length / 1024}kb DLL to local filesystem"); try { + // Get DLL path var dllPath = GetDLLDirectory(); var dllOldPath = dllPath + ".old"; + // Move old DLL if (File.Exists(dllOldPath)) File.Delete(dllOldPath); File.Move(dllPath, dllOldPath); - using (var fileStream = File.Create(dllPath)) - { - fileStream.Write(dllBytes, 0, dllBytes.Length); - } + // Write new DLL + using var fileStream = File.Create(dllPath); + fileStream.Write(dllBytes, 0, dllBytes.Length); + // Clear cache FileCache.Clear(); + // Log success LILogger.Info("Update complete"); onSuccess(); }