mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
Make Discord Presence logging more verbose
This commit is contained in:
parent
f738ffc349
commit
52313cf2af
@ -15,80 +15,92 @@ namespace Bloxstrap.Helpers.Integrations
|
|||||||
{
|
{
|
||||||
class DiscordRichPresence : IDisposable
|
class DiscordRichPresence : IDisposable
|
||||||
{
|
{
|
||||||
readonly DiscordRpcClient RichPresence = new("1005469189907173486");
|
private readonly DiscordRpcClient _rpcClient = new("1005469189907173486");
|
||||||
|
|
||||||
const string GameJoiningEntry = "[FLog::Output] ! Joining game";
|
// i'm thinking the functionality for parsing roblox logs could be broadened for more features than just rich presence,
|
||||||
const string GameJoinedEntry = "[FLog::Network] serverId:";
|
// like checking the ping and region of the current connected server. maybe that's something to add?
|
||||||
const string GameDisconnectedEntry = "[FLog::Network] Time to disconnect replication data:";
|
private const string GameJoiningEntry = "[FLog::Output] ! Joining game";
|
||||||
|
private const string GameJoinedEntry = "[FLog::Network] serverId:";
|
||||||
|
private const string GameDisconnectedEntry = "[FLog::Network] Time to disconnect replication data:";
|
||||||
|
|
||||||
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\.]+)";
|
||||||
const string GameJoinedEntryPattern = @"serverId: ([0-9\.]+)\|([0-9]+)";
|
private const string GameJoinedEntryPattern = @"serverId: ([0-9\.]+)\|([0-9]+)";
|
||||||
|
|
||||||
|
private int _logEntriesRead = 0;
|
||||||
|
|
||||||
// these are values to use assuming the player isn't currently in a game
|
// these are values to use assuming the player isn't currently in a game
|
||||||
bool ActivityInGame = false;
|
private bool _activityInGame = false;
|
||||||
long ActivityPlaceId = 0;
|
private long _activityPlaceId = 0;
|
||||||
string ActivityJobId = "";
|
private string _activityJobId = "";
|
||||||
string ActivityMachineAddress = ""; // we're only really using this to confirm a place join. todo: maybe this could be used to see server location/ping?
|
private string _activityMachineAddress = "";
|
||||||
|
|
||||||
public DiscordRichPresence()
|
public DiscordRichPresence()
|
||||||
{
|
{
|
||||||
RichPresence.OnReady += (_, e) =>
|
_rpcClient.OnReady += (_, e) =>
|
||||||
App.Logger.WriteLine($"[DiscordRichPresence::DiscordRichPresence] Received ready from user {e.User.Username} ({e.User.ID})");
|
App.Logger.WriteLine($"[DiscordRichPresence::DiscordRichPresence] Received ready from user {e.User.Username} ({e.User.ID})");
|
||||||
|
|
||||||
RichPresence.OnPresenceUpdate += (_, e) =>
|
_rpcClient.OnPresenceUpdate += (_, e) =>
|
||||||
App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Updated presence");
|
App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Updated presence");
|
||||||
|
|
||||||
RichPresence.OnConnectionEstablished += (_, e) =>
|
_rpcClient.OnConnectionEstablished += (_, e) =>
|
||||||
App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Established connection with Discord RPC");
|
App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Established connection with Discord RPC");
|
||||||
|
|
||||||
//spams log as it tries to connect every ~15 sec when discord is closed so not now
|
//spams log as it tries to connect every ~15 sec when discord is closed so not now
|
||||||
//RichPresence.OnConnectionFailed += (_, e) =>
|
//_rpcClient.OnConnectionFailed += (_, e) =>
|
||||||
// App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Failed to establish connection with Discord RPC");
|
// App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Failed to establish connection with Discord RPC");
|
||||||
|
|
||||||
RichPresence.OnClose += (_, e) =>
|
_rpcClient.OnClose += (_, e) =>
|
||||||
App.Logger.WriteLine($"[DiscordRichPresence::DiscordRichPresence] Lost connection to Discord RPC - {e.Reason} ({e.Code})");
|
App.Logger.WriteLine($"[DiscordRichPresence::DiscordRichPresence] Lost connection to Discord RPC - {e.Reason} ({e.Code})");
|
||||||
|
|
||||||
RichPresence.Initialize();
|
_rpcClient.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExamineLogEntry(string entry)
|
private async Task ExamineLogEntry(string entry)
|
||||||
{
|
{
|
||||||
// App.Logger.WriteLine(entry);
|
// App.Logger.WriteLine(entry);
|
||||||
|
_logEntriesRead += 1;
|
||||||
|
|
||||||
if (entry.Contains(GameJoiningEntry) && !ActivityInGame && ActivityPlaceId == 0)
|
// debug stats to ensure that the log reader is working correctly
|
||||||
|
// if more than 5000 log entries have been read, only log per 100 to save on spam
|
||||||
|
if (_logEntriesRead <= 5000 && _logEntriesRead % 50 == 0)
|
||||||
|
App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Read {_logEntriesRead} log entries");
|
||||||
|
else if (_logEntriesRead % 100 == 0)
|
||||||
|
App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Read {_logEntriesRead} log entries");
|
||||||
|
|
||||||
|
if (entry.Contains(GameJoiningEntry) && !_activityInGame && _activityPlaceId == 0)
|
||||||
{
|
{
|
||||||
Match match = Regex.Match(entry, GameJoiningEntryPattern);
|
Match match = Regex.Match(entry, GameJoiningEntryPattern);
|
||||||
|
|
||||||
if (match.Groups.Count != 4)
|
if (match.Groups.Count != 4)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ActivityInGame = false;
|
_activityInGame = false;
|
||||||
ActivityPlaceId = Int64.Parse(match.Groups[2].Value);
|
_activityPlaceId = Int64.Parse(match.Groups[2].Value);
|
||||||
ActivityJobId = match.Groups[1].Value;
|
_activityJobId = match.Groups[1].Value;
|
||||||
ActivityMachineAddress = match.Groups[3].Value;
|
_activityMachineAddress = match.Groups[3].Value;
|
||||||
|
|
||||||
App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Joining Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})");
|
App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Joining Game ({_activityPlaceId}/{_activityJobId}/{_activityMachineAddress})");
|
||||||
}
|
}
|
||||||
else if (entry.Contains(GameJoinedEntry) && !ActivityInGame && ActivityPlaceId != 0)
|
else if (entry.Contains(GameJoinedEntry) && !_activityInGame && _activityPlaceId != 0)
|
||||||
{
|
{
|
||||||
Match match = Regex.Match(entry, GameJoinedEntryPattern);
|
Match match = Regex.Match(entry, GameJoinedEntryPattern);
|
||||||
|
|
||||||
if (match.Groups.Count != 3 || match.Groups[1].Value != ActivityMachineAddress)
|
if (match.Groups.Count != 3 || match.Groups[1].Value != _activityMachineAddress)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Joined Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})");
|
App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Joined Game ({_activityPlaceId}/{_activityJobId}/{_activityMachineAddress})");
|
||||||
|
|
||||||
ActivityInGame = true;
|
_activityInGame = true;
|
||||||
await SetPresence();
|
await SetPresence();
|
||||||
}
|
}
|
||||||
else if (entry.Contains(GameDisconnectedEntry) && ActivityInGame && ActivityPlaceId != 0)
|
else if (entry.Contains(GameDisconnectedEntry) && _activityInGame && _activityPlaceId != 0)
|
||||||
{
|
{
|
||||||
App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Disconnected from Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})");
|
App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Disconnected from Game ({_activityPlaceId}/{_activityJobId}/{_activityMachineAddress})");
|
||||||
|
|
||||||
ActivityInGame = false;
|
_activityInGame = false;
|
||||||
ActivityPlaceId = 0;
|
_activityPlaceId = 0;
|
||||||
ActivityJobId = "";
|
_activityJobId = "";
|
||||||
ActivityMachineAddress = "";
|
_activityMachineAddress = "";
|
||||||
await SetPresence();
|
await SetPresence();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,6 +129,8 @@ namespace Bloxstrap.Helpers.Integrations
|
|||||||
// if roblox doesn't start quickly enough, we can wind up fetching the previous log file
|
// if roblox doesn't start quickly enough, we can wind up fetching the previous log file
|
||||||
// good rule of thumb is to find a log file that was created in the last 15 seconds or so
|
// good rule of thumb is to find a log file that was created in the last 15 seconds or so
|
||||||
|
|
||||||
|
App.Logger.WriteLine("[DiscordRichPresence::MonitorGameActivity] Opening Roblox log file...");
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
logFileInfo = new DirectoryInfo(logDirectory).GetFiles().OrderByDescending(x => x.CreationTime).First();
|
logFileInfo = new DirectoryInfo(logDirectory).GetFiles().OrderByDescending(x => x.CreationTime).First();
|
||||||
@ -124,10 +138,12 @@ namespace Bloxstrap.Helpers.Integrations
|
|||||||
if (logFileInfo.CreationTime.AddSeconds(15) > DateTime.Now)
|
if (logFileInfo.CreationTime.AddSeconds(15) > DateTime.Now)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
App.Logger.WriteLine($"[DiscordRichPresence::MonitorGameActivity] Could not find recent enough log file, waiting... (newest is {logFileInfo.Name})");
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileStream logFileStream = logFileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
FileStream logFileStream = logFileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||||
|
App.Logger.WriteLine($"[DiscordRichPresence::MonitorGameActivity] Opened {logFileInfo.Name}");
|
||||||
|
|
||||||
AutoResetEvent logUpdatedEvent = new(false);
|
AutoResetEvent logUpdatedEvent = new(false);
|
||||||
FileSystemWatcher logWatcher = new()
|
FileSystemWatcher logWatcher = new()
|
||||||
@ -138,74 +154,66 @@ namespace Bloxstrap.Helpers.Integrations
|
|||||||
};
|
};
|
||||||
logWatcher.Changed += (s, e) => logUpdatedEvent.Set();
|
logWatcher.Changed += (s, e) => logUpdatedEvent.Set();
|
||||||
|
|
||||||
using (StreamReader sr = new(logFileStream))
|
using StreamReader sr = new(logFileStream);
|
||||||
{
|
|
||||||
string? log = null;
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
log = await sr.ReadLineAsync();
|
string? log = await sr.ReadLineAsync();
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(log))
|
if (String.IsNullOrEmpty(log))
|
||||||
{
|
|
||||||
logUpdatedEvent.WaitOne(1000);
|
logUpdatedEvent.WaitOne(1000);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
//App.Logger.WriteLine(log);
|
|
||||||
await ExamineLogEntry(log);
|
await ExamineLogEntry(log);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no need to close the event, its going to be finished with when the program closes anyway
|
// no need to close the event, its going to be finished with when the program closes anyway
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SetPresence()
|
public async Task<bool> SetPresence()
|
||||||
{
|
{
|
||||||
if (!ActivityInGame)
|
if (!_activityInGame)
|
||||||
{
|
{
|
||||||
RichPresence.ClearPresence();
|
_rpcClient.ClearPresence();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string placeThumbnail = "roblox";
|
string placeThumbnail = "roblox";
|
||||||
|
|
||||||
var placeInfo = await Utilities.GetJson<RobloxAsset>($"https://economy.roblox.com/v2/assets/{ActivityPlaceId}/details");
|
var placeInfo = await Utilities.GetJson<RobloxAsset>($"https://economy.roblox.com/v2/assets/{_activityPlaceId}/details");
|
||||||
|
|
||||||
if (placeInfo is null || placeInfo.Creator is null)
|
if (placeInfo is null || placeInfo.Creator is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var thumbnailInfo = await Utilities.GetJson<RobloxThumbnails>($"https://thumbnails.roblox.com/v1/places/gameicons?placeIds={ActivityPlaceId}&returnPolicy=PlaceHolder&size=512x512&format=Png&isCircular=false");
|
var thumbnailInfo = await Utilities.GetJson<RobloxThumbnails>($"https://thumbnails.roblox.com/v1/places/gameicons?placeIds={_activityPlaceId}&returnPolicy=PlaceHolder&size=512x512&format=Png&isCircular=false");
|
||||||
|
|
||||||
if (thumbnailInfo is not null)
|
if (thumbnailInfo is not null)
|
||||||
placeThumbnail = thumbnailInfo.Data![0].ImageUrl!;
|
placeThumbnail = thumbnailInfo.Data![0].ImageUrl!;
|
||||||
|
|
||||||
List<DiscordRPC.Button> buttons = new()
|
List<Button> buttons = new()
|
||||||
{
|
{
|
||||||
new DiscordRPC.Button()
|
new Button
|
||||||
{
|
{
|
||||||
Label = "See Details",
|
Label = "See Details",
|
||||||
Url = $"https://www.roblox.com/games/{ActivityPlaceId}"
|
Url = $"https://www.roblox.com/games/{_activityPlaceId}"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!App.Settings.Prop.HideRPCButtons)
|
if (!App.Settings.Prop.HideRPCButtons)
|
||||||
{
|
{
|
||||||
buttons.Insert(0, new DiscordRPC.Button()
|
buttons.Insert(0, new Button
|
||||||
{
|
{
|
||||||
Label = "Join",
|
Label = "Join",
|
||||||
Url = $"https://www.roblox.com/games/start?placeId={ActivityPlaceId}&gameInstanceId={ActivityJobId}&launchData=%7B%7D"
|
Url = $"https://www.roblox.com/games/start?placeId={_activityPlaceId}&gameInstanceId={_activityJobId}&launchData=%7B%7D"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RichPresence.SetPresence(new RichPresence()
|
_rpcClient.SetPresence(new RichPresence
|
||||||
{
|
{
|
||||||
Details = placeInfo.Name,
|
Details = placeInfo.Name,
|
||||||
State = $"by {placeInfo.Creator.Name}",
|
State = $"by {placeInfo.Creator.Name}",
|
||||||
Timestamps = new Timestamps() { Start = DateTime.UtcNow },
|
Timestamps = new Timestamps { Start = DateTime.UtcNow },
|
||||||
Buttons = buttons.ToArray(),
|
Buttons = buttons.ToArray(),
|
||||||
Assets = new Assets()
|
Assets = new Assets
|
||||||
{
|
{
|
||||||
LargeImageKey = placeThumbnail,
|
LargeImageKey = placeThumbnail,
|
||||||
LargeImageText = placeInfo.Name,
|
LargeImageText = placeInfo.Name,
|
||||||
@ -220,8 +228,8 @@ namespace Bloxstrap.Helpers.Integrations
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
App.Logger.WriteLine("[DiscordRichPresence::Dispose] Cleaning up Discord RPC and Presence");
|
App.Logger.WriteLine("[DiscordRichPresence::Dispose] Cleaning up Discord RPC and Presence");
|
||||||
RichPresence.ClearPresence();
|
_rpcClient.ClearPresence();
|
||||||
RichPresence.Dispose();
|
_rpcClient.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user