diff --git a/Bloxstrap/GlobalCache.cs b/Bloxstrap/GlobalCache.cs index 69772244..fe28cc08 100644 --- a/Bloxstrap/GlobalCache.cs +++ b/Bloxstrap/GlobalCache.cs @@ -3,5 +3,7 @@ public static class GlobalCache { public static readonly Dictionary ServerLocation = new(); + + public static readonly Dictionary UserThumbnails = new(); } } diff --git a/Bloxstrap/Integrations/ActivityWatcher.cs b/Bloxstrap/Integrations/ActivityWatcher.cs index 73b3b80c..88eb98b4 100644 --- a/Bloxstrap/Integrations/ActivityWatcher.cs +++ b/Bloxstrap/Integrations/ActivityWatcher.cs @@ -222,7 +222,7 @@ private void ReadLogEntry(string entry) return; } - if (!UInt64.TryParse(match.Groups[1].Value, out ulong result)) + if (!Int64.TryParse(match.Groups[1].Value, out long result)) { App.Logger.WriteLine(LOG_IDENT, "Failed to parse userid from game join load time entry"); App.Logger.WriteLine(LOG_IDENT, match.Groups[1].Value); diff --git a/Bloxstrap/Integrations/DiscordRichPresence.cs b/Bloxstrap/Integrations/DiscordRichPresence.cs index 38619184..8d140f9f 100644 --- a/Bloxstrap/Integrations/DiscordRichPresence.cs +++ b/Bloxstrap/Integrations/DiscordRichPresence.cs @@ -227,29 +227,12 @@ public async Task SetCurrentGame() icon = universeDetails.Thumbnail.ImageUrl; - if (App.Settings.Prop.AccountShownOnProfile) + if (App.Settings.Prop.ShowAccountOnRichPresence) { - var userPfpResponse = await Http.GetJson>($"https://thumbnails.roblox.com/v1/users/avatar-headshot?userIds={activity.UserId}&size=180x180&format=Png&isCircular=false"); //we can remove '-headshot' from the url if we want a full avatar picture - if (userPfpResponse is null || !userPfpResponse.Data.Any()) - { - App.Logger.WriteLine(LOG_IDENT, "Could not get user thumbnail info!"); - } - else - { - smallImage = userPfpResponse.Data.First().ImageUrl; - App.Logger.WriteLine(LOG_IDENT, $"Got user thumbnail as {smallImage}"); - } - - var userInfoResponse = await Http.GetJson($"https://users.roblox.com/v1/users/{activity.UserId}"); - if (userInfoResponse is null) - { - App.Logger.WriteLine(LOG_IDENT, "Could not get user info!"); - } - else - { - smallImageText = userInfoResponse.DisplayName + $" (@{userInfoResponse.Username})"; //example: john doe (@johndoe) - App.Logger.WriteLine(LOG_IDENT, $"Got user info as {smallImageText}"); - } + var userDetails = await UserDetails.Fetch(activity.UserId); + + smallImage = userDetails.Thumbnail.ImageUrl; + smallImageText = $"Playing on {userDetails.Data.DisplayName} (@{userDetails.Data.Name})"; // i.e. "axell (@Axelan_se)" } if (!_activityWatcher.InGame || placeId != activity.PlaceId) diff --git a/Bloxstrap/Models/APIs/Roblox/GetUserResponse.cs b/Bloxstrap/Models/APIs/Roblox/GetUserResponse.cs new file mode 100644 index 00000000..aece061b --- /dev/null +++ b/Bloxstrap/Models/APIs/Roblox/GetUserResponse.cs @@ -0,0 +1,56 @@ +namespace Bloxstrap.Models.RobloxApi +{ + /// + /// Roblox.Users.Api.GetUserResponse + /// + public class GetUserResponse + { + /// + /// The user description. + /// + [JsonPropertyName("description")] + public string Description { get; set; } = null!; + + /// + /// When the user signed up. + /// + [JsonPropertyName("created")] + public DateTime Created { get; set; } + + /// + /// Whether the user is banned + /// + [JsonPropertyName("isBanned")] + public bool IsBanned { get; set; } + + /// + /// Unused, legacy attribute… rely on its existence. + /// + [JsonPropertyName("externalAppDisplayName")] + public string ExternalAppDisplayName { get; set; } = null!; + + /// + /// The user's verified badge status. + /// + [JsonPropertyName("hasVerifiedBadge")] + public bool HasVerifiedBadge { get; set; } + + /// + /// The user Id. + /// + [JsonPropertyName("id")] + public long Id { get; set; } + + /// + /// The user name. + /// + [JsonPropertyName("name")] + public string Name { get; set; } = null!; + + /// + /// The user DisplayName. + /// + [JsonPropertyName("displayName")] + public string DisplayName { get; set; } = null!; + } +} diff --git a/Bloxstrap/Models/APIs/Roblox/UserInfoResponse.cs b/Bloxstrap/Models/APIs/Roblox/UserInfoResponse.cs deleted file mode 100644 index c043a8f7..00000000 --- a/Bloxstrap/Models/APIs/Roblox/UserInfoResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Bloxstrap.Models.RobloxApi -{ - /// - /// Roblox.Web.Responses.Users.UserInfoResponse - /// - public class UserInfoResponse - { - [JsonPropertyName("description")] - public string ProfileDescription { get; set; } = null!; - - [JsonPropertyName("created")] - public string JoinDate { get; set; } = null!; - - [JsonPropertyName("isBanned")] - public bool IsBanned { get; set; } - - [JsonPropertyName("hasVerifiedBadge")] - public bool HasVerifiedBadge { get; set; } - - [JsonPropertyName("name")] - public string Username { get; set; } = null!; - - [JsonPropertyName("displayName")] - public string DisplayName { get; set; } = null!; - } -} diff --git a/Bloxstrap/Models/Entities/ActivityData.cs b/Bloxstrap/Models/Entities/ActivityData.cs index 8cebff2a..e77828e1 100644 --- a/Bloxstrap/Models/Entities/ActivityData.cs +++ b/Bloxstrap/Models/Entities/ActivityData.cs @@ -35,7 +35,7 @@ public long UniverseId /// public string AccessCode { get; set; } = string.Empty; - public ulong UserId { get; set; } = 0; + public long UserId { get; set; } = 0; public string MachineAddress { get; set; } = string.Empty; diff --git a/Bloxstrap/Models/Entities/UniverseDetails.cs b/Bloxstrap/Models/Entities/UniverseDetails.cs index 62f5445d..449eede6 100644 --- a/Bloxstrap/Models/Entities/UniverseDetails.cs +++ b/Bloxstrap/Models/Entities/UniverseDetails.cs @@ -1,7 +1,8 @@ -using Bloxstrap.Models.APIs.Roblox; - -namespace Bloxstrap.Models.Entities +namespace Bloxstrap.Models.Entities { + /// + /// Explicit loading. Load from cache before and after a fetch. + /// public class UniverseDetails { private static List _cache { get; set; } = new(); diff --git a/Bloxstrap/Models/Entities/UserDetails.cs b/Bloxstrap/Models/Entities/UserDetails.cs new file mode 100644 index 00000000..6fc8e7ab --- /dev/null +++ b/Bloxstrap/Models/Entities/UserDetails.cs @@ -0,0 +1,42 @@ +using Bloxstrap.Models.RobloxApi; + +namespace Bloxstrap.Models.Entities +{ + public class UserDetails + { + private static List _cache { get; set; } = new(); + + public GetUserResponse Data { get; set; } = null!; + + public ThumbnailResponse Thumbnail { get; set; } = null!; + + public static async Task Fetch(long id) + { + var cacheQuery = _cache.Where(x => x.Data?.Id == id); + + if (cacheQuery.Any()) + return cacheQuery.First(); + + var userResponse = await Http.GetJson($"https://users.roblox.com/v1/users/{id}"); + + if (userResponse is null) + throw new InvalidHTTPResponseException("Roblox API for User Details returned invalid data"); + + // we can remove '-headshot' from the url if we want a full avatar picture + var thumbnailResponse = await Http.GetJson>($"https://thumbnails.roblox.com/v1/users/avatar-headshot?userIds={id}&size=180x180&format=Png&isCircular=false"); + + if (thumbnailResponse is null || !thumbnailResponse.Data.Any()) + throw new InvalidHTTPResponseException("Roblox API for Thumbnails returned invalid data"); + + var details = new UserDetails + { + Data = userResponse, + Thumbnail = thumbnailResponse.Data.First() + }; + + _cache.Add(details); + + return details; + } + } +} diff --git a/Bloxstrap/Models/Persistable/Settings.cs b/Bloxstrap/Models/Persistable/Settings.cs index 3b753f0f..fcea6cb3 100644 --- a/Bloxstrap/Models/Persistable/Settings.cs +++ b/Bloxstrap/Models/Persistable/Settings.cs @@ -21,7 +21,7 @@ public class Settings public bool EnableActivityTracking { get; set; } = true; public bool UseDiscordRichPresence { get; set; } = true; public bool HideRPCButtons { get; set; } = true; - public bool AccountShownOnProfile { get; set; } = true; + public bool ShowAccountOnRichPresence { get; set; } = false; public bool ShowServerDetails { get; set; } = false; public ObservableCollection CustomIntegrations { get; set; } = new(); diff --git a/Bloxstrap/Resources/Strings.Designer.cs b/Bloxstrap/Resources/Strings.Designer.cs index f8464a80..f8ec5240 100644 --- a/Bloxstrap/Resources/Strings.Designer.cs +++ b/Bloxstrap/Resources/Strings.Designer.cs @@ -2664,24 +2664,6 @@ public static string Menu_Integrations_AllowActivityJoining_Description { return ResourceManager.GetString("Menu.Integrations.AllowActivityJoining.Description", resourceCulture); } } - - /// - /// Looks up a localized string similar to Show account on profile. - /// - public static string Menu_Integrations_ShowAccountOnProfile_Title { - get { - return ResourceManager.GetString("Menu.Integrations.ShowAccountOnProfile.Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Shows what Roblox account your using on your Discord profile. - /// - public static string Menu_Integrations_ShowAccountOnProfile_Description { - get { - return ResourceManager.GetString("Menu.Integrations.ShowAccountOnProfile.Description", resourceCulture); - } - } /// /// Looks up a localized string similar to Allow activity joining. @@ -2836,6 +2818,24 @@ public static string Menu_Integrations_RequiresActivityTracking { } } + /// + /// Looks up a localized string similar to Shows the Roblox account you're playing with on your Discord profile.. + /// + public static string Menu_Integrations_ShowAccountOnProfile_Description { + get { + return ResourceManager.GetString("Menu.Integrations.ShowAccountOnProfile.Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Show Roblox account. + /// + public static string Menu_Integrations_ShowAccountOnProfile_Title { + get { + return ResourceManager.GetString("Menu.Integrations.ShowAccountOnProfile.Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to The Roblox game you're playing will be shown on your Discord profile. [Not working?]({0}). /// diff --git a/Bloxstrap/Resources/Strings.resx b/Bloxstrap/Resources/Strings.resx index dc3cd26f..3a1baf1e 100644 --- a/Bloxstrap/Resources/Strings.resx +++ b/Bloxstrap/Resources/Strings.resx @@ -702,10 +702,10 @@ Selecting 'No' will ignore this warning and continue installation. Allow activity joining - Shows which Roblox account you are using on your Discord profile. + Shows the Roblox account you're playing with on your Discord profile. - Show account on profile + Show Roblox account Application Location diff --git a/Bloxstrap/UI/Elements/About/Pages/AboutPage.xaml b/Bloxstrap/UI/Elements/About/Pages/AboutPage.xaml index d35d6bf8..1b57bab4 100644 --- a/Bloxstrap/UI/Elements/About/Pages/AboutPage.xaml +++ b/Bloxstrap/UI/Elements/About/Pages/AboutPage.xaml @@ -102,6 +102,7 @@ + @@ -133,7 +134,7 @@ - + diff --git a/Bloxstrap/UI/ViewModels/Settings/IntegrationsViewModel.cs b/Bloxstrap/UI/ViewModels/Settings/IntegrationsViewModel.cs index 78b007c8..d66789d6 100644 --- a/Bloxstrap/UI/ViewModels/Settings/IntegrationsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Settings/IntegrationsViewModel.cs @@ -115,8 +115,8 @@ public bool DiscordActivityJoinEnabled public bool DiscordAccountOnProfile { - get => App.Settings.Prop.AccountShownOnProfile; - set => App.Settings.Prop.AccountShownOnProfile = value; + get => App.Settings.Prop.ShowAccountOnRichPresence; + set => App.Settings.Prop.ShowAccountOnRichPresence = value; } public bool DisableAppPatchEnabled