mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-05-14 04:04:42 -07:00
Make log-based Discord RP more reliable
Changed to continuously reading the log file stream rather than re-reading the log file every 30 seconds
This commit is contained in:
parent
1c14a0a3fa
commit
5b94b2741a
@ -217,20 +217,6 @@ namespace Bloxstrap
|
|||||||
richPresence.MonitorGameActivity();
|
richPresence.MonitorGameActivity();
|
||||||
|
|
||||||
shouldWait = true;
|
shouldWait = true;
|
||||||
|
|
||||||
// probably not the most ideal way to do this
|
|
||||||
//string? placeId = Utilities.GetKeyValue(LaunchCommandLine, "placeId=", '&');
|
|
||||||
|
|
||||||
//if (placeId is not null)
|
|
||||||
//{
|
|
||||||
// richPresence = new DiscordRichPresence();
|
|
||||||
// bool presenceSet = await richPresence.SetPresence(placeId);
|
|
||||||
|
|
||||||
// if (presenceSet)
|
|
||||||
// shouldWait = true;
|
|
||||||
// else
|
|
||||||
// richPresence.Dispose();
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldWait)
|
if (!shouldWait)
|
||||||
|
@ -24,49 +24,23 @@ namespace Bloxstrap.Helpers.Integrations
|
|||||||
bool ActivityInGame = false;
|
bool ActivityInGame = false;
|
||||||
long ActivityPlaceId = 0;
|
long ActivityPlaceId = 0;
|
||||||
string ActivityJobId = "";
|
string ActivityJobId = "";
|
||||||
string ActivityMachineAddress = ""; // we're only really using this to confirm a place join
|
string ActivityMachineAddress = ""; // we're only really using this to confirm a place join. todo: maybe this could be used to see server location/ping?
|
||||||
|
|
||||||
public DiscordRichPresence()
|
public DiscordRichPresence()
|
||||||
{
|
{
|
||||||
RichPresence.Initialize();
|
RichPresence.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<string> GetLog()
|
private async Task ExamineLogEntry(string entry)
|
||||||
{
|
{
|
||||||
Debug.WriteLine("[DiscordRichPresence] Reading log file...");
|
Debug.WriteLine(entry);
|
||||||
|
|
||||||
string logDirectory = Path.Combine(Program.LocalAppData, "Roblox\\logs");
|
|
||||||
|
|
||||||
if (!Directory.Exists(logDirectory))
|
|
||||||
return Enumerable.Empty<string>();
|
|
||||||
|
|
||||||
FileInfo logFileInfo = new DirectoryInfo(logDirectory).GetFiles().OrderByDescending(f => f.LastWriteTime).First();
|
|
||||||
List<string> log = new();
|
|
||||||
|
|
||||||
// we just want to read the last 3500 lines of the log file
|
|
||||||
// this should typically more than cover the last 30 seconds of logs
|
|
||||||
// it has to be last 3500 lines (~360KB) because voice chat outputs a loooot of logs :')
|
|
||||||
|
|
||||||
ReverseLineReader rlr = new(() => logFileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
|
|
||||||
log = rlr.Take(3500).ToList();
|
|
||||||
|
|
||||||
Debug.WriteLine("[DiscordRichPresence] Finished reading log file");
|
|
||||||
|
|
||||||
return log;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ExamineLog(List<string> log)
|
|
||||||
{
|
|
||||||
Debug.WriteLine("[DiscordRichPresence] Examining log file...");
|
|
||||||
|
|
||||||
foreach (string entry in log)
|
|
||||||
{
|
|
||||||
if (entry.Contains(GameJoiningEntry) && !ActivityInGame && ActivityPlaceId == 0)
|
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)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
ActivityInGame = false;
|
ActivityInGame = false;
|
||||||
ActivityPlaceId = Int64.Parse(match.Groups[2].Value);
|
ActivityPlaceId = Int64.Parse(match.Groups[2].Value);
|
||||||
@ -74,35 +48,20 @@ namespace Bloxstrap.Helpers.Integrations
|
|||||||
ActivityMachineAddress = match.Groups[3].Value;
|
ActivityMachineAddress = match.Groups[3].Value;
|
||||||
|
|
||||||
Debug.WriteLine($"[DiscordRichPresence] Joining Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})");
|
Debug.WriteLine($"[DiscordRichPresence] Joining Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})");
|
||||||
|
|
||||||
// examine log again to check for immediate changes
|
|
||||||
await Task.Delay(1000);
|
|
||||||
MonitorGameActivity(false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
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)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
Debug.WriteLine($"[DiscordRichPresence] Joined Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})");
|
Debug.WriteLine($"[DiscordRichPresence] Joined Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})");
|
||||||
|
|
||||||
ActivityInGame = true;
|
ActivityInGame = true;
|
||||||
await SetPresence();
|
await SetPresence();
|
||||||
|
|
||||||
// examine log again to check for immediate changes
|
|
||||||
await Task.Delay(1000);
|
|
||||||
MonitorGameActivity(false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
//else if (entry.Contains(GameDisconnectedEntry) && ActivityInGame && ActivityPlaceId != 0)
|
else if (entry.Contains(GameDisconnectedEntry) && ActivityInGame && ActivityPlaceId != 0)
|
||||||
else if (entry.Contains(GameDisconnectedEntry))
|
|
||||||
{
|
|
||||||
// for this one, we want to break as soon as we see this entry
|
|
||||||
// or else it'll match a game join entry and think we're joining again
|
|
||||||
if (ActivityInGame && ActivityPlaceId != 0)
|
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"[DiscordRichPresence] Disconnected from Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})");
|
Debug.WriteLine($"[DiscordRichPresence] Disconnected from Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})");
|
||||||
|
|
||||||
@ -111,20 +70,11 @@ namespace Bloxstrap.Helpers.Integrations
|
|||||||
ActivityJobId = "";
|
ActivityJobId = "";
|
||||||
ActivityMachineAddress = "";
|
ActivityMachineAddress = "";
|
||||||
await SetPresence();
|
await SetPresence();
|
||||||
|
|
||||||
// examine log again to check for immediate changes
|
|
||||||
await Task.Delay(1000);
|
|
||||||
MonitorGameActivity(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.WriteLine("[DiscordRichPresence] Finished examining log file");
|
public async void MonitorGameActivity()
|
||||||
}
|
|
||||||
|
|
||||||
public async void MonitorGameActivity(bool loop = true)
|
|
||||||
{
|
{
|
||||||
// okay, here's the process:
|
// okay, here's the process:
|
||||||
//
|
//
|
||||||
@ -135,20 +85,47 @@ namespace Bloxstrap.Helpers.Integrations
|
|||||||
// - confirm place join with 'serverId: {{MACHINEADDRESS}}|{{MACHINEPORT}}' entry
|
// - confirm place join with 'serverId: {{MACHINEADDRESS}}|{{MACHINEPORT}}' entry
|
||||||
// - check for leaves/disconnects with 'Client:Disconnect' entry
|
// - check for leaves/disconnects with 'Client:Disconnect' entry
|
||||||
//
|
//
|
||||||
// we'll read the log file from bottom-to-top and find which line meets the criteria
|
// we'll tail the log file continuously, monitoring for any log entries that we need to determine the current game activity
|
||||||
// the processes for reading and examining the log files are separated since the log may have to be examined multiple times
|
|
||||||
|
|
||||||
// read log file
|
string logDirectory = Path.Combine(Program.LocalAppData, "Roblox\\logs");
|
||||||
List<string> log = GetLog().ToList();
|
|
||||||
|
|
||||||
// and now let's get the current status from the log
|
if (!Directory.Exists(logDirectory))
|
||||||
await ExamineLog(log);
|
|
||||||
|
|
||||||
if (!loop)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await Task.Delay(ActivityInGame ? 30000 : 10000);
|
FileInfo logFileInfo = new DirectoryInfo(logDirectory).GetFiles().OrderByDescending(f => f.LastWriteTime).First();
|
||||||
MonitorGameActivity();
|
FileStream logFileStream = logFileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||||
|
|
||||||
|
AutoResetEvent logUpdatedEvent = new(false);
|
||||||
|
FileSystemWatcher logWatcher = new()
|
||||||
|
{
|
||||||
|
Path = logDirectory,
|
||||||
|
Filter = Path.GetFileName(logFileInfo.FullName),
|
||||||
|
EnableRaisingEvents = true
|
||||||
|
};
|
||||||
|
logWatcher.Changed += (s, e) => logUpdatedEvent.Set();
|
||||||
|
|
||||||
|
using (StreamReader sr = new(logFileStream))
|
||||||
|
{
|
||||||
|
string? log = null;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
log = await sr.ReadLineAsync();
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(log))
|
||||||
|
{
|
||||||
|
logUpdatedEvent.WaitOne(1000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Debug.WriteLine(log);
|
||||||
|
await ExamineLogEntry(log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no need to close the event, its going to be finished with when the program closes anyway
|
||||||
|
// ...rr im too lazy to fix the event still be updating when its closed... lol
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SetPresence()
|
public async Task<bool> SetPresence()
|
||||||
|
Loading…
Reference in New Issue
Block a user