Use static JSON models and some cleanup

This commit is contained in:
pizzaboxer 2022-08-22 21:55:07 +01:00
parent 0da759d1f4
commit 3e42c7511a
14 changed files with 157 additions and 111 deletions

View File

@ -16,19 +16,6 @@ namespace Bloxstrap
public partial class Bootstrapper public partial class Bootstrapper
{ {
#region Properties #region Properties
private string? LaunchCommandLine;
private string VersionGuid;
private PackageManifest VersionPackageManifest;
private string VersionFolder;
private readonly bool FreshInstall;
private int ProgressIncrement;
private bool CancelFired = false;
private static readonly HttpClient Client = new();
// in case a new package is added, you can find the corresponding directory // in case a new package is added, you can find the corresponding directory
// by opening the stock bootstrapper in a hex editor // by opening the stock bootstrapper in a hex editor
// TODO - there ideally should be a less static way to do this that's not hardcoded? // TODO - there ideally should be a less static way to do this that's not hardcoded?
@ -79,8 +66,18 @@ namespace Bloxstrap
"By default, two mod presets are provided for restoring the old death\n" + "By default, two mod presets are provided for restoring the old death\n" +
"sound and the old mouse cursor.\n"; "sound and the old mouse cursor.\n";
// TODO: reduce reliance on event handlers for signalling property changes to the bootstrapper dialog private static readonly HttpClient Client = new();
// i mean, chances are we can just use IBootstrapperDialog now?
private string? LaunchCommandLine;
private string VersionGuid;
private PackageManifest VersionPackageManifest;
private string VersionFolder;
private readonly bool FreshInstall;
private int ProgressIncrement;
private bool CancelFired = false;
public IBootstrapperDialog Dialog; public IBootstrapperDialog Dialog;
#endregion #endregion
@ -498,7 +495,7 @@ namespace Bloxstrap
string relativeFile = file.Substring(modFolder.Length + 1); string relativeFile = file.Substring(modFolder.Length + 1);
// ignore files placed in the root directory // ignore files placed in the root directory
if (!relativeFile.Contains(@"\")) if (!relativeFile.Contains('\\'))
continue; continue;
modFolderFiles.Add(relativeFile); modFolderFiles.Add(relativeFile);
@ -554,7 +551,7 @@ namespace Bloxstrap
File.WriteAllLines(manifestFile, modFolderFiles); File.WriteAllLines(manifestFile, modFolderFiles);
} }
private void CheckModPreset(bool condition, string location, string base64Contents) private static void CheckModPreset(bool condition, string location, string base64Contents)
{ {
string modFolderLocation = Path.Combine(Directories.Modifications, location); string modFolderLocation = Path.Combine(Directories.Modifications, location);

View File

@ -7,7 +7,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
{ {
public Bootstrapper? Bootstrapper { get; set; } public Bootstrapper? Bootstrapper { get; set; }
protected virtual string _message { get; set; } protected virtual string _message { get; set; } = "Please wait...";
protected virtual ProgressBarStyle _progressStyle { get; set; } protected virtual ProgressBarStyle _progressStyle { get; set; }
protected virtual int _progressValue { get; set; } protected virtual int _progressValue { get; set; }
protected virtual bool _cancelEnabled { get; set; } protected virtual bool _cancelEnabled { get; set; }
@ -18,7 +18,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
set set
{ {
if (this.InvokeRequired) if (this.InvokeRequired)
this.Invoke(new Action(() => { Message = value; })); this.Invoke(new Action(() => { _message = value; }));
else else
_message = value; _message = value;
} }
@ -30,7 +30,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
set set
{ {
if (this.InvokeRequired) if (this.InvokeRequired)
this.Invoke(new Action(() => { ProgressStyle = value; })); this.Invoke(new Action(() => { _progressStyle = value; }));
else else
_progressStyle = value; _progressStyle = value;
} }
@ -42,7 +42,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
set set
{ {
if (this.InvokeRequired) if (this.InvokeRequired)
this.Invoke(new Action(() => { ProgressValue = value; })); this.Invoke(new Action(() => { _progressValue = value; }));
else else
_progressValue = value; _progressValue = value;
} }
@ -54,7 +54,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
set set
{ {
if (this.InvokeRequired) if (this.InvokeRequired)
this.Invoke(new Action(() => { CancelEnabled = value; })); this.Invoke(new Action(() => { _cancelEnabled = value; }));
else else
_cancelEnabled = value; _cancelEnabled = value;
} }

View File

@ -37,7 +37,7 @@ namespace Bloxstrap.Dialogs
private BootstrapperStyle SelectedStyle private BootstrapperStyle SelectedStyle
{ {
get => (BootstrapperStyle)_selectedStyle; get => _selectedStyle ?? BootstrapperStyle.ProgressDialog;
set set
{ {
@ -53,7 +53,7 @@ namespace Bloxstrap.Dialogs
private BootstrapperIcon SelectedIcon private BootstrapperIcon SelectedIcon
{ {
get => (BootstrapperIcon)_selectedIcon; get => _selectedIcon ?? BootstrapperIcon.IconBloxstrap;
set set
{ {

View File

@ -1,4 +1,4 @@
using Newtonsoft.Json.Linq; using Bloxstrap.Models;
using DiscordRPC; using DiscordRPC;
namespace Bloxstrap.Helpers.Integrations namespace Bloxstrap.Helpers.Integrations
@ -9,22 +9,19 @@ namespace Bloxstrap.Helpers.Integrations
public async Task<bool> SetPresence(string placeId) public async Task<bool> SetPresence(string placeId)
{ {
string placeName;
string placeThumbnail; string placeThumbnail;
string creatorName;
// null checking could probably be a lot more concrete here var placeInfo = await Utilities.GetJson<RobloxAsset>($"https://economy.roblox.com/v2/assets/{placeId}/details");
JObject placeInfo = await Utilities.GetJson($"https://economy.roblox.com/v2/assets/{placeId}/details");
placeName = placeInfo["Name"].Value<string>(); if (placeInfo is null || placeInfo.Creator is null)
creatorName = placeInfo["Creator"]["Name"].Value<string>();
JObject thumbnailInfo = await Utilities.GetJson($"https://thumbnails.roblox.com/v1/places/gameicons?placeIds={placeId}&returnPolicy=PlaceHolder&size=512x512&format=Png&isCircular=false");
if (thumbnailInfo["data"] is null)
return false; return false;
placeThumbnail = thumbnailInfo["data"][0]["imageUrl"].Value<string>(); var thumbnailInfo = await Utilities.GetJson<RobloxThumbnails>($"https://thumbnails.roblox.com/v1/places/gameicons?placeIds={placeId}&returnPolicy=PlaceHolder&size=512x512&format=Png&isCircular=false");
if (thumbnailInfo is null)
placeThumbnail = "roblox"; //fallback
else
placeThumbnail = thumbnailInfo.Data[0].ImageUrl;
DiscordRPC.Button[]? buttons = null; DiscordRPC.Button[]? buttons = null;
@ -50,14 +47,14 @@ namespace Bloxstrap.Helpers.Integrations
RichPresence.SetPresence(new RichPresence() RichPresence.SetPresence(new RichPresence()
{ {
Details = placeName, Details = placeInfo.Name,
State = $"by {creatorName}", State = $"by {placeInfo.Creator.Name}",
Timestamps = new Timestamps() { Start = DateTime.UtcNow }, Timestamps = new Timestamps() { Start = DateTime.UtcNow },
Buttons = buttons, Buttons = buttons,
Assets = new Assets() Assets = new Assets()
{ {
LargeImageKey = placeThumbnail, LargeImageKey = placeThumbnail,
LargeImageText = placeName, LargeImageText = placeInfo.Name,
SmallImageKey = "roblox", SmallImageKey = "roblox",
SmallImageText = "Roblox" SmallImageText = "Roblox"
} }

View File

@ -5,6 +5,8 @@ using System.Net.Http;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Bloxstrap.Models;
namespace Bloxstrap.Helpers.Integrations namespace Bloxstrap.Helpers.Integrations
{ {
internal class RbxFpsUnlocker internal class RbxFpsUnlocker
@ -35,9 +37,7 @@ namespace Bloxstrap.Helpers.Integrations
if (!Program.Settings.RFUEnabled) if (!Program.Settings.RFUEnabled)
{ {
if (Directory.Exists(folderLocation)) if (Directory.Exists(folderLocation))
{
Directory.Delete(folderLocation, true); Directory.Delete(folderLocation, true);
}
return; return;
} }
@ -45,20 +45,13 @@ namespace Bloxstrap.Helpers.Integrations
DateTime lastReleasePublish; DateTime lastReleasePublish;
string downloadUrl; string downloadUrl;
try var releaseInfo = await Utilities.GetJson<GithubRelease>($"https://api.github.com/repos/{ProjectRepository}/releases/latest");
{
JObject releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{ProjectRepository}/releases/latest");
// so... rbxfpsunlocker does not actually have any version info for the executable if (releaseInfo is null || releaseInfo.CreatedAt is null || releaseInfo.Assets is null)
// meaning the best way we can check for a new version is comparing time last download to time last release published
lastReleasePublish = DateTime.Parse(releaseInfo["created_at"].Value<string>());
downloadUrl = releaseInfo["assets"][0]["browser_download_url"].Value<string>();
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to fetch latest version info! ({ex.Message})");
return; return;
}
lastReleasePublish = DateTime.Parse(releaseInfo.CreatedAt);
downloadUrl = releaseInfo.Assets[0].BrowserDownloadUrl;
Directory.CreateDirectory(folderLocation); Directory.CreateDirectory(folderLocation);
@ -79,9 +72,9 @@ namespace Bloxstrap.Helpers.Integrations
{ {
byte[] bytes = await client.GetByteArrayAsync(downloadUrl); byte[] bytes = await client.GetByteArrayAsync(downloadUrl);
using (MemoryStream zipStream = new MemoryStream(bytes)) using (MemoryStream zipStream = new(bytes))
{ {
ZipArchive zip = new ZipArchive(zipStream); ZipArchive zip = new(zipStream);
zip.ExtractToDirectory(folderLocation, true); zip.ExtractToDirectory(folderLocation, true);
} }
} }

View File

@ -4,16 +4,11 @@ namespace Bloxstrap.Helpers.RSMM
{ {
internal class Package internal class Package
{ {
public string Name { get; set; } public string Name { get; set; } = "";
public string Signature { get; set; } public string Signature { get; set; } = "";
public int PackedSize { get; set; } public int PackedSize { get; set; }
public int Size { get; set; } public int Size { get; set; }
public bool Exists { get; set; }
public bool ShouldInstall { get; set; }
internal byte[] Data { get; set; }
public override string ToString() public override string ToString()
{ {
return $"[{Signature}] {Name}"; return $"[{Signature}] {Name}";

View File

@ -1,8 +1,12 @@
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net.Http;
using System.Text.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Bloxstrap.Models;
namespace Bloxstrap.Helpers namespace Bloxstrap.Helpers
{ {
public class Updater public class Updater
@ -52,20 +56,13 @@ namespace Bloxstrap.Helpers
string latestVersion; string latestVersion;
string releaseNotes; string releaseNotes;
// get the latest version according to the latest github release info var releaseInfo = await Utilities.GetJson<GithubRelease>($"https://api.github.com/repos/{Program.ProjectRepository}/releases/latest");
// it should contain the latest product version, which we can check against
try
{
JObject releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{Program.ProjectRepository}/releases/latest");
latestVersion = releaseInfo["name"].Value<string>(); if (releaseInfo is null || releaseInfo.Name is null || releaseInfo.Body is null)
releaseNotes = releaseInfo["body"].Value<string>();
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to fetch latest version info! ({ex.Message})");
return; return;
}
latestVersion = releaseInfo.Name;
releaseNotes = releaseInfo.Body;
if (currentVersion != latestVersion) if (currentVersion != latestVersion)
{ {

View File

@ -2,9 +2,7 @@
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Bloxstrap.Helpers namespace Bloxstrap.Helpers
{ {
@ -15,14 +13,14 @@ namespace Bloxstrap.Helpers
Process.Start(new ProcessStartInfo { FileName = website, UseShellExecute = true }); Process.Start(new ProcessStartInfo { FileName = website, UseShellExecute = true });
} }
public static async Task<JObject> GetJson(string url) public static async Task<T?> GetJson<T>(string url)
{ {
using (HttpClient client = new()) using (HttpClient client = new())
{ {
client.DefaultRequestHeaders.Add("User-Agent", Program.ProjectRepository); client.DefaultRequestHeaders.Add("User-Agent", Program.ProjectRepository);
string jsonString = await client.GetStringAsync(url); string json = await client.GetStringAsync(url);
return (JObject)JsonConvert.DeserializeObject(jsonString); return JsonSerializer.Deserialize<T>(json);
} }
} }
@ -47,7 +45,7 @@ namespace Bloxstrap.Helpers
string substr = subject.Substring(subject.LastIndexOf(key) + key.Length); string substr = subject.Substring(subject.LastIndexOf(key) + key.Length);
if (substr.IndexOf(delimiter) == -1) if (!substr.Contains(delimiter))
return null; return null;
return substr.Split(delimiter)[0]; return substr.Split(delimiter)[0];

View File

@ -0,0 +1,25 @@
using System.Text.Json.Serialization;
namespace Bloxstrap.Models
{
public class GithubRelease
{
[JsonPropertyName("name")]
public string? Name { get; set; }
[JsonPropertyName("body")]
public string? Body { get; set; }
[JsonPropertyName("created_at")]
public string? CreatedAt { get; set; }
[JsonPropertyName("assets")]
public List<GithubReleaseAsset>? Assets { get; set; }
}
public class GithubReleaseAsset
{
[JsonPropertyName("browser_download_url")]
public string? BrowserDownloadUrl { get; set; }
}
}

View File

@ -0,0 +1,13 @@
namespace Bloxstrap.Models
{
public class RobloxAsset
{
public string? Name { get; set; }
public RobloxAssetCreator? Creator { get; set; }
}
public class RobloxAssetCreator
{
public string? Name { get; set; }
}
}

View File

@ -0,0 +1,16 @@
using System.Text.Json.Serialization;
namespace Bloxstrap.Models
{
public class RobloxThumbnails
{
[JsonPropertyName("data")]
public List<RobloxThumbnail>? Data { get; set; }
}
public class RobloxThumbnail
{
[JsonPropertyName("imageUrl")]
public string? ImageUrl { get; set; }
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Bloxstrap.Enums;
namespace Bloxstrap.Models
{
public class SettingsFormat
{
public string VersionGuid { get; set; } = "";
public bool CheckForUpdates { get; set; } = true;
public BootstrapperStyle BootstrapperStyle { get; set; } = BootstrapperStyle.ProgressDialog;
public BootstrapperIcon BootstrapperIcon { get; set; } = BootstrapperIcon.IconBloxstrap;
public bool UseDiscordRichPresence { get; set; } = true;
public bool HideRPCButtons { get; set; } = false;
public bool RFUEnabled { get; set; } = false;
public bool RFUAutoclose { get; set; } = false;
public bool UseOldDeathSound { get; set; } = true;
public bool UseOldMouseCursor { get; set; } = false;
}
}

View File

@ -2,7 +2,9 @@ using System.Diagnostics;
using System.IO; using System.IO;
using Microsoft.Win32; using Microsoft.Win32;
using Bloxstrap.Helpers; using Bloxstrap.Helpers;
using Bloxstrap.Models;
namespace Bloxstrap namespace Bloxstrap
{ {
@ -27,8 +29,9 @@ namespace Bloxstrap
public static string LocalAppData { get; private set; } = ""; public static string LocalAppData { get; private set; } = "";
public static string StartMenu { get; private set; } = ""; public static string StartMenu { get; private set; } = "";
public static SettingsFormat Settings;
public static SettingsManager SettingsManager = new(); public static SettingsManager SettingsManager = new();
public static SettingsFormat Settings = SettingsManager.Settings;
public static void ShowMessageBox(MessageBoxIcon icon, string message) public static void ShowMessageBox(MessageBoxIcon icon, string message)
{ {

View File

@ -2,36 +2,18 @@
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;
using Bloxstrap.Enums; using Bloxstrap.Models;
namespace Bloxstrap namespace Bloxstrap
{ {
public class SettingsFormat
{
public string VersionGuid { get; set; }
public bool CheckForUpdates { get; set; } = true;
public BootstrapperStyle BootstrapperStyle { get; set; } = BootstrapperStyle.ProgressDialog;
public BootstrapperIcon BootstrapperIcon { get; set; } = BootstrapperIcon.IconBloxstrap;
public bool UseDiscordRichPresence { get; set; } = true;
public bool HideRPCButtons { get; set; } = false;
public bool RFUEnabled { get; set; } = false;
public bool RFUAutoclose { get; set; } = false;
public bool UseOldDeathSound { get; set; } = true;
public bool UseOldMouseCursor { get; set; } = false;
}
public class SettingsManager public class SettingsManager
{ {
public SettingsFormat Settings = new(); public SettingsFormat Settings = new();
public bool ShouldSave = false; public bool ShouldSave = false;
private bool IsSaving = false; private bool IsSaving = false;
private string _saveLocation; private string? _saveLocation;
public string SaveLocation public string? SaveLocation
{ {
get => _saveLocation; get => _saveLocation;
@ -51,7 +33,12 @@ namespace Bloxstrap
try try
{ {
Settings = JsonSerializer.Deserialize<SettingsFormat>(settingsJson); var settings = JsonSerializer.Deserialize<SettingsFormat>(settingsJson);
if (settings is null)
throw new Exception("Deserialization returned null");
Settings = settings;
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -79,7 +66,7 @@ namespace Bloxstrap
string SettingsJson = JsonSerializer.Serialize(Settings, new JsonSerializerOptions { WriteIndented = true }); string SettingsJson = JsonSerializer.Serialize(Settings, new JsonSerializerOptions { WriteIndented = true });
Debug.WriteLine(SettingsJson); Debug.WriteLine(SettingsJson);
if (!ShouldSave) if (!ShouldSave || SaveLocation is null)
{ {
Debug.WriteLine("ShouldSave set to false, not saving..."); Debug.WriteLine("ShouldSave set to false, not saving...");
return; return;