mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
Merge branch 'main' into user-pfp-discord-rpc
This commit is contained in:
commit
3510730a6e
@ -110,22 +110,24 @@ namespace Bloxstrap
|
|||||||
public static async Task<GithubRelease?> GetLatestRelease()
|
public static async Task<GithubRelease?> GetLatestRelease()
|
||||||
{
|
{
|
||||||
const string LOG_IDENT = "App::GetLatestRelease";
|
const string LOG_IDENT = "App::GetLatestRelease";
|
||||||
|
|
||||||
GithubRelease? releaseInfo = null;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
releaseInfo = await Http.GetJson<GithubRelease>($"https://api.github.com/repos/{ProjectRepository}/releases/latest");
|
var releaseInfo = await Http.GetJson<GithubRelease>($"https://api.github.com/repos/{ProjectRepository}/releases/latest");
|
||||||
|
|
||||||
if (releaseInfo is null || releaseInfo.Assets is null)
|
if (releaseInfo is null || releaseInfo.Assets is null)
|
||||||
|
{
|
||||||
Logger.WriteLine(LOG_IDENT, "Encountered invalid data");
|
Logger.WriteLine(LOG_IDENT, "Encountered invalid data");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return releaseInfo;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.WriteException(LOG_IDENT, ex);
|
Logger.WriteException(LOG_IDENT, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return releaseInfo;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStartup(StartupEventArgs e)
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
|
13
Bloxstrap/Exceptions/InvalidHTTPResponseException.cs
Normal file
13
Bloxstrap/Exceptions/InvalidHTTPResponseException.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Bloxstrap.Exceptions
|
||||||
|
{
|
||||||
|
internal class InvalidHTTPResponseException : Exception
|
||||||
|
{
|
||||||
|
public InvalidHTTPResponseException(string message) : base(message) { }
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
namespace Bloxstrap.Integrations
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace Bloxstrap.Integrations
|
||||||
{
|
{
|
||||||
public class ActivityWatcher : IDisposable
|
public class ActivityWatcher : IDisposable
|
||||||
{
|
{
|
||||||
@ -388,21 +390,19 @@
|
|||||||
string location = "";
|
string location = "";
|
||||||
var ipInfo = await Http.GetJson<IPInfoResponse>($"https://ipinfo.io/{Data.MachineAddress}/json");
|
var ipInfo = await Http.GetJson<IPInfoResponse>($"https://ipinfo.io/{Data.MachineAddress}/json");
|
||||||
|
|
||||||
if (ipInfo is null)
|
if (String.IsNullOrEmpty(ipInfo.City))
|
||||||
return $"? ({Strings.ActivityTracker_LookupFailed})";
|
throw new InvalidHTTPResponseException("Reported city was blank");
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(ipInfo.Country))
|
if (ipInfo.City == ipInfo.Region)
|
||||||
location = "?";
|
|
||||||
else if (ipInfo.City == ipInfo.Region)
|
|
||||||
location = $"{ipInfo.Region}, {ipInfo.Country}";
|
location = $"{ipInfo.Region}, {ipInfo.Country}";
|
||||||
else
|
else
|
||||||
location = $"{ipInfo.City}, {ipInfo.Region}, {ipInfo.Country}";
|
location = $"{ipInfo.City}, {ipInfo.Region}, {ipInfo.Country}";
|
||||||
|
|
||||||
if (!InGame)
|
|
||||||
return $"? ({Strings.ActivityTracker_LeftGame})";
|
|
||||||
|
|
||||||
GeolocationCache[Data.MachineAddress] = location;
|
GeolocationCache[Data.MachineAddress] = location;
|
||||||
|
|
||||||
|
if (!InGame)
|
||||||
|
return "";
|
||||||
|
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -410,7 +410,9 @@
|
|||||||
App.Logger.WriteLine(LOG_IDENT, $"Failed to get server location for {Data.MachineAddress}");
|
App.Logger.WriteLine(LOG_IDENT, $"Failed to get server location for {Data.MachineAddress}");
|
||||||
App.Logger.WriteException(LOG_IDENT, ex);
|
App.Logger.WriteException(LOG_IDENT, ex);
|
||||||
|
|
||||||
return $"? ({Strings.ActivityTracker_LookupFailed})";
|
Frontend.ShowMessageBox($"{Strings.ActivityWatcher_LocationQueryFailed}\n\n{ex.Message}", MessageBoxImage.Warning);
|
||||||
|
|
||||||
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Windows;
|
||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
|
|
||||||
namespace Bloxstrap.Integrations
|
namespace Bloxstrap.Integrations
|
||||||
@ -206,18 +207,22 @@ namespace Bloxstrap.Integrations
|
|||||||
timeStarted = activity.RootActivity.TimeJoined;
|
timeStarted = activity.RootActivity.TimeJoined;
|
||||||
|
|
||||||
if (activity.UniverseDetails is null)
|
if (activity.UniverseDetails is null)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await UniverseDetails.FetchSingle(activity.UniverseId);
|
await UniverseDetails.FetchSingle(activity.UniverseId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
App.Logger.WriteException(LOG_IDENT, ex);
|
||||||
|
Frontend.ShowMessageBox($"{Strings.ActivityWatcher_RichPresenceLoadFailed}\n\n{ex.Message}", MessageBoxImage.Warning);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
activity.UniverseDetails = UniverseDetails.LoadFromCache(activity.UniverseId);
|
activity.UniverseDetails = UniverseDetails.LoadFromCache(activity.UniverseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
var universeDetails = activity.UniverseDetails;
|
var universeDetails = activity.UniverseDetails!;
|
||||||
|
|
||||||
if (universeDetails is null)
|
|
||||||
{
|
|
||||||
Frontend.ShowMessageBox(Strings.ActivityTracker_RichPresenceLoadFailed, System.Windows.MessageBoxImage.Warning);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
icon = universeDetails.Thumbnail.ImageUrl;
|
icon = universeDetails.Thumbnail.ImageUrl;
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ namespace Bloxstrap
|
|||||||
message = Strings.JsonManager_FastFlagsLoadFailed;
|
message = Strings.JsonManager_FastFlagsLoadFailed;
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(message))
|
if (!String.IsNullOrEmpty(message))
|
||||||
Frontend.ShowMessageBox($"{message}\n\n{ex.GetType()}: {ex.Message}", System.Windows.MessageBoxImage.Warning);
|
Frontend.ShowMessageBox($"{message}\n\n{ex.Message}", System.Windows.MessageBoxImage.Warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
|
@ -21,17 +21,19 @@
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<bool> FetchSingle(long id) => FetchBulk(id.ToString());
|
public static Task FetchSingle(long id) => FetchBulk(id.ToString());
|
||||||
|
|
||||||
public static async Task<bool> FetchBulk(string ids)
|
public static async Task FetchBulk(string ids)
|
||||||
{
|
{
|
||||||
var gameDetailResponse = await Http.GetJson<ApiArrayResponse<GameDetailResponse>>($"https://games.roblox.com/v1/games?universeIds={ids}");
|
var gameDetailResponse = await Http.GetJson<ApiArrayResponse<GameDetailResponse>>($"https://games.roblox.com/v1/games?universeIds={ids}");
|
||||||
if (gameDetailResponse is null || !gameDetailResponse.Data.Any())
|
|
||||||
return false;
|
if (!gameDetailResponse.Data.Any())
|
||||||
|
throw new InvalidHTTPResponseException("Roblox API for Game Details returned invalid data");
|
||||||
|
|
||||||
var universeThumbnailResponse = await Http.GetJson<ApiArrayResponse<ThumbnailResponse>>($"https://thumbnails.roblox.com/v1/games/icons?universeIds={ids}&returnPolicy=PlaceHolder&size=128x128&format=Png&isCircular=false");
|
var universeThumbnailResponse = await Http.GetJson<ApiArrayResponse<ThumbnailResponse>>($"https://thumbnails.roblox.com/v1/games/icons?universeIds={ids}&returnPolicy=PlaceHolder&size=128x128&format=Png&isCircular=false");
|
||||||
if (universeThumbnailResponse is null || !universeThumbnailResponse.Data.Any())
|
|
||||||
return false;
|
if (!universeThumbnailResponse.Data.Any())
|
||||||
|
throw new InvalidHTTPResponseException("Roblox API for Game Thumbnails returned invalid data");
|
||||||
|
|
||||||
foreach (string strId in ids.Split(','))
|
foreach (string strId in ids.Split(','))
|
||||||
{
|
{
|
||||||
@ -43,8 +45,6 @@
|
|||||||
Thumbnail = universeThumbnailResponse.Data.Where(x => x.TargetId == id).First(),
|
Thumbnail = universeThumbnailResponse.Data.Where(x => x.TargetId == id).First(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
Bloxstrap/Resources/Strings.Designer.cs
generated
19
Bloxstrap/Resources/Strings.Designer.cs
generated
@ -106,29 +106,20 @@ namespace Bloxstrap.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to left game.
|
/// Looks up a localized string similar to Failed to query server location..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ActivityTracker_LeftGame {
|
public static string ActivityWatcher_LocationQueryFailed {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("ActivityTracker.LeftGame", resourceCulture);
|
return ResourceManager.GetString("ActivityWatcher.LocationQueryFailed", resourceCulture);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to lookup failed.
|
|
||||||
/// </summary>
|
|
||||||
public static string ActivityTracker_LookupFailed {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("ActivityTracker.LookupFailed", resourceCulture);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Your current game will not show on your Discord presence because an error occurred when loading the game information..
|
/// Looks up a localized string similar to Your current game will not show on your Discord presence because an error occurred when loading the game information..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ActivityTracker_RichPresenceLoadFailed {
|
public static string ActivityWatcher_RichPresenceLoadFailed {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("ActivityTracker.RichPresenceLoadFailed", resourceCulture);
|
return ResourceManager.GetString("ActivityWatcher.RichPresenceLoadFailed", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,12 +117,6 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="ActivityTracker.LeftGame" xml:space="preserve">
|
|
||||||
<value>left game</value>
|
|
||||||
</data>
|
|
||||||
<data name="ActivityTracker.LookupFailed" xml:space="preserve">
|
|
||||||
<value>lookup failed</value>
|
|
||||||
</data>
|
|
||||||
<data name="Bootstrapper.AutoUpdateFailed" xml:space="preserve">
|
<data name="Bootstrapper.AutoUpdateFailed" xml:space="preserve">
|
||||||
<value>Bloxstrap was unable to automatically update to version {0}. Please update it manually by downloading and running it from the website.</value>
|
<value>Bloxstrap was unable to automatically update to version {0}. Please update it manually by downloading and running it from the website.</value>
|
||||||
</data>
|
</data>
|
||||||
@ -1177,10 +1171,13 @@ Are you sure you want to continue?</value>
|
|||||||
<data name="ContextMenu.GameHistory.Rejoin" xml:space="preserve">
|
<data name="ContextMenu.GameHistory.Rejoin" xml:space="preserve">
|
||||||
<value>Rejoin</value>
|
<value>Rejoin</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActivityTracker.RichPresenceLoadFailed" xml:space="preserve">
|
<data name="ActivityWatcher.RichPresenceLoadFailed" xml:space="preserve">
|
||||||
<value>Your current game will not show on your Discord presence because an error occurred when loading the game information.</value>
|
<value>Your current game will not show on your Discord presence because an error occurred when loading the game information.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContextMenu.GameHistory.Description" xml:space="preserve">
|
<data name="ContextMenu.GameHistory.Description" xml:space="preserve">
|
||||||
<value>Game history is only recorded for your current Roblox session. Games will appear here as you leave them or teleport within them.</value>
|
<value>Game history is only recorded for your current Roblox session. Games will appear here as you leave them or teleport within them.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ActivityWatcher.LocationQueryFailed" xml:space="preserve">
|
||||||
|
<value>Failed to query server location.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||||
xmlns:models="clr-namespace:Bloxstrap.UI.ViewModels.ContextMenu"
|
xmlns:models="clr-namespace:Bloxstrap.UI.ViewModels.ContextMenu"
|
||||||
xmlns:resources="clr-namespace:Bloxstrap.Resources"
|
xmlns:resources="clr-namespace:Bloxstrap.Resources"
|
||||||
|
xmlns:enums="clr-namespace:Bloxstrap.Enums"
|
||||||
d:DataContext="{d:DesignInstance Type=models:ServerHistoryViewModel}"
|
d:DataContext="{d:DesignInstance Type=models:ServerHistoryViewModel}"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="{x:Static resources:Strings.ContextMenu_GameHistory_Title}"
|
Title="{x:Static resources:Strings.ContextMenu_GameHistory_Title}"
|
||||||
@ -30,11 +31,24 @@
|
|||||||
|
|
||||||
<TextBlock Grid.Row="1" Margin="16,8,16,0" Text="{x:Static resources:Strings.ContextMenu_GameHistory_Description}" TextWrapping="Wrap" />
|
<TextBlock Grid.Row="1" Margin="16,8,16,0" Text="{x:Static resources:Strings.ContextMenu_GameHistory_Description}" TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="2" Margin="16,8,16,0" Text="{Binding Error, Mode=OneWay}" TextWrapping="Wrap">
|
||||||
|
<TextBlock.Style>
|
||||||
|
<Style TargetType="TextBlock">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding LoadState, Mode=OneWay}" Value="{x:Static enums:GenericTriState.Failed}">
|
||||||
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
|
</Style>
|
||||||
|
</TextBlock.Style>
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
<Border Grid.Row="2">
|
<Border Grid.Row="2">
|
||||||
<Border.Style>
|
<Border.Style>
|
||||||
<Style TargetType="Border">
|
<Style TargetType="Border">
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding GameHistory, Mode=OneWay}" Value="{x:Null}">
|
<DataTrigger Binding="{Binding LoadState, Mode=OneWay}" Value="{x:Static enums:GenericTriState.Unknown}">
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
@ -49,11 +63,11 @@
|
|||||||
<ListView.Style>
|
<ListView.Style>
|
||||||
<Style TargetType="ListView" BasedOn="{StaticResource {x:Type ListView}}">
|
<Style TargetType="ListView" BasedOn="{StaticResource {x:Type ListView}}">
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding GameHistory, Mode=OneWay}" Value="{x:Null}">
|
<DataTrigger Binding="{Binding LoadState, Mode=OneWay}" Value="{x:Static enums:GenericTriState.Successful}">
|
||||||
<Setter Property="Visibility" Value="Collapsed" />
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
</Style>
|
</Style>
|
||||||
</ListView.Style>
|
</ListView.Style>
|
||||||
<ListView.ItemTemplate>
|
<ListView.ItemTemplate>
|
||||||
|
@ -60,6 +60,10 @@ namespace Bloxstrap.UI
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
string serverLocation = await _activityWatcher.GetServerLocation();
|
string serverLocation = await _activityWatcher.GetServerLocation();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(serverLocation))
|
||||||
|
return;
|
||||||
|
|
||||||
string title = _activityWatcher.Data.ServerType switch
|
string title = _activityWatcher.Data.ServerType switch
|
||||||
{
|
{
|
||||||
ServerType.Public => Strings.ContextMenu_ServerInformation_Notification_Title_Public,
|
ServerType.Public => Strings.ContextMenu_ServerInformation_Notification_Title_Public,
|
||||||
|
@ -10,6 +10,10 @@ namespace Bloxstrap.UI.ViewModels.ContextMenu
|
|||||||
|
|
||||||
public List<ActivityData>? GameHistory { get; private set; }
|
public List<ActivityData>? GameHistory { get; private set; }
|
||||||
|
|
||||||
|
public GenericTriState LoadState { get; private set; } = GenericTriState.Unknown;
|
||||||
|
|
||||||
|
public string Error { get; private set; } = String.Empty;
|
||||||
|
|
||||||
public ICommand CloseWindowCommand => new RelayCommand(RequestClose);
|
public ICommand CloseWindowCommand => new RelayCommand(RequestClose);
|
||||||
|
|
||||||
public EventHandler? RequestCloseEvent;
|
public EventHandler? RequestCloseEvent;
|
||||||
@ -25,6 +29,9 @@ namespace Bloxstrap.UI.ViewModels.ContextMenu
|
|||||||
|
|
||||||
private async void LoadData()
|
private async void LoadData()
|
||||||
{
|
{
|
||||||
|
LoadState = GenericTriState.Unknown;
|
||||||
|
OnPropertyChanged(nameof(LoadState));
|
||||||
|
|
||||||
var entries = _activityWatcher.History.Where(x => x.UniverseDetails is null);
|
var entries = _activityWatcher.History.Where(x => x.UniverseDetails is null);
|
||||||
|
|
||||||
if (entries.Any())
|
if (entries.Any())
|
||||||
@ -32,8 +39,22 @@ namespace Bloxstrap.UI.ViewModels.ContextMenu
|
|||||||
// TODO: this will duplicate universe ids
|
// TODO: this will duplicate universe ids
|
||||||
string universeIds = String.Join(',', entries.Select(x => x.UniverseId));
|
string universeIds = String.Join(',', entries.Select(x => x.UniverseId));
|
||||||
|
|
||||||
if (!await UniverseDetails.FetchBulk(universeIds))
|
try
|
||||||
|
{
|
||||||
|
await UniverseDetails.FetchBulk(universeIds);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
App.Logger.WriteException("ServerHistoryViewModel::LoadData", ex);
|
||||||
|
|
||||||
|
Error = ex.Message;
|
||||||
|
OnPropertyChanged(nameof(Error));
|
||||||
|
|
||||||
|
LoadState = GenericTriState.Failed;
|
||||||
|
OnPropertyChanged(nameof(LoadState));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var entry in entries)
|
foreach (var entry in entries)
|
||||||
entry.UniverseDetails = UniverseDetails.LoadFromCache(entry.UniverseId);
|
entry.UniverseDetails = UniverseDetails.LoadFromCache(entry.UniverseId);
|
||||||
@ -64,6 +85,9 @@ namespace Bloxstrap.UI.ViewModels.ContextMenu
|
|||||||
}
|
}
|
||||||
|
|
||||||
OnPropertyChanged(nameof(GameHistory));
|
OnPropertyChanged(nameof(GameHistory));
|
||||||
|
|
||||||
|
LoadState = GenericTriState.Successful;
|
||||||
|
OnPropertyChanged(nameof(LoadState));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RequestClose() => RequestCloseEvent?.Invoke(this, EventArgs.Empty);
|
private void RequestClose() => RequestCloseEvent?.Invoke(this, EventArgs.Empty);
|
||||||
|
@ -5,14 +5,6 @@ namespace Bloxstrap
|
|||||||
{
|
{
|
||||||
static class Utilities
|
static class Utilities
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Is process running as administrator
|
|
||||||
/// https://stackoverflow.com/a/11660205
|
|
||||||
/// </summary>
|
|
||||||
public static bool IsAdministrator =>
|
|
||||||
new WindowsPrincipal(WindowsIdentity.GetCurrent())
|
|
||||||
.IsInRole(WindowsBuiltInRole.Administrator);
|
|
||||||
|
|
||||||
public static void ShellExecute(string website)
|
public static void ShellExecute(string website)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -2,22 +2,22 @@
|
|||||||
{
|
{
|
||||||
internal static class Http
|
internal static class Http
|
||||||
{
|
{
|
||||||
public static async Task<T?> GetJson<T>(string url)
|
/// <summary>
|
||||||
|
/// Gets and deserializes a JSON API response to the specified object
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="url"></param>
|
||||||
|
/// <exception cref="HttpRequestException"></exception>
|
||||||
|
/// <exception cref="JsonException"></exception>
|
||||||
|
public static async Task<T> GetJson<T>(string url)
|
||||||
{
|
{
|
||||||
string LOG_IDENT = $"Http::GetJson<{typeof(T).Name}>";
|
var request = await App.HttpClient.GetAsync(url);
|
||||||
|
|
||||||
string json = await App.HttpClient.GetStringAsync(url);
|
request.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
try
|
string json = await request.Content.ReadAsStringAsync();
|
||||||
{
|
|
||||||
return JsonSerializer.Deserialize<T>(json);
|
return JsonSerializer.Deserialize<T>(json)!;
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, $"Failed to deserialize JSON for {url}!");
|
|
||||||
App.Logger.WriteException(LOG_IDENT, ex);
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user