mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
Show account on discord rich presence (#2255)
* add functionality for grabbing userid * Create UserInfoResponse.cs * add user pfp small image thingy * add missing semicolons * get rid of semicolons * debugging (remove later) * make properties nullable * forgot to put dollar sign before interpolated string * make properties that cant be nullable not nullable * more debugging * remove thing * remove other thing * remove thing (again) (again) * remove thing (again) (again) (again) * add space between username and displayname to make it more visually pleasing * matt review changes (better code readability) * add strings for show account on profile * add AccountShownOnProfile setting * add DiscordActivityJoinEnabled to integrations viewmodel * fix accidentally swapping 2 variables * refrence correct variables * refrence correct variables (again) * add showaccountonprofile strings * add option to integrations page * add missing < that somehow got lost * make that its own option * dont invert that value * dont invert that (again) * Update IntegrationsViewModel.cs * fix grammatical issue in string * move else to new line * fix merge conflicts * move gameJoinLoadTime check * matt review changes * handle if parsing userid fails --------- Co-authored-by: pizzaboxer <pizzaboxer@pizzaboxer.xyz>
This commit is contained in:
parent
0acf1ee24b
commit
55f5ef48e8
@ -17,7 +17,9 @@
|
|||||||
private const string GameDisconnectedEntry = "[FLog::Network] Time to disconnect replication data:";
|
private const string GameDisconnectedEntry = "[FLog::Network] Time to disconnect replication data:";
|
||||||
private const string GameTeleportingEntry = "[FLog::SingleSurfaceApp] initiateTeleport";
|
private const string GameTeleportingEntry = "[FLog::SingleSurfaceApp] initiateTeleport";
|
||||||
private const string GameLeavingEntry = "[FLog::SingleSurfaceApp] leaveUGCGameInternal";
|
private const string GameLeavingEntry = "[FLog::SingleSurfaceApp] leaveUGCGameInternal";
|
||||||
|
private const string GameJoinLoadTimeEntry = "[FLog::GameJoinLoadTime] Report game_join_loadtime:";
|
||||||
|
|
||||||
|
private const string GameJoinLoadTimeEntryPattern = ", userid:([0-9]+)";
|
||||||
private const string GameJoiningEntryPattern = @"! Joining game '([0-9a-f\-]{36})' place ([0-9]+) at ([0-9\.]+)";
|
private const string GameJoiningEntryPattern = @"! Joining game '([0-9a-f\-]{36})' place ([0-9]+) at ([0-9\.]+)";
|
||||||
private const string GameJoiningPrivateServerPattern = @"""accessCode"":""([0-9a-f\-]{36})""";
|
private const string GameJoiningPrivateServerPattern = @"""accessCode"":""([0-9a-f\-]{36})""";
|
||||||
private const string GameJoiningUniversePattern = @"universeid:([0-9]+)";
|
private const string GameJoiningUniversePattern = @"universeid:([0-9]+)";
|
||||||
@ -209,6 +211,28 @@
|
|||||||
{
|
{
|
||||||
// We are not confirmed to be in a game, but we are in the process of joining one
|
// We are not confirmed to be in a game, but we are in the process of joining one
|
||||||
|
|
||||||
|
if (entry.Contains(GameJoinLoadTimeEntry))
|
||||||
|
{
|
||||||
|
Match match = Regex.Match(entry, GameJoinLoadTimeEntryPattern);
|
||||||
|
|
||||||
|
if (match.Groups.Count != 2)
|
||||||
|
{
|
||||||
|
App.Logger.WriteLine(LOG_IDENT, "Failed to assert format for game join load time entry");
|
||||||
|
App.Logger.WriteLine(LOG_IDENT, entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UInt64.TryParse(match.Groups[1].Value, out ulong 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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Data.UserId = result;
|
||||||
|
App.Logger.WriteLine(LOG_IDENT, $"Got userid as {Data.UserId}");
|
||||||
|
}
|
||||||
|
|
||||||
if (entry.Contains(GameJoiningUniverseEntry))
|
if (entry.Contains(GameJoiningUniverseEntry))
|
||||||
{
|
{
|
||||||
var match = Regex.Match(entry, GameJoiningUniversePattern);
|
var match = Regex.Match(entry, GameJoiningUniversePattern);
|
||||||
@ -279,7 +303,6 @@
|
|||||||
History.Insert(0, Data);
|
History.Insert(0, Data);
|
||||||
|
|
||||||
InGame = false;
|
InGame = false;
|
||||||
|
|
||||||
Data = new();
|
Data = new();
|
||||||
|
|
||||||
OnGameLeave?.Invoke(this, new EventArgs());
|
OnGameLeave?.Invoke(this, new EventArgs());
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using Bloxstrap.Models.RobloxApi;
|
||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
|
|
||||||
namespace Bloxstrap.Integrations
|
namespace Bloxstrap.Integrations
|
||||||
@ -192,6 +192,9 @@ namespace Bloxstrap.Integrations
|
|||||||
}
|
}
|
||||||
|
|
||||||
string icon = "roblox";
|
string icon = "roblox";
|
||||||
|
string smallImageText = "Roblox";
|
||||||
|
string smallImage = "roblox";
|
||||||
|
|
||||||
|
|
||||||
var activity = _activityWatcher.Data;
|
var activity = _activityWatcher.Data;
|
||||||
long placeId = activity.PlaceId;
|
long placeId = activity.PlaceId;
|
||||||
@ -224,6 +227,31 @@ namespace Bloxstrap.Integrations
|
|||||||
|
|
||||||
icon = universeDetails.Thumbnail.ImageUrl;
|
icon = universeDetails.Thumbnail.ImageUrl;
|
||||||
|
|
||||||
|
if (App.Settings.Prop.AccountShownOnProfile)
|
||||||
|
{
|
||||||
|
var userPfpResponse = await Http.GetJson<ApiArrayResponse<ThumbnailResponse>>($"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<UserInfoResponse>($"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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!_activityWatcher.InGame || placeId != activity.PlaceId)
|
if (!_activityWatcher.InGame || placeId != activity.PlaceId)
|
||||||
{
|
{
|
||||||
App.Logger.WriteLine(LOG_IDENT, "Aborting presence set because game activity has changed");
|
App.Logger.WriteLine(LOG_IDENT, "Aborting presence set because game activity has changed");
|
||||||
@ -251,9 +279,9 @@ namespace Bloxstrap.Integrations
|
|||||||
Assets = new Assets
|
Assets = new Assets
|
||||||
{
|
{
|
||||||
LargeImageKey = icon,
|
LargeImageKey = icon,
|
||||||
LargeImageText = universeName,
|
LargeImageText = universeDetails.Data.Name,
|
||||||
SmallImageKey = "roblox",
|
SmallImageKey = smallImage,
|
||||||
SmallImageText = "Roblox"
|
SmallImageText = smallImageText
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
26
Bloxstrap/Models/APIs/Roblox/UserInfoResponse.cs
Normal file
26
Bloxstrap/Models/APIs/Roblox/UserInfoResponse.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
namespace Bloxstrap.Models.RobloxApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Roblox.Web.Responses.Users.UserInfoResponse
|
||||||
|
/// </summary>
|
||||||
|
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!;
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,8 @@ namespace Bloxstrap.Models.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string AccessCode { get; set; } = string.Empty;
|
public string AccessCode { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public ulong UserId { get; set; } = 0;
|
||||||
|
|
||||||
public string MachineAddress { get; set; } = string.Empty;
|
public string MachineAddress { get; set; } = string.Empty;
|
||||||
|
|
||||||
public bool MachineAddressValid => !string.IsNullOrEmpty(MachineAddress) && !MachineAddress.StartsWith("10.");
|
public bool MachineAddressValid => !string.IsNullOrEmpty(MachineAddress) && !MachineAddress.StartsWith("10.");
|
||||||
|
@ -21,6 +21,7 @@ namespace Bloxstrap.Models.Persistable
|
|||||||
public bool EnableActivityTracking { get; set; } = true;
|
public bool EnableActivityTracking { get; set; } = true;
|
||||||
public bool UseDiscordRichPresence { get; set; } = true;
|
public bool UseDiscordRichPresence { get; set; } = true;
|
||||||
public bool HideRPCButtons { get; set; } = true;
|
public bool HideRPCButtons { get; set; } = true;
|
||||||
|
public bool AccountShownOnProfile { get; set; } = true;
|
||||||
public bool ShowServerDetails { get; set; } = false;
|
public bool ShowServerDetails { get; set; } = false;
|
||||||
public ObservableCollection<CustomIntegration> CustomIntegrations { get; set; } = new();
|
public ObservableCollection<CustomIntegration> CustomIntegrations { get; set; } = new();
|
||||||
|
|
||||||
|
18
Bloxstrap/Resources/Strings.Designer.cs
generated
18
Bloxstrap/Resources/Strings.Designer.cs
generated
@ -2665,6 +2665,24 @@ namespace Bloxstrap.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Show account on profile.
|
||||||
|
/// </summary>
|
||||||
|
public static string Menu_Integrations_ShowAccountOnProfile_Title {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Menu.Integrations.ShowAccountOnProfile.Title", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Shows what Roblox account your using on your Discord profile.
|
||||||
|
/// </summary>
|
||||||
|
public static string Menu_Integrations_ShowAccountOnProfile_Description {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Menu.Integrations.ShowAccountOnProfile.Description", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Allow activity joining.
|
/// Looks up a localized string similar to Allow activity joining.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -701,6 +701,12 @@ Selecting 'No' will ignore this warning and continue installation.</value>
|
|||||||
<data name="Menu.Integrations.AllowActivityJoining.Title" xml:space="preserve">
|
<data name="Menu.Integrations.AllowActivityJoining.Title" xml:space="preserve">
|
||||||
<value>Allow activity joining</value>
|
<value>Allow activity joining</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Menu.Integrations.ShowAccountOnProfile.Description" xml:space="preserve">
|
||||||
|
<value>Shows which Roblox account you are using on your Discord profile.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Menu.Integrations.ShowAccountOnProfile.Title" xml:space="preserve">
|
||||||
|
<value>Show account on profile</value>
|
||||||
|
</data>
|
||||||
<data name="Menu.Integrations.Custom.AppLocation" xml:space="preserve">
|
<data name="Menu.Integrations.Custom.AppLocation" xml:space="preserve">
|
||||||
<value>Application Location</value>
|
<value>Application Location</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -58,6 +58,13 @@
|
|||||||
<ui:ToggleSwitch IsChecked="{Binding DiscordActivityJoinEnabled, Mode=TwoWay}" />
|
<ui:ToggleSwitch IsChecked="{Binding DiscordActivityJoinEnabled, Mode=TwoWay}" />
|
||||||
</controls:OptionControl>
|
</controls:OptionControl>
|
||||||
|
|
||||||
|
<controls:OptionControl
|
||||||
|
Header="{x:Static resources:Strings.Menu_Integrations_ShowAccountOnProfile_Title}"
|
||||||
|
Description="{x:Static resources:Strings.Menu_Integrations_ShowAccountOnProfile_Description}"
|
||||||
|
IsEnabled="{Binding InnerContent.IsChecked, ElementName=DiscordActivityOption, Mode=OneWay}">
|
||||||
|
<ui:ToggleSwitch IsChecked="{Binding DiscordAccountOnProfile, Mode=TwoWay}" />
|
||||||
|
</controls:OptionControl>
|
||||||
|
|
||||||
<TextBlock Text="{x:Static resources:Strings.Menu_Integrations_Custom_Title}" FontSize="20" FontWeight="Medium" Margin="0,16,0,0" />
|
<TextBlock Text="{x:Static resources:Strings.Menu_Integrations_Custom_Title}" FontSize="20" FontWeight="Medium" Margin="0,16,0,0" />
|
||||||
<TextBlock Text="{x:Static resources:Strings.Menu_Integrations_Custom_Description}" TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
<TextBlock Text="{x:Static resources:Strings.Menu_Integrations_Custom_Description}" TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||||
<Grid Margin="0,8,0,0">
|
<Grid Margin="0,8,0,0">
|
||||||
|
@ -100,7 +100,9 @@ namespace Bloxstrap.UI.ViewModels.Settings
|
|||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
DiscordActivityJoinEnabled = value;
|
DiscordActivityJoinEnabled = value;
|
||||||
|
DiscordAccountOnProfile = value;
|
||||||
OnPropertyChanged(nameof(DiscordActivityJoinEnabled));
|
OnPropertyChanged(nameof(DiscordActivityJoinEnabled));
|
||||||
|
OnPropertyChanged(nameof(DiscordAccountOnProfile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,6 +113,12 @@ namespace Bloxstrap.UI.ViewModels.Settings
|
|||||||
set => App.Settings.Prop.HideRPCButtons = !value;
|
set => App.Settings.Prop.HideRPCButtons = !value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool DiscordAccountOnProfile
|
||||||
|
{
|
||||||
|
get => App.Settings.Prop.AccountShownOnProfile;
|
||||||
|
set => App.Settings.Prop.AccountShownOnProfile = value;
|
||||||
|
}
|
||||||
|
|
||||||
public bool DisableAppPatchEnabled
|
public bool DisableAppPatchEnabled
|
||||||
{
|
{
|
||||||
get => App.Settings.Prop.UseDisableAppPatch;
|
get => App.Settings.Prop.UseDisableAppPatch;
|
||||||
|
Loading…
Reference in New Issue
Block a user