mirror of
https://github.com/RPCS3/discord-bot.git
synced 2026-01-31 01:25:22 +01:00
RPCS3 Compatibility Bot reimplemented in C# for .NET Core Current status of this PR: * tested and targeted for .NET Core 2.1 * all functionality is either on par or improved compared to the python version * compatibility with current bot.db should be preserved in all upgrade scenarios * some bot management commands were changed (now under !sudo bot) * standard help generator for the new discord client is ... different; compatibility with old format could be restored through custom formatter if needed * everything has been split in more loosely tied components for easier extensibility and maintenance * log parsing has been rewritten and should work ~2x as fast
153 lines
8.1 KiB
C#
153 lines
8.1 KiB
C#
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using CompatBot.Providers;
|
|
|
|
namespace CompatBot.LogParsing
|
|
{
|
|
internal partial class LogParser
|
|
{
|
|
private const RegexOptions DefaultOptions = RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.ExplicitCapture;
|
|
|
|
/*
|
|
* Extractors are defined in terms of trigger-extractor
|
|
*
|
|
* Parser scans the log from section to section with a sliding window of up to 50 lines of text
|
|
* Triggers are scanned for in the first line of said sliding window
|
|
* If trigger is matched, then the associated reges will be run on THE WHOLE sliding window
|
|
* If any data was captured, it will be stored in the current collection of items with the key of the explicit capture group of regex
|
|
*
|
|
* Due to limitations, REGEX can't contain anything other than ASCII (triggers CAN however)
|
|
*
|
|
*/
|
|
private static readonly List<LogSection> LogSections = new List<LogSection>
|
|
{
|
|
new LogSection
|
|
{
|
|
Extractors = new Dictionary<string, Regex>
|
|
{
|
|
["RPCS3"] = new Regex(@"(?<build_and_specs>.*)\r?$", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture),
|
|
},
|
|
EndTrigger = "·",
|
|
},
|
|
new LogSection
|
|
{
|
|
Extractors = new Dictionary<string, Regex>
|
|
{
|
|
["Serial:"] = new Regex(@"Serial: (?<serial>[A-z]{4}\d{5})\r?$", DefaultOptions),
|
|
["Path:"] = new Regex(@"Path: ((?<win_path>\w:/)|(?<lin_path>/[^/])).*?\r?$", DefaultOptions),
|
|
["custom config:"] = new Regex("custom config: (?<custom_config>.*?)\r?$", DefaultOptions),
|
|
},
|
|
OnNewLineAsync = PiracyCheckAsync,
|
|
EndTrigger = "Core:",
|
|
},
|
|
new LogSection
|
|
{
|
|
Extractors = new Dictionary<string, Regex>
|
|
{
|
|
["PPU Decoder:"] = new Regex("PPU Decoder: (?<ppu_decoder>.*?)\r?$", DefaultOptions),
|
|
["PPU Threads:"] = new Regex("Threads: (?<ppu_threads>.*?)\r?$", DefaultOptions),
|
|
["thread scheduler:"] = new Regex("scheduler: (?<thread_scheduler>.*?)\r?$", DefaultOptions),
|
|
["SPU Decoder:"] = new Regex("SPU Decoder: (?<spu_decoder>.*?)\r?$", DefaultOptions),
|
|
["secondary cores:"] = new Regex("secondary cores: (?<spu_secondary_cores>.*?)\r?$", DefaultOptions),
|
|
["priority:"] = new Regex("priority: (?<spu_lower_thread_priority>.*?)\r?$", DefaultOptions),
|
|
["SPU Threads:"] = new Regex("SPU Threads: (?<spu_threads>.*?)\r?$", DefaultOptions),
|
|
["delay penalty:"] = new Regex("penalty: (?<spu_delay_penalty>.*?)\r?$", DefaultOptions),
|
|
["loop detection:"] = new Regex("detection: (?<spu_loop_detection>.*?)\r?$", DefaultOptions),
|
|
["Lib Loader:"] = new Regex("[Ll]oader: (?<lib_loader>.*?)\r?$", DefaultOptions),
|
|
["static functions:"] = new Regex("functions: (?<hook_static_functions>.*?)\r?$", DefaultOptions),
|
|
["Load libraries:"] = new Regex("libraries: (?<library_list>.*)", DefaultOptions),
|
|
},
|
|
EndTrigger = "VFS:",
|
|
},
|
|
new LogSection
|
|
{
|
|
EndTrigger = "Video:",
|
|
},
|
|
new LogSection
|
|
{
|
|
Extractors = new Dictionary<string, Regex>
|
|
{
|
|
["Renderer:"] = new Regex("Renderer: (?<renderer>.*?)\r?$", DefaultOptions),
|
|
["Resolution:"] = new Regex("Resolution: (?<resolution>.*?)\r?$", DefaultOptions),
|
|
["Aspect ratio:"] = new Regex("Aspect ratio: (?<aspect_ratio>.*?)\r?$", DefaultOptions),
|
|
["Frame limit:"] = new Regex("Frame limit: (?<frame_limit>.*?)\r?$", DefaultOptions),
|
|
["Write Color Buffers:"] = new Regex("Write Color Buffers: (?<write_color_buffers>.*?)\r?$", DefaultOptions),
|
|
["VSync:"] = new Regex("VSync: (?<vsync>.*?)\r?$", DefaultOptions),
|
|
["GPU texture scaling:"] = new Regex("Use GPU texture scaling: (?<gpu_texture_scaling>.*?)\r?$", DefaultOptions),
|
|
["Strict Rendering Mode:"] = new Regex("Strict Rendering Mode: (?<strict_rendering_mode>.*?)\r?$", DefaultOptions),
|
|
["Vertex Cache:"] = new Regex("Disable Vertex Cache: (?<vertex_cache>.*?)\r?$", DefaultOptions),
|
|
["Blit:"] = new Regex("Blit: (?<cpu_blit>.*?)\r?$", DefaultOptions),
|
|
["Resolution Scale:"] = new Regex("Resolution Scale: (?<resolution_scale>.*?)\r?$", DefaultOptions),
|
|
["Anisotropic Filter"] = new Regex("Anisotropic Filter Override: (?<af_override>.*?)\r?$", DefaultOptions),
|
|
["Scalable Dimension:"] = new Regex("Minimum Scalable Dimension: (?<texture_scale_threshold>.*?)\r?$", DefaultOptions),
|
|
["12:"] = new Regex(@"(D3D12|DirectX 12):\s*\r?\n\s*Adapter: (?<d3d_gpu>.*?)\r?$", DefaultOptions),
|
|
["Vulkan:"] = new Regex(@"Vulkan:\s*\r?\n\s*Adapter: (?<vulkan_gpu>.*?)\r?$", DefaultOptions),
|
|
},
|
|
EndTrigger = "Audio:",
|
|
},
|
|
new LogSection
|
|
{
|
|
EndTrigger = "Log:",
|
|
OnSectionEnd = MarkAsComplete,
|
|
},
|
|
new LogSection
|
|
{
|
|
Extractors = new Dictionary<string, Regex>
|
|
{
|
|
["RSX:"] = new Regex(@"RSX:(\d|\.|\s|\w|-)* (?<driver_version>(\d+\.)*\d+)\r?\n[^\n]*?" +
|
|
@"RSX: [^\n]+\r?\n[^\n]*?" +
|
|
@"RSX: (?<driver_manuf>.*?)\r?\n[^\n]*?" +
|
|
@"RSX: Supported texel buffer size", DefaultOptions),
|
|
["GL RENDERER:"] = new Regex(@"GL RENDERER: (?<driver_manuf_new>.*?)\r?\n", DefaultOptions),
|
|
["GL VERSION:"] = new Regex(@"GL VERSION:(\d|\.|\s|\w|-)* (?<driver_version_new>(\d+\.)*\d+)\r?\n", DefaultOptions),
|
|
["texel buffer size reported:"] = new Regex(@"RSX: Supported texel buffer size reported: (?<texel_buffer_size_new>\d*?) bytes", DefaultOptions),
|
|
["·F "] = new Regex(@"F \d+:\d+:\d+\.\d+ {.+?} (?<fatal_error>.*?)\r?$", DefaultOptions),
|
|
},
|
|
OnSectionEnd = MarkAsCompleteAndReset,
|
|
EndTrigger = "Objects cleared...",
|
|
}
|
|
};
|
|
|
|
private static async Task PiracyCheckAsync(string line, LogParseState state)
|
|
{
|
|
if (await PiracyStringProvider.FindTriggerAsync(line).ConfigureAwait(false) is string match)
|
|
{
|
|
state.PiracyTrigger = match;
|
|
state.PiracyContext = Utf8.GetString(Encoding.ASCII.GetBytes(line));
|
|
state.Error = LogParseState.ErrorCode.PiracyDetected;
|
|
}
|
|
}
|
|
|
|
private static void ClearResults(LogParseState state)
|
|
{
|
|
void Copy(params string[] keys)
|
|
{
|
|
foreach (var key in keys)
|
|
if (state.CompleteCollection?[key] is string value)
|
|
state.WipCollection[key] = value;
|
|
}
|
|
state.WipCollection = new NameValueCollection();
|
|
Copy(
|
|
"build_and_specs",
|
|
"vulkan_gpu", "d3d_gpu",
|
|
"driver_version", "driver_manuf",
|
|
"driver_manuf_new", "driver_version_new"
|
|
);
|
|
}
|
|
|
|
private static void MarkAsComplete(LogParseState state)
|
|
{
|
|
state.CompleteCollection = state.WipCollection;
|
|
}
|
|
|
|
private static void MarkAsCompleteAndReset(LogParseState state)
|
|
{
|
|
MarkAsComplete(state);
|
|
ClearResults(state);
|
|
state.Id = -1;
|
|
}
|
|
}
|
|
} |