using System.Text.Json.Serialization; using System.IO.Compression; using RobloxLegacy.AppData; using RobloxLegacy.Utilities; namespace RobloxLegacy; public abstract class VersionData { [JsonPropertyName("version")] public required string Version { get; set; } [JsonPropertyName("clientVersionUpload")] public required string UploadHash { get; set; } } public class VersionManager(IAppData appData) { private static readonly HttpClient Client = new(); private const string CdnUrl = "https://setup.rbxcdn.com"; private static string GetVersionPath(string version) { var localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); return Path.Combine(localAppDataPath, "Roblox", "Versions", version); } private async Task GetLatestVersion() { var url = $"https://clientsettings.roblox.com/v2/client-version/{appData.Name}/channel/LIVE"; var response = await Client.GetAsync(url); if(!response.IsSuccessStatusCode) // just to be safe return null; var version = await response.Content.ReadAsAsync(); return version; } private static void ExtractBundle(string version, string folder, Stream file) { var extractPath = Path.Combine(GetVersionPath(version), folder); ZipFile.ExtractToDirectory(file, extractPath); } public async Task InstallPackage() { var version = await GetLatestVersion(); if(version == null) throw new Exception("No version data found"); Logger.Log($"Installing {appData.Name} version {version.Version}"); foreach (var file in appData.PackageFiles) { var fileName = $"{version.UploadHash}-{file.Key}"; var fileStream = await Client.GetStreamAsync($"{CdnUrl}/{fileName}"); ExtractBundle(version.UploadHash, file.Value, fileStream); } } }