This repository has been archived on 2025-06-05. You can view files and clone it, but cannot push or open issues or pull requests.
roblox-patcher/RobloxLegacy/VersionManager.cs

110 lines
3.5 KiB
C#

using System.Diagnostics;
using Newtonsoft.Json;
using RobloxLegacy.AppData;
using RobloxLegacy.Utilities;
using ICSharpCode.SharpZipLib.Zip;
namespace RobloxLegacy;
public class VersionData
{
[JsonProperty("version")]
public required string Version { get; set; }
[JsonProperty("clientVersionUpload")]
public required string UploadHash { get; set; }
}
public class VersionManager : IDisposable
{
private static readonly HttpClient Client = new();
private const string CdnUrl = "https://setup.rbxcdn.com";
private string? _currentVersion;
private readonly string _tempPath = Path.Combine(Path.GetTempPath(), $"RobloxLegacy.{Guid.NewGuid().ToString()}");
private readonly IAppData _appData;
public VersionManager(IAppData appData)
{
Directory.CreateDirectory(_tempPath);
_currentVersion = Registry.GetVersion(appData.PackageName);
_appData = appData;
}
private static string GetVersionPath(string version)
{
var localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
return Path.Combine(localAppDataPath, "Roblox", "Versions", version);
}
private async Task<VersionData?> GetLatestVersion()
{
var url = $"https://clientsettings.roblox.com/v2/client-version/{_appData.PackageName}/channel/LIVE";
var response = await Client.GetAsync(url);
if (!response.IsSuccessStatusCode) // just to be safe
return null;
var version = await response.Content.ReadAsAsync<VersionData>();
return version;
}
private static void ExtractBundle(string version, string folder, string tempFile)
{
var fastZip = new FastZip();
var extractPath = Path.Combine(GetVersionPath(version), folder);
fastZip.ExtractZip(tempFile, extractPath, null);
}
public async Task InstallPackage()
{
var version = await GetLatestVersion();
if (version == null)
throw new Exception("No version data found");
if (version.UploadHash == _currentVersion)
return;
Logger.Info($"Installing {_appData.PackageName} version {version.Version}");
foreach (var file in _appData.PackageFiles)
{
try
{
var fileName = $"{version.UploadHash}-{file.Key}";
var fileBytes = await Client.GetByteArrayAsync($"{CdnUrl}/{fileName}");
var zipPath = Path.Combine(_tempPath, fileName);
await File.WriteAllBytesAsync(zipPath, fileBytes);
ExtractBundle(version.UploadHash, file.Value, zipPath);
}
catch (HttpRequestException)
{
Logger.Error($"Failed to download {file.Key}");
}
}
_currentVersion = version.UploadHash;
Registry.SaveVersion(_appData.PackageName, version.UploadHash);
}
public void LaunchApp()
{
Logger.Info($"Launching {_appData.PackageName}...");
if(string.IsNullOrEmpty(_currentVersion))
throw new Exception("No version data found");
var startInfo = new ProcessStartInfo()
{
FileName = _appData.ExecutableName,
WorkingDirectory = GetVersionPath(_currentVersion),
UseShellExecute = true
};
Process.Start(startInfo);
}
public void Dispose()
{
Directory.Delete(_tempPath, true);
GC.SuppressFinalize(this);
}
}