diff --git a/CompatBot/Config.cs b/CompatBot/Config.cs index 906b2e56..06c23ee6 100644 --- a/CompatBot/Config.cs +++ b/CompatBot/Config.cs @@ -26,6 +26,7 @@ namespace CompatBot public static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30); public static readonly TimeSpan LogParsingTimeout = TimeSpan.FromSeconds(30); public static readonly TimeSpan BuildTimeDifferenceForOutdatedBuilds = TimeSpan.FromDays(3); + public static readonly TimeSpan ShutupTimeLimit = TimeSpan.FromMinutes(5); public static readonly Stopwatch Uptime = Stopwatch.StartNew(); // these settings could be configured either through `$ dotnet user-secrets`, or through environment variables (e.g. launchSettings.json, etc) @@ -99,6 +100,7 @@ namespace CompatBot public static readonly DiscordEmoji No = DiscordEmoji.FromUnicode("😐"); public static readonly DiscordEmoji PleaseWait = DiscordEmoji.FromUnicode("👀"); public static readonly DiscordEmoji PiracyCheck = DiscordEmoji.FromUnicode("🔨"); + public static readonly DiscordEmoji Shutup = DiscordEmoji.FromUnicode("🔇"); } public static class Moderation diff --git a/CompatBot/EventHandlers/BotReactionsHandler.cs b/CompatBot/EventHandlers/BotReactionsHandler.cs index 05d54d76..5dad109e 100644 --- a/CompatBot/EventHandlers/BotReactionsHandler.cs +++ b/CompatBot/EventHandlers/BotReactionsHandler.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; using CompatBot.Commands.Attributes; using CompatBot.Utils; @@ -150,7 +149,7 @@ namespace CompatBot.EventHandlers var botMember = args.Guild?.CurrentMember ?? args.Client.GetMember(args.Client.CurrentUser); if (args.Channel.PermissionsFor(botMember).HasPermission(Permissions.ReadMessageHistory)) { - var lastBotMessages = await args.Channel.GetMessagesBeforeAsync(args.Message.Id, 20, DateTime.UtcNow.AddMinutes(-5)).ConfigureAwait(false); + var lastBotMessages = await args.Channel.GetMessagesBeforeAsync(args.Message.Id, 20, DateTime.UtcNow.Add(-Config.ShutupTimeLimit)).ConfigureAwait(false); if (lastBotMessages.OrderByDescending(m => m.CreationTimestamp).FirstOrDefault(m => m.Author.IsCurrent) is DiscordMessage msg) await msg.DeleteAsync("asked to shut up").ConfigureAwait(false); } diff --git a/CompatBot/EventHandlers/LogParsing/LogParser.LogSections.cs b/CompatBot/EventHandlers/LogParsing/LogParser.LogSections.cs index ceabae32..3050fb8b 100644 --- a/CompatBot/EventHandlers/LogParsing/LogParser.LogSections.cs +++ b/CompatBot/EventHandlers/LogParsing/LogParser.LogSections.cs @@ -175,6 +175,7 @@ namespace CompatBot.EventHandlers.LogParsing ["PS3 firmware is not installed"] = new Regex(@"(?PS3 firmware is not installed.+)\r?$", DefaultOptions), ["do you have the PS3 firmware installed"] = new Regex(@"(?do you have the PS3 firmware installed.*)\r?$", DefaultOptions), ["Unimplemented syscall"] = new Regex(@"U \d+:\d+:\d+\.\d+ ({(?.+?)} )?.*(?Unimplemented syscall syscall_\d+ .*)\r?$", DefaultOptions), + ["Could not enqueue"] = new Regex(@"cellAudio: Could not enqueue buffer onto audio backend(?.).*\r?$", DefaultOptions), }, OnNewLineAsync = LimitedPiracyCheckAsync, OnSectionEnd = MarkAsCompleteAndReset, @@ -199,6 +200,8 @@ namespace CompatBot.EventHandlers.LogParsing "failed_to_verify", }; + public static readonly string[] CountValueItems = {"enqueue_buffer_error"}; + private static async Task PiracyCheckAsync(string line, LogParseState state) { if (await PiracyStringProvider.FindTriggerAsync(line).ConfigureAwait(false) is string match) diff --git a/CompatBot/EventHandlers/LogParsing/LogParser.StateMachineGenerator.cs b/CompatBot/EventHandlers/LogParsing/LogParser.StateMachineGenerator.cs index 0b1e0b0d..c8980ad3 100644 --- a/CompatBot/EventHandlers/LogParsing/LogParser.StateMachineGenerator.cs +++ b/CompatBot/EventHandlers/LogParsing/LogParser.StateMachineGenerator.cs @@ -65,6 +65,7 @@ namespace CompatBot.EventHandlers.LogParsing var strValue = group.Value.ToUtf8(); Config.Log.Debug($"regex {group.Name} = {group.Value}"); lock(state) + { if (MultiValueItems.Contains(group.Name)) { var currentValue = state.WipCollection[group.Name]; @@ -74,6 +75,12 @@ namespace CompatBot.EventHandlers.LogParsing } else state.WipCollection[group.Name] = strValue; + if (CountValueItems.Contains(group.Name)) + { + state.ValueHitStats.TryGetValue(group.Name, out var hits); + state.ValueHitStats[group.Name] = ++hits; + } + } } } diff --git a/CompatBot/EventHandlers/LogParsing/POCOs/LogParseState.cs b/CompatBot/EventHandlers/LogParsing/POCOs/LogParseState.cs index d6643d54..239a8653 100644 --- a/CompatBot/EventHandlers/LogParsing/POCOs/LogParseState.cs +++ b/CompatBot/EventHandlers/LogParsing/POCOs/LogParseState.cs @@ -8,6 +8,7 @@ namespace CompatBot.EventHandlers.LogParsing.POCOs { public NameValueCollection CompleteCollection = null; public NameValueCollection WipCollection = new NameValueCollection(); + public Dictionary ValueHitStats = new Dictionary(); public int Id = 0; public ErrorCode Error = ErrorCode.None; public string PiracyTrigger; diff --git a/CompatBot/EventHandlers/Starbucks.cs b/CompatBot/EventHandlers/Starbucks.cs index e81ab96b..bd7a0cbf 100644 --- a/CompatBot/EventHandlers/Starbucks.cs +++ b/CompatBot/EventHandlers/Starbucks.cs @@ -47,17 +47,18 @@ namespace CompatBot.EventHandlers [DiscordEmoji.FromUnicode("🇾")] = "Y", [DiscordEmoji.FromUnicode("🇿")] = "Z", - [DiscordEmoji.FromUnicode("0⃣️")] = "0", - [DiscordEmoji.FromUnicode("1️⃣")] = "1", - [DiscordEmoji.FromUnicode("2️⃣")] = "2", - [DiscordEmoji.FromUnicode("3️⃣")] = "3", - [DiscordEmoji.FromUnicode("4️⃣")] = "4", - [DiscordEmoji.FromUnicode("5️⃣")] = "5", - [DiscordEmoji.FromUnicode("6️⃣")] = "6", - [DiscordEmoji.FromUnicode("7️⃣")] = "7", - [DiscordEmoji.FromUnicode("8️⃣")] = "8", - [DiscordEmoji.FromUnicode("9️⃣")] = "9", + [DiscordEmoji.FromUnicode("0\u20E3")] = "0", + [DiscordEmoji.FromUnicode("1\u20E3")] = "1", + [DiscordEmoji.FromUnicode("2\u20E3")] = "2", + [DiscordEmoji.FromUnicode("3\u20E3")] = "3", + [DiscordEmoji.FromUnicode("4\u20E3")] = "4", + [DiscordEmoji.FromUnicode("5\u20E3")] = "5", + [DiscordEmoji.FromUnicode("6\u20E3")] = "6", + [DiscordEmoji.FromUnicode("7\u20E3")] = "7", + [DiscordEmoji.FromUnicode("8\u20E3")] = "8", + [DiscordEmoji.FromUnicode("9\u20E3")] = "9", [DiscordEmoji.FromUnicode("🔟")] = "10", + [DiscordEmoji.FromUnicode("💯")] = "100", [DiscordEmoji.FromUnicode("🆑")] = "CL", [DiscordEmoji.FromUnicode("🆐")] = "DJ", @@ -125,6 +126,8 @@ namespace CompatBot.EventHandlers message = await channel.GetMessageAsync(message.Id).ConfigureAwait(false); if (emoji == Config.Reactions.Starbucks) await CheckMediaTalkAsync(client, channel, message, emoji).ConfigureAwait(false); + if (emoji == Config.Reactions.Shutup) + await ShutupAsync(client, user, message).ConfigureAwait(false); await CheckGameFansAsync(client, channel, message).ConfigureAwait(false); } @@ -174,6 +177,22 @@ namespace CompatBot.EventHandlers await client.ReportAsync(Config.Reactions.Starbucks + " Media talk report", message, reporters, null, ReportSeverity.Medium).ConfigureAwait(false); } + + private static Task ShutupAsync(DiscordClient client, DiscordUser user, DiscordMessage message) + { + if (!message.Author.IsCurrent) + return Task.CompletedTask; + + if (message.CreationTimestamp.Add(Config.ShutupTimeLimit) < DateTime.UtcNow) + return Task.CompletedTask; + + if (!user.IsWhitelisted(client, message.Channel.Guild)) + return Task.CompletedTask; + + return message.DeleteAsync(); + } + + private static async Task CheckGameFansAsync(DiscordClient client, DiscordChannel channel, DiscordMessage message) { var bot = client.GetMember(channel.Guild, client.CurrentUser); diff --git a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs index da5cdc6f..3657ed5a 100644 --- a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs +++ b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs @@ -208,6 +208,16 @@ namespace CompatBot.Utils.ResultFormatters notes.Add("❌ Shader compilation error on unsupported GPU"); } + if (!string.IsNullOrEmpty(items["enqueue_buffer_error"]) + && state.ValueHitStats.TryGetValue("enqueue_buffer_error", out var enqueueBufferErrorCount) + && enqueueBufferErrorCount > 100) + { + if (items["os_type"] == "Windows") + notes.Add("⚠ Audio backend issues detected; it could be caused by a bad driver or 3rd party software"); + else + notes.Add("⚠ Audio backend issues detected; check for high audio driver/sink latency"); + } + var ppuPatches = GetPatches(items["ppu_hash"], items["ppu_hash_patch"]); var ovlPatches = GetPatches(items["ovl_hash"], items["ovl_hash_patch"]); var spuPatches = GetPatches(items["spu_hash"], items["spu_hash_patch"]); diff --git a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.WeirdSettingsSection.cs b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.WeirdSettingsSection.cs index 9e193bec..940883c6 100644 --- a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.WeirdSettingsSection.cs +++ b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.WeirdSettingsSection.cs @@ -123,8 +123,13 @@ namespace CompatBot.Utils.ResultFormatters notes.Add("⚠ `Audio backend` is set to `null`"); } - if (int.TryParse(items["audio_volume"], out var audioVolume) && audioVolume < 10) - notes.Add($"⚠ Audio volume is set to {audioVolume}%"); + if (int.TryParse(items["audio_volume"], out var audioVolume)) + { + if (audioVolume < 10) + notes.Add($"⚠ Audio volume is set to {audioVolume}%"); + else if (audioVolume > 100) + notes.Add($"⚠ Audio volume is set to {audioVolume}%; audio clipping is to be expected"); + } if (items["hle_lwmutex"] is string hleLwmutex && hleLwmutex == EnabledMark) notes.Add("⚠ `HLE lwmutex` is enabled, might affect compatibility");