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
{
#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
// 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?
@ -79,8 +66,18 @@ namespace Bloxstrap
"By default, two mod presets are provided for restoring the old death\n" +
"sound and the old mouse cursor.\n";
// TODO: reduce reliance on event handlers for signalling property changes to the bootstrapper dialog
// i mean, chances are we can just use IBootstrapperDialog now?
private static readonly HttpClient Client = new();
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;
#endregion
@ -498,7 +495,7 @@ namespace Bloxstrap
string relativeFile = file.Substring(modFolder.Length + 1);
// ignore files placed in the root directory
if (!relativeFile.Contains(@"\"))
if (!relativeFile.Contains('\\'))
continue;
modFolderFiles.Add(relativeFile);
@ -554,7 +551,7 @@ namespace Bloxstrap
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);

View File

@ -7,7 +7,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
{
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 int _progressValue { get; set; }
protected virtual bool _cancelEnabled { get; set; }
@ -18,7 +18,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
set
{
if (this.InvokeRequired)
this.Invoke(new Action(() => { Message = value; }));
this.Invoke(new Action(() => { _message = value; }));
else
_message = value;
}
@ -30,7 +30,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
set
{
if (this.InvokeRequired)
this.Invoke(new Action(() => { ProgressStyle = value; }));
this.Invoke(new Action(() => { _progressStyle = value; }));
else
_progressStyle = value;
}
@ -42,7 +42,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
set
{
if (this.InvokeRequired)
this.Invoke(new Action(() => { ProgressValue = value; }));
this.Invoke(new Action(() => { _progressValue = value; }));
else
_progressValue = value;
}
@ -54,7 +54,7 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
set
{
if (this.InvokeRequired)
this.Invoke(new Action(() => { CancelEnabled = value; }));
this.Invoke(new Action(() => { _cancelEnabled = value; }));
else
_cancelEnabled = value;
}

View File

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

View File

@ -1,4 +1,4 @@
using Newtonsoft.Json.Linq;
using Bloxstrap.Models;
using DiscordRPC;
namespace Bloxstrap.Helpers.Integrations
@ -9,22 +9,19 @@ namespace Bloxstrap.Helpers.Integrations
public async Task<bool> SetPresence(string placeId)
{
string placeName;
string placeThumbnail;
string creatorName;
// null checking could probably be a lot more concrete here
JObject placeInfo = await Utilities.GetJson($"https://economy.roblox.com/v2/assets/{placeId}/details");
var placeInfo = await Utilities.GetJson<RobloxAsset>($"https://economy.roblox.com/v2/assets/{placeId}/details");
placeName = placeInfo["Name"].Value<string>();
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)
if (placeInfo is null || placeInfo.Creator is null)
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;
@ -50,14 +47,14 @@ namespace Bloxstrap.Helpers.Integrations
RichPresence.SetPresence(new RichPresence()
{
Details = placeName,
State = $"by {creatorName}",
Details = placeInfo.Name,
State = $"by {placeInfo.Creator.Name}",
Timestamps = new Timestamps() { Start = DateTime.UtcNow },
Buttons = buttons,
Assets = new Assets()
{
LargeImageKey = placeThumbnail,
LargeImageText = placeName,
LargeImageText = placeInfo.Name,
SmallImageKey = "roblox",
SmallImageText = "Roblox"
}

View File

@ -5,6 +5,8 @@ using System.Net.Http;
using Newtonsoft.Json.Linq;
using Bloxstrap.Models;
namespace Bloxstrap.Helpers.Integrations
{
internal class RbxFpsUnlocker
@ -35,9 +37,7 @@ namespace Bloxstrap.Helpers.Integrations
if (!Program.Settings.RFUEnabled)
{
if (Directory.Exists(folderLocation))
{
Directory.Delete(folderLocation, true);
}
return;
}
@ -45,20 +45,13 @@ namespace Bloxstrap.Helpers.Integrations
DateTime lastReleasePublish;
string downloadUrl;
try
{
JObject releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{ProjectRepository}/releases/latest");
var releaseInfo = await Utilities.GetJson<GithubRelease>($"https://api.github.com/repos/{ProjectRepository}/releases/latest");
// so... rbxfpsunlocker does not actually have any version info for the executable
// 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})");
if (releaseInfo is null || releaseInfo.CreatedAt is null || releaseInfo.Assets is null)
return;
}
lastReleasePublish = DateTime.Parse(releaseInfo.CreatedAt);
downloadUrl = releaseInfo.Assets[0].BrowserDownloadUrl;
Directory.CreateDirectory(folderLocation);
@ -79,9 +72,9 @@ namespace Bloxstrap.Helpers.Integrations
{
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);
}
}

View File

@ -4,16 +4,11 @@ namespace Bloxstrap.Helpers.RSMM
{
internal class Package
{
public string Name { get; set; }
public string Signature { get; set; }
public string Name { get; set; } = "";
public string Signature { get; set; } = "";
public int PackedSize { 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()
{
return $"[{Signature}] {Name}";

View File

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

View File

@ -2,9 +2,7 @@
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text.Json;
namespace Bloxstrap.Helpers
{
@ -15,14 +13,14 @@ namespace Bloxstrap.Helpers
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())
{
client.DefaultRequestHeaders.Add("User-Agent", Program.ProjectRepository);
string jsonString = await client.GetStringAsync(url);
return (JObject)JsonConvert.DeserializeObject(jsonString);
string json = await client.GetStringAsync(url);
return JsonSerializer.Deserialize<T>(json);
}
}
@ -47,7 +45,7 @@ namespace Bloxstrap.Helpers
string substr = subject.Substring(subject.LastIndexOf(key) + key.Length);
if (substr.IndexOf(delimiter) == -1)
if (!substr.Contains(delimiter))
return null;
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 Microsoft.Win32;
using Bloxstrap.Helpers;
using Bloxstrap.Models;
namespace Bloxstrap
{
@ -27,8 +29,9 @@ namespace Bloxstrap
public static string LocalAppData { get; private set; } = "";
public static string StartMenu { get; private set; } = "";
public static SettingsFormat Settings;
public static SettingsManager SettingsManager = new();
public static SettingsFormat Settings = SettingsManager.Settings;
public static void ShowMessageBox(MessageBoxIcon icon, string message)
{

View File

@ -2,36 +2,18 @@
using System.IO;
using System.Text.Json;
using Bloxstrap.Enums;
using Bloxstrap.Models;
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 SettingsFormat Settings = new();
public bool ShouldSave = false;
private bool IsSaving = false;
private string _saveLocation;
public string SaveLocation
private string? _saveLocation;
public string? SaveLocation
{
get => _saveLocation;
@ -51,7 +33,12 @@ namespace Bloxstrap
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)
{
@ -79,7 +66,7 @@ namespace Bloxstrap
string SettingsJson = JsonSerializer.Serialize(Settings, new JsonSerializerOptions { WriteIndented = true });
Debug.WriteLine(SettingsJson);
if (!ShouldSave)
if (!ShouldSave || SaveLocation is null)
{
Debug.WriteLine("ShouldSave set to false, not saving...");
return;